From ca8805933bd0026dc0f35c683cab6413ef0b90ca Mon Sep 17 00:00:00 2001 From: Eirikr Hinngart <151315375+Oichkatzelesfrettschen@users.noreply.github.com> Date: Fri, 30 May 2025 23:27:30 -0700 Subject: [PATCH] Remove NetBSD references from bin --- bin/cat/Makefile | 6 - bin/cat/cat.1 | 218 --- bin/cat/cat.c | 321 ---- bin/chmod/Makefile | 6 - bin/chmod/chmod.1 | 315 --- bin/chmod/chmod.c | 239 --- bin/csh/Makefile | 72 - bin/csh/USD.doc/Makefile | 12 - bin/csh/USD.doc/csh.1 | 1010 ---------- bin/csh/USD.doc/csh.2 | 1303 ------------- bin/csh/USD.doc/csh.3 | 648 ------- bin/csh/USD.doc/csh.4 | 176 -- bin/csh/USD.doc/csh.ap | 93 - bin/csh/USD.doc/csh.g | 1719 ----------------- bin/csh/USD.doc/tabs | 32 - bin/csh/alloc.c | 91 - bin/csh/char.c | 315 --- bin/csh/char.h | 100 - bin/csh/const.c | 164 -- bin/csh/csh.1 | 2293 ---------------------- bin/csh/csh.c | 1401 -------------- bin/csh/csh.h | 559 ------ bin/csh/dir.c | 901 --------- bin/csh/dir.h | 48 - bin/csh/dol.c | 968 ---------- bin/csh/err.c | 388 ---- bin/csh/exec.c | 746 -------- bin/csh/exp.c | 661 ------- bin/csh/extern.h | 341 ---- bin/csh/file.c | 729 ------- bin/csh/func.c | 1456 -------------- bin/csh/glob.c | 923 --------- bin/csh/hist.c | 207 -- bin/csh/init.c | 131 -- bin/csh/lex.c | 1631 ---------------- bin/csh/misc.c | 407 ---- bin/csh/parse.c | 640 ------- bin/csh/pathnames.h | 44 - bin/csh/proc.c | 1359 ------------- bin/csh/proc.h | 104 - bin/csh/sem.c | 646 ------- bin/csh/set.c | 820 -------- bin/csh/str.c | 441 ----- bin/csh/time.c | 285 --- bin/dd/Makefile | 22 - bin/dd/conv.c | 283 --- bin/dd/conv_tab.c | 287 --- bin/dd/dd.1 | 522 ----- bin/dd/dd.c | 616 ------ bin/dd/dd.h | 126 -- bin/dd/dd_hostops.c | 53 - bin/dd/dd_rumpops.c | 52 - bin/dd/extern.h | 86 - bin/dd/misc.c | 342 ---- bin/dd/position.c | 185 -- bin/df/Makefile | 11 - bin/df/df.1 | 206 -- bin/df/df.c | 520 ----- bin/domainname/Makefile | 6 - bin/domainname/domainname.1 | 65 - bin/domainname/domainname.c | 95 - bin/ed/Makefile | 17 - bin/ed/POSIX | 103 - bin/ed/buf.c | 319 --- bin/ed/cbc.c | 460 ----- bin/ed/ed.1 | 979 ---------- bin/ed/ed.h | 294 --- bin/ed/glbl.c | 227 --- bin/ed/io.c | 358 ---- bin/ed/main.c | 1433 -------------- bin/ed/re.c | 146 -- bin/ed/sub.c | 262 --- bin/ed/test/Makefile | 28 - bin/ed/test/TODO | 17 - bin/ed/test/ckscripts.sh | 37 - bin/ed/test/mkscripts.sh | 75 - bin/ed/undo.c | 158 -- bin/expr/Makefile | 6 - bin/expr/expr.1 | 280 --- bin/expr/expr.y | 457 ----- bin/hostname/Makefile | 6 - bin/hostname/hostname.1 | 65 - bin/hostname/hostname.c | 101 - bin/kill/Makefile | 6 - bin/kill/kill.1 | 156 -- bin/kill/kill.c | 253 --- bin/ksh/Makefile | 51 - bin/ksh/alloc.c | 127 -- bin/ksh/c_ksh.c | 1490 -------------- bin/ksh/c_sh.c | 919 --------- bin/ksh/c_test.c | 666 ------- bin/ksh/c_test.h | 55 - bin/ksh/c_ulimit.c | 292 --- bin/ksh/conf-end.h | 57 - bin/ksh/config.h | 365 ---- bin/ksh/edit.c | 1095 ----------- bin/ksh/edit.h | 87 - bin/ksh/emacs-gen.sh | 47 - bin/ksh/emacs.c | 2221 --------------------- bin/ksh/eval.c | 1403 -------------- bin/ksh/exec.c | 1749 ----------------- bin/ksh/expand.h | 109 -- bin/ksh/expr.c | 613 ------ bin/ksh/history.c | 1225 ------------ bin/ksh/io.c | 568 ------ bin/ksh/jobs.c | 1858 ------------------ bin/ksh/ksh.Man | 3620 ----------------------------------- bin/ksh/ksh_dir.h | 27 - bin/ksh/ksh_limval.h | 25 - bin/ksh/ksh_stat.h | 60 - bin/ksh/ksh_time.h | 27 - bin/ksh/ksh_times.h | 20 - bin/ksh/ksh_wait.h | 52 - bin/ksh/lex.c | 1398 -------------- bin/ksh/lex.h | 133 -- bin/ksh/mail.c | 202 -- bin/ksh/main.c | 869 --------- bin/ksh/misc.c | 1364 ------------- bin/ksh/path.c | 318 --- bin/ksh/proto.h | 298 --- bin/ksh/sh.h | 735 ------- bin/ksh/shf.c | 1302 ------------- bin/ksh/shf.h | 87 - bin/ksh/sigact.c | 486 ----- bin/ksh/sigact.h | 125 -- bin/ksh/siglist.in | 56 - bin/ksh/siglist.sh | 44 - bin/ksh/syn.c | 958 --------- bin/ksh/table.c | 247 --- bin/ksh/table.h | 181 -- bin/ksh/trap.c | 460 ----- bin/ksh/tree.c | 766 -------- bin/ksh/tree.h | 142 -- bin/ksh/tty.c | 187 -- bin/ksh/tty.h | 110 -- bin/ksh/var.c | 1260 ------------ bin/ksh/version.c | 16 - bin/ksh/vi.c | 2203 --------------------- bin/ln/Makefile | 7 - bin/ln/ln.1 | 173 -- bin/ln/ln.c | 230 --- bin/ls/Makefile | 10 - bin/ls/cmp.c | 199 -- bin/ls/extern.h | 53 - bin/ls/ls.1 | 516 ----- bin/ls/ls.c | 715 ------- bin/ls/ls.h | 81 - bin/ls/main.c | 50 - bin/ls/print.c | 497 ----- bin/ls/util.c | 168 -- bin/mv/Makefile | 6 - bin/mv/mv.1 | 151 -- bin/mv/mv.c | 409 ---- bin/mv/pathnames.h | 40 - bin/ps/Makefile | 12 - bin/ps/extern.h | 99 - bin/ps/fmt.c | 60 - bin/ps/keyword.c | 419 ---- bin/ps/nlist.c | 207 -- bin/ps/print.c | 1483 -------------- bin/ps/ps.1 | 708 ------- bin/ps/ps.c | 783 -------- bin/ps/ps.h | 96 - bin/rcmd/Makefile | 15 - bin/rcmd/rcmd.1 | 199 -- bin/rcp/Makefile | 11 - bin/rcp/extern.h | 49 - bin/rcp/pathnames.h | 42 - bin/rcp/rcp.1 | 172 -- bin/rcp/rcp.c | 813 -------- bin/rcp/util.c | 184 -- bin/rm/Makefile | 6 - bin/rm/rm.1 | 215 --- bin/rm/rm.c | 635 ------ bin/rmdir/Makefile | 6 - bin/rmdir/rmdir.1 | 95 - bin/rmdir/rmdir.c | 125 -- bin/sh/Makefile | 91 - bin/sh/TOUR | 357 ---- bin/sh/USD.doc/Makefile | 12 - bin/sh/USD.doc/referargs | 8 - bin/sh/USD.doc/t.mac | 69 - bin/sh/USD.doc/t1 | 553 ------ bin/sh/USD.doc/t2 | 971 ---------- bin/sh/USD.doc/t3 | 976 ---------- bin/sh/USD.doc/t4 | 180 -- bin/sh/alias.c | 275 --- bin/sh/alias.h | 48 - bin/sh/arith.y | 206 -- bin/sh/arith_lex.l | 103 - bin/sh/bltin/bltin.h | 100 - bin/sh/bltin/echo.1 | 109 -- bin/sh/bltin/echo.c | 122 -- bin/sh/builtins.def | 93 - bin/sh/cd.c | 464 ----- bin/sh/cd.h | 34 - bin/sh/error.c | 370 ---- bin/sh/error.h | 119 -- bin/sh/eval.c | 1366 ------------- bin/sh/eval.h | 73 - bin/sh/exec.c | 1071 ----------- bin/sh/exec.h | 76 - bin/sh/expand.c | 1640 ---------------- bin/sh/expand.h | 73 - bin/sh/funcs/cmv | 50 - bin/sh/funcs/dirs | 74 - bin/sh/funcs/kill | 50 - bin/sh/funcs/login | 39 - bin/sh/funcs/newgrp | 38 - bin/sh/funcs/popd | 74 - bin/sh/funcs/pushd | 74 - bin/sh/funcs/suspend | 42 - bin/sh/histedit.c | 549 ------ bin/sh/init.h | 39 - bin/sh/input.c | 550 ------ bin/sh/input.h | 62 - bin/sh/jobs.c | 1532 --------------- bin/sh/jobs.h | 101 - bin/sh/machdep.h | 47 - bin/sh/mail.c | 120 -- bin/sh/mail.h | 37 - bin/sh/main.c | 376 ---- bin/sh/main.h | 41 - bin/sh/memalloc.c | 307 --- bin/sh/memalloc.h | 77 - bin/sh/miscbltin.c | 458 ----- bin/sh/miscbltin.h | 31 - bin/sh/mkbuiltins | 136 -- bin/sh/mkinit.sh | 170 -- bin/sh/mknodes.sh | 214 --- bin/sh/mktokens | 95 - bin/sh/myhistedit.h | 46 - bin/sh/mystring.c | 133 -- bin/sh/mystring.h | 45 - bin/sh/nodes.c.pat | 159 -- bin/sh/nodetypes | 143 -- bin/sh/options.c | 543 ------ bin/sh/options.h | 134 -- bin/sh/output.c | 556 ------ bin/sh/output.h | 84 - bin/sh/parser.c | 1686 ---------------- bin/sh/parser.h | 84 - bin/sh/redir.c | 400 ---- bin/sh/redir.h | 48 - bin/sh/sh.1 | 2047 -------------------- bin/sh/shell.h | 89 - bin/sh/show.c | 430 ----- bin/sh/show.h | 45 - bin/sh/syntax.c | 105 - bin/sh/syntax.h | 83 - bin/sh/trap.c | 484 ----- bin/sh/trap.h | 46 - bin/sh/var.c | 844 -------- bin/sh/var.h | 130 -- bin/sleep/Makefile | 8 - bin/sleep/sleep.1 | 128 -- bin/sleep/sleep.c | 159 -- bin/stty/Makefile | 9 - bin/stty/cchar.c | 148 -- bin/stty/extern.h | 51 - bin/stty/gfmt.c | 132 -- bin/stty/key.c | 332 ---- bin/stty/modes.c | 224 --- bin/stty/print.c | 257 --- bin/stty/stty.1 | 640 ------- bin/stty/stty.c | 168 -- bin/stty/stty.h | 62 - bin/sync/Makefile | 7 - bin/sync/sync.8 | 72 - bin/sync/sync.c | 57 - bin/test/Makefile | 9 - bin/test/TEST.csh | 138 -- bin/test/test.1 | 330 ---- bin/test/test.c | 717 ------- 274 files changed, 104157 deletions(-) delete mode 100644 bin/cat/Makefile delete mode 100644 bin/cat/cat.1 delete mode 100644 bin/cat/cat.c delete mode 100644 bin/chmod/Makefile delete mode 100644 bin/chmod/chmod.1 delete mode 100644 bin/chmod/chmod.c delete mode 100644 bin/csh/Makefile delete mode 100644 bin/csh/USD.doc/Makefile delete mode 100644 bin/csh/USD.doc/csh.1 delete mode 100644 bin/csh/USD.doc/csh.2 delete mode 100644 bin/csh/USD.doc/csh.3 delete mode 100644 bin/csh/USD.doc/csh.4 delete mode 100644 bin/csh/USD.doc/csh.ap delete mode 100644 bin/csh/USD.doc/csh.g delete mode 100644 bin/csh/USD.doc/tabs delete mode 100644 bin/csh/alloc.c delete mode 100644 bin/csh/char.c delete mode 100644 bin/csh/char.h delete mode 100644 bin/csh/const.c delete mode 100644 bin/csh/csh.1 delete mode 100644 bin/csh/csh.c delete mode 100644 bin/csh/csh.h delete mode 100644 bin/csh/dir.c delete mode 100644 bin/csh/dir.h delete mode 100644 bin/csh/dol.c delete mode 100644 bin/csh/err.c delete mode 100644 bin/csh/exec.c delete mode 100644 bin/csh/exp.c delete mode 100644 bin/csh/extern.h delete mode 100644 bin/csh/file.c delete mode 100644 bin/csh/func.c delete mode 100644 bin/csh/glob.c delete mode 100644 bin/csh/hist.c delete mode 100644 bin/csh/init.c delete mode 100644 bin/csh/lex.c delete mode 100644 bin/csh/misc.c delete mode 100644 bin/csh/parse.c delete mode 100644 bin/csh/pathnames.h delete mode 100644 bin/csh/proc.c delete mode 100644 bin/csh/proc.h delete mode 100644 bin/csh/sem.c delete mode 100644 bin/csh/set.c delete mode 100644 bin/csh/str.c delete mode 100644 bin/csh/time.c delete mode 100644 bin/dd/Makefile delete mode 100644 bin/dd/conv.c delete mode 100644 bin/dd/conv_tab.c delete mode 100644 bin/dd/dd.1 delete mode 100644 bin/dd/dd.c delete mode 100644 bin/dd/dd.h delete mode 100644 bin/dd/dd_hostops.c delete mode 100644 bin/dd/dd_rumpops.c delete mode 100644 bin/dd/extern.h delete mode 100644 bin/dd/misc.c delete mode 100644 bin/dd/position.c delete mode 100644 bin/df/Makefile delete mode 100644 bin/df/df.1 delete mode 100644 bin/df/df.c delete mode 100644 bin/domainname/Makefile delete mode 100644 bin/domainname/domainname.1 delete mode 100644 bin/domainname/domainname.c delete mode 100644 bin/ed/Makefile delete mode 100644 bin/ed/POSIX delete mode 100644 bin/ed/buf.c delete mode 100644 bin/ed/cbc.c delete mode 100644 bin/ed/ed.1 delete mode 100644 bin/ed/ed.h delete mode 100644 bin/ed/glbl.c delete mode 100644 bin/ed/io.c delete mode 100644 bin/ed/main.c delete mode 100644 bin/ed/re.c delete mode 100644 bin/ed/sub.c delete mode 100644 bin/ed/test/Makefile delete mode 100644 bin/ed/test/TODO delete mode 100755 bin/ed/test/ckscripts.sh delete mode 100755 bin/ed/test/mkscripts.sh delete mode 100644 bin/ed/undo.c delete mode 100644 bin/expr/Makefile delete mode 100644 bin/expr/expr.1 delete mode 100644 bin/expr/expr.y delete mode 100644 bin/hostname/Makefile delete mode 100644 bin/hostname/hostname.1 delete mode 100644 bin/hostname/hostname.c delete mode 100644 bin/kill/Makefile delete mode 100644 bin/kill/kill.1 delete mode 100644 bin/kill/kill.c delete mode 100644 bin/ksh/Makefile delete mode 100644 bin/ksh/alloc.c delete mode 100644 bin/ksh/c_ksh.c delete mode 100644 bin/ksh/c_sh.c delete mode 100644 bin/ksh/c_test.c delete mode 100644 bin/ksh/c_test.h delete mode 100644 bin/ksh/c_ulimit.c delete mode 100644 bin/ksh/conf-end.h delete mode 100644 bin/ksh/config.h delete mode 100644 bin/ksh/edit.c delete mode 100644 bin/ksh/edit.h delete mode 100755 bin/ksh/emacs-gen.sh delete mode 100644 bin/ksh/emacs.c delete mode 100644 bin/ksh/eval.c delete mode 100644 bin/ksh/exec.c delete mode 100644 bin/ksh/expand.h delete mode 100644 bin/ksh/expr.c delete mode 100644 bin/ksh/history.c delete mode 100644 bin/ksh/io.c delete mode 100644 bin/ksh/jobs.c delete mode 100644 bin/ksh/ksh.Man delete mode 100644 bin/ksh/ksh_dir.h delete mode 100644 bin/ksh/ksh_limval.h delete mode 100644 bin/ksh/ksh_stat.h delete mode 100644 bin/ksh/ksh_time.h delete mode 100644 bin/ksh/ksh_times.h delete mode 100644 bin/ksh/ksh_wait.h delete mode 100644 bin/ksh/lex.c delete mode 100644 bin/ksh/lex.h delete mode 100644 bin/ksh/mail.c delete mode 100644 bin/ksh/main.c delete mode 100644 bin/ksh/misc.c delete mode 100644 bin/ksh/path.c delete mode 100644 bin/ksh/proto.h delete mode 100644 bin/ksh/sh.h delete mode 100644 bin/ksh/shf.c delete mode 100644 bin/ksh/shf.h delete mode 100644 bin/ksh/sigact.c delete mode 100644 bin/ksh/sigact.h delete mode 100644 bin/ksh/siglist.in delete mode 100755 bin/ksh/siglist.sh delete mode 100644 bin/ksh/syn.c delete mode 100644 bin/ksh/table.c delete mode 100644 bin/ksh/table.h delete mode 100644 bin/ksh/trap.c delete mode 100644 bin/ksh/tree.c delete mode 100644 bin/ksh/tree.h delete mode 100644 bin/ksh/tty.c delete mode 100644 bin/ksh/tty.h delete mode 100644 bin/ksh/var.c delete mode 100644 bin/ksh/version.c delete mode 100644 bin/ksh/vi.c delete mode 100644 bin/ln/Makefile delete mode 100644 bin/ln/ln.1 delete mode 100644 bin/ln/ln.c delete mode 100644 bin/ls/Makefile delete mode 100644 bin/ls/cmp.c delete mode 100644 bin/ls/extern.h delete mode 100644 bin/ls/ls.1 delete mode 100644 bin/ls/ls.c delete mode 100644 bin/ls/ls.h delete mode 100644 bin/ls/main.c delete mode 100644 bin/ls/print.c delete mode 100644 bin/ls/util.c delete mode 100644 bin/mv/Makefile delete mode 100644 bin/mv/mv.1 delete mode 100644 bin/mv/mv.c delete mode 100644 bin/mv/pathnames.h delete mode 100644 bin/ps/Makefile delete mode 100644 bin/ps/extern.h delete mode 100644 bin/ps/fmt.c delete mode 100644 bin/ps/keyword.c delete mode 100644 bin/ps/nlist.c delete mode 100644 bin/ps/print.c delete mode 100644 bin/ps/ps.1 delete mode 100644 bin/ps/ps.c delete mode 100644 bin/ps/ps.h delete mode 100644 bin/rcmd/Makefile delete mode 100644 bin/rcmd/rcmd.1 delete mode 100644 bin/rcp/Makefile delete mode 100644 bin/rcp/extern.h delete mode 100644 bin/rcp/pathnames.h delete mode 100644 bin/rcp/rcp.1 delete mode 100644 bin/rcp/rcp.c delete mode 100644 bin/rcp/util.c delete mode 100644 bin/rm/Makefile delete mode 100644 bin/rm/rm.1 delete mode 100644 bin/rm/rm.c delete mode 100644 bin/rmdir/Makefile delete mode 100644 bin/rmdir/rmdir.1 delete mode 100644 bin/rmdir/rmdir.c delete mode 100644 bin/sh/Makefile delete mode 100644 bin/sh/TOUR delete mode 100644 bin/sh/USD.doc/Makefile delete mode 100644 bin/sh/USD.doc/referargs delete mode 100644 bin/sh/USD.doc/t.mac delete mode 100644 bin/sh/USD.doc/t1 delete mode 100644 bin/sh/USD.doc/t2 delete mode 100644 bin/sh/USD.doc/t3 delete mode 100644 bin/sh/USD.doc/t4 delete mode 100644 bin/sh/alias.c delete mode 100644 bin/sh/alias.h delete mode 100644 bin/sh/arith.y delete mode 100644 bin/sh/arith_lex.l delete mode 100644 bin/sh/bltin/bltin.h delete mode 100644 bin/sh/bltin/echo.1 delete mode 100644 bin/sh/bltin/echo.c delete mode 100644 bin/sh/builtins.def delete mode 100644 bin/sh/cd.c delete mode 100644 bin/sh/cd.h delete mode 100644 bin/sh/error.c delete mode 100644 bin/sh/error.h delete mode 100644 bin/sh/eval.c delete mode 100644 bin/sh/eval.h delete mode 100644 bin/sh/exec.c delete mode 100644 bin/sh/exec.h delete mode 100644 bin/sh/expand.c delete mode 100644 bin/sh/expand.h delete mode 100644 bin/sh/funcs/cmv delete mode 100644 bin/sh/funcs/dirs delete mode 100644 bin/sh/funcs/kill delete mode 100644 bin/sh/funcs/login delete mode 100644 bin/sh/funcs/newgrp delete mode 100644 bin/sh/funcs/popd delete mode 100644 bin/sh/funcs/pushd delete mode 100644 bin/sh/funcs/suspend delete mode 100644 bin/sh/histedit.c delete mode 100644 bin/sh/init.h delete mode 100644 bin/sh/input.c delete mode 100644 bin/sh/input.h delete mode 100644 bin/sh/jobs.c delete mode 100644 bin/sh/jobs.h delete mode 100644 bin/sh/machdep.h delete mode 100644 bin/sh/mail.c delete mode 100644 bin/sh/mail.h delete mode 100644 bin/sh/main.c delete mode 100644 bin/sh/main.h delete mode 100644 bin/sh/memalloc.c delete mode 100644 bin/sh/memalloc.h delete mode 100644 bin/sh/miscbltin.c delete mode 100644 bin/sh/miscbltin.h delete mode 100644 bin/sh/mkbuiltins delete mode 100755 bin/sh/mkinit.sh delete mode 100755 bin/sh/mknodes.sh delete mode 100644 bin/sh/mktokens delete mode 100644 bin/sh/myhistedit.h delete mode 100644 bin/sh/mystring.c delete mode 100644 bin/sh/mystring.h delete mode 100644 bin/sh/nodes.c.pat delete mode 100644 bin/sh/nodetypes delete mode 100644 bin/sh/options.c delete mode 100644 bin/sh/options.h delete mode 100644 bin/sh/output.c delete mode 100644 bin/sh/output.h delete mode 100644 bin/sh/parser.c delete mode 100644 bin/sh/parser.h delete mode 100644 bin/sh/redir.c delete mode 100644 bin/sh/redir.h delete mode 100644 bin/sh/sh.1 delete mode 100644 bin/sh/shell.h delete mode 100644 bin/sh/show.c delete mode 100644 bin/sh/show.h delete mode 100644 bin/sh/syntax.c delete mode 100644 bin/sh/syntax.h delete mode 100644 bin/sh/trap.c delete mode 100644 bin/sh/trap.h delete mode 100644 bin/sh/var.c delete mode 100644 bin/sh/var.h delete mode 100644 bin/sleep/Makefile delete mode 100644 bin/sleep/sleep.1 delete mode 100644 bin/sleep/sleep.c delete mode 100644 bin/stty/Makefile delete mode 100644 bin/stty/cchar.c delete mode 100644 bin/stty/extern.h delete mode 100644 bin/stty/gfmt.c delete mode 100644 bin/stty/key.c delete mode 100644 bin/stty/modes.c delete mode 100644 bin/stty/print.c delete mode 100644 bin/stty/stty.1 delete mode 100644 bin/stty/stty.c delete mode 100644 bin/stty/stty.h delete mode 100644 bin/sync/Makefile delete mode 100644 bin/sync/sync.8 delete mode 100644 bin/sync/sync.c delete mode 100644 bin/test/Makefile delete mode 100644 bin/test/TEST.csh delete mode 100644 bin/test/test.1 delete mode 100644 bin/test/test.c diff --git a/bin/cat/Makefile b/bin/cat/Makefile deleted file mode 100644 index d46aa3810..000000000 --- a/bin/cat/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# $NetBSD: Makefile,v 1.12 2003/05/18 07:57:31 lukem Exp $ -# @(#)Makefile 8.1 (Berkeley) 5/31/93 - -PROG= cat - -.include diff --git a/bin/cat/cat.1 b/bin/cat/cat.1 deleted file mode 100644 index 2873f5e61..000000000 --- a/bin/cat/cat.1 +++ /dev/null @@ -1,218 +0,0 @@ -.\" $NetBSD: cat.1,v 1.38 2014/06/15 07:27:22 wiz Exp $ -.\" -.\" Copyright (c) 1989, 1990, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Institute of Electrical and Electronics Engineers, Inc. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)cat.1 8.3 (Berkeley) 5/2/95 -.\" -.Dd June 15, 2014 -.Dt CAT 1 -.Os -.Sh NAME -.Nm cat -.Nd concatenate and print files -.Sh SYNOPSIS -.Nm -.Op Fl beflnstuv -.Op Fl B Ar bsize -.Op Fl -.Op Ar -.Sh DESCRIPTION -The -.Nm -utility reads files sequentially, writing them to the standard output. -The -.Ar file -operands are processed in command line order. -A single dash represents the standard input, -and may appear multiple times in the -.Ar file -list. -If no -.Ar file -operands are given, standard input is read. -.Pp -The word -.Dq concatenate -is just a verbose synonym for -.Dq catenate . -.Pp -The options are as follows: -.Bl -tag -width Ds -.It Fl B Ar bsize -Read with a buffer size of -.Ar bsize -bytes, instead of the default buffer size which is the blocksize of the -output file. -.It Fl b -Implies the -.Fl n -option, but doesn't number blank lines. -.It Fl e -Implies the -.Fl v -option, and displays a dollar sign -.Pq Ql \&$ -at the end of each line -as well. -.It Fl f -Only attempt to display regular files. -.It Fl l -Set an exclusive advisory lock on the standard output file descriptor. -This lock is set using -.Xr fcntl 2 -with the -.Dv F_SETLKW -command. -If the output file is already locked, -.Nm -will block until the lock is acquired. -.It Fl n -Number the output lines, starting at 1. -.It Fl s -Squeeze multiple adjacent empty lines, causing the output to be -single spaced. -.It Fl t -Implies the -.Fl v -option, and displays tab characters as -.Ql ^I -as well. -.It Fl u -The -.Fl u -option guarantees that the output is unbuffered. -.It Fl v -Displays non-printing characters so they are visible. -Control characters print as -.Ql ^X -for control-X; the delete -character (octal 0177) prints as -.Ql ^? . -Non-ascii characters (with the high bit set) are printed as -.Ql M- -(for meta) followed by the character for the low 7 bits. -.El -.Sh EXIT STATUS -The -.Nm -utility exits 0 on success, and \*[Gt]0 if an error occurs. -.Sh EXAMPLES -The command: -.Bd -literal -offset indent -.Ic cat file1 -.Ed -.Pp -will print the contents of -.Ar file1 -to the standard output. -.Pp -The command: -.Bd -literal -offset indent -.Ic cat file1 file2 \*[Gt] file3 -.Ed -.Pp -will sequentially print the contents of -.Ar file1 -and -.Ar file2 -to the file -.Ar file3 , -truncating -.Ar file3 -if it already exists. -See the manual page for your shell (e.g., -.Xr sh 1 ) -for more information on redirection. -.Pp -The command: -.Bd -literal -offset indent -.Ic cat file1 - file2 - file3 -.Ed -.Pp -will print the contents of -.Ar file1 , -print data it receives from the standard input until it receives an -.Dv EOF -.Pq Sq ^D -character, print the contents of -.Ar file2 , -read and output contents of the standard input again, then finally output -the contents of -.Ar file3 . -Note that if the standard input referred to a file, the second dash -on the command-line would have no effect, since the entire contents of the file -would have already been read and printed by -.Nm -when it encountered the first -.Ql \&- -operand. -.Sh SEE ALSO -.Xr head 1 , -.Xr hexdump 1 , -.Xr lpr 1 , -.Xr more 1 , -.Xr pr 1 , -.Xr tail 1 , -.Xr view 1 , -.Xr vis 1 , -.Xr fcntl 2 -.Rs -.%A Rob Pike -.%T "UNIX Style, or cat -v Considered Harmful" -.%J "USENIX Summer Conference Proceedings" -.%D 1983 -.Re -.Sh STANDARDS -The -.Nm -utility is expected to conform to the -.St -p1003.2-92 -specification. -.Pp -The flags -.Op Fl Bbeflnstv -are extensions to the specification. -.Sh HISTORY -A -.Nm -utility appeared in -.At v1 . -Dennis Ritchie designed and wrote the first man page. -It appears to have been -.Xr cat 1 . -.Sh BUGS -Because of the shell language mechanism used to perform output -redirection, the command -.Dq Li cat file1 file2 \*[Gt] file1 -will cause the original data in file1 to be destroyed! -This is performed by the shell before -.Nm -is run. diff --git a/bin/cat/cat.c b/bin/cat/cat.c deleted file mode 100644 index 563ba6388..000000000 --- a/bin/cat/cat.c +++ /dev/null @@ -1,321 +0,0 @@ -/* $NetBSD: cat.c,v 1.57 2016/06/16 00:52:37 sevan Exp $ */ - -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kevin Fall. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if HAVE_NBTOOL_CONFIG_H -#include "nbtool_config.h" -#endif - -#include -#if !defined(lint) -__COPYRIGHT( -"@(#) Copyright (c) 1989, 1993\ - The Regents of the University of California. All rights reserved."); -#if 0 -static char sccsid[] = "@(#)cat.c 8.2 (Berkeley) 4/27/95"; -#else -__RCSID("$NetBSD: cat.c,v 1.57 2016/06/16 00:52:37 sevan Exp $"); -#endif -#endif /* not lint */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int bflag, eflag, fflag, lflag, nflag, sflag, tflag, vflag; -static size_t bsize; -static int rval; -static const char *filename; - -void cook_args(char *argv[]); -void cook_buf(FILE *); -void raw_args(char *argv[]); -void raw_cat(int); - -int -main(int argc, char *argv[]) -{ - int ch; - struct flock stdout_lock; - - setprogname(argv[0]); - (void)setlocale(LC_ALL, ""); - - while ((ch = getopt(argc, argv, "B:beflnstuv")) != -1) - switch (ch) { - case 'B': - bsize = (size_t)strtol(optarg, NULL, 0); - break; - case 'b': - bflag = nflag = 1; /* -b implies -n */ - break; - case 'e': - eflag = vflag = 1; /* -e implies -v */ - break; - case 'f': - fflag = 1; - break; - case 'l': - lflag = 1; - break; - case 'n': - nflag = 1; - break; - case 's': - sflag = 1; - break; - case 't': - tflag = vflag = 1; /* -t implies -v */ - break; - case 'u': - setbuf(stdout, NULL); - break; - case 'v': - vflag = 1; - break; - default: - case '?': - (void)fprintf(stderr, - "Usage: %s [-beflnstuv] [-B bsize] [-] " - "[file ...]\n", getprogname()); - return EXIT_FAILURE; - } - argv += optind; - - if (lflag) { - stdout_lock.l_len = 0; - stdout_lock.l_start = 0; - stdout_lock.l_type = F_WRLCK; - stdout_lock.l_whence = SEEK_SET; - if (fcntl(STDOUT_FILENO, F_SETLKW, &stdout_lock) == -1) - err(EXIT_FAILURE, "stdout"); - } - - if (bflag || eflag || nflag || sflag || tflag || vflag) - cook_args(argv); - else - raw_args(argv); - if (fclose(stdout)) - err(EXIT_FAILURE, "stdout"); - return rval; -} - -void -cook_args(char **argv) -{ - FILE *fp; - - fp = stdin; - filename = "stdin"; - do { - if (*argv) { - if (!strcmp(*argv, "-")) - fp = stdin; - else if ((fp = fopen(*argv, - fflag ? "rf" : "r")) == NULL) { - warn("%s", *argv); - rval = EXIT_FAILURE; - ++argv; - continue; - } - filename = *argv++; - } - cook_buf(fp); - if (fp != stdin) - (void)fclose(fp); - else - clearerr(fp); - } while (*argv); -} - -void -cook_buf(FILE *fp) -{ - int ch, gobble, line, prev; - - line = gobble = 0; - for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { - if (prev == '\n') { - if (sflag) { - if (ch == '\n') { - if (gobble) - continue; - gobble = 1; - } else - gobble = 0; - } - if (nflag) { - if (!bflag || ch != '\n') { - (void)fprintf(stdout, - "%6d\t", ++line); - if (ferror(stdout)) - break; - } else if (eflag) { - (void)fprintf(stdout, - "%6s\t", ""); - if (ferror(stdout)) - break; - } - } - } - if (ch == '\n') { - if (eflag) - if (putchar('$') == EOF) - break; - } else if (ch == '\t') { - if (tflag) { - if (putchar('^') == EOF || putchar('I') == EOF) - break; - continue; - } - } else if (vflag) { - if (!isascii(ch)) { - if (putchar('M') == EOF || putchar('-') == EOF) - break; - ch = toascii(ch); - } - if (iscntrl(ch)) { - if (putchar('^') == EOF || - putchar(ch == '\177' ? '?' : - ch | 0100) == EOF) - break; - continue; - } - } - if (putchar(ch) == EOF) - break; - } - if (ferror(fp)) { - warn("%s", filename); - rval = EXIT_FAILURE; - clearerr(fp); - } - if (ferror(stdout)) - err(EXIT_FAILURE, "stdout"); -} - -void -raw_args(char **argv) -{ - int fd; - - fd = fileno(stdin); - filename = "stdin"; - do { - if (*argv) { - if (!strcmp(*argv, "-")) { - fd = fileno(stdin); - if (fd < 0) - goto skip; - } else if (fflag) { - struct stat st; - fd = open(*argv, O_RDONLY|O_NONBLOCK, 0); - if (fd < 0) - goto skip; - - if (fstat(fd, &st) == -1) { - close(fd); - goto skip; - } - if (!S_ISREG(st.st_mode)) { - close(fd); - warnx("%s: not a regular file", *argv); - goto skipnomsg; - } - } - else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { -skip: - warn("%s", *argv); -skipnomsg: - rval = EXIT_FAILURE; - ++argv; - continue; - } - filename = *argv++; - } else if (fd < 0) { - err(EXIT_FAILURE, "stdin"); - } - raw_cat(fd); - if (fd != fileno(stdin)) - (void)close(fd); - } while (*argv); -} - -void -raw_cat(int rfd) -{ - static char *buf; - static char fb_buf[BUFSIZ]; - - ssize_t nr, nw, off; - int wfd; - - wfd = fileno(stdout); - if (wfd < 0) - err(EXIT_FAILURE, "stdout"); - if (buf == NULL) { - struct stat sbuf; - - if (bsize == 0) { - if (fstat(wfd, &sbuf) == 0 && sbuf.st_blksize > 0 && - (size_t)sbuf.st_blksize > sizeof(fb_buf)) - bsize = sbuf.st_blksize; - } - if (bsize > sizeof(fb_buf)) { - buf = malloc(bsize); - if (buf == NULL) - warnx("malloc, using %zu buffer", bsize); - } - if (buf == NULL) { - bsize = sizeof(fb_buf); - buf = fb_buf; - } - } - while ((nr = read(rfd, buf, bsize)) > 0) - for (off = 0; nr; nr -= nw, off += nw) - if ((nw = write(wfd, buf + off, (size_t)nr)) < 0) - err(EXIT_FAILURE, "stdout"); - if (nr < 0) { - warn("%s", filename); - rval = EXIT_FAILURE; - } -} diff --git a/bin/chmod/Makefile b/bin/chmod/Makefile deleted file mode 100644 index 8e241d099..000000000 --- a/bin/chmod/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# $NetBSD: Makefile,v 1.8 1997/07/20 22:36:34 christos Exp $ -# @(#)Makefile 8.1 (Berkeley) 5/31/93 - -PROG= chmod - -.include diff --git a/bin/chmod/chmod.1 b/bin/chmod/chmod.1 deleted file mode 100644 index 7c3add61a..000000000 --- a/bin/chmod/chmod.1 +++ /dev/null @@ -1,315 +0,0 @@ -.\" $NetBSD: chmod.1,v 1.26 2016/08/11 00:10:42 sevan Exp $ -.\" -.\" Copyright (c) 1989, 1990, 1993, 1994 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Institute of Electrical and Electronics Engineers, Inc. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)chmod.1 8.4 (Berkeley) 3/31/94 -.\" -.Dd August 11, 2016 -.Dt CHMOD 1 -.Os -.Sh NAME -.Nm chmod -.Nd change file modes -.Sh SYNOPSIS -.Nm -.Oo -.Fl R -.Op Fl H | Fl L | Fl P -.Oc -.Op Fl fh -.Ar mode -.Ar -.Nm -.Oo -.Fl R -.Op Fl H | Fl L | Fl P -.Oc -.Op Fl fh -.Fl Fl reference=rfile -.Ar -.Sh DESCRIPTION -The -.Nm -utility modifies the file mode bits of the listed files -as specified by the -.Ar mode -operand, or -copied from a reference -.Ar rfile , -as specified with the -.Fl Fl reference -argument. -.Pp -The options are as follows: -.Bl -tag -width Ds -.It Fl H -If the -.Fl R -option is specified, symbolic links on the command line are followed. -(Symbolic links encountered in the tree traversal are not followed.) -.It Fl L -If the -.Fl R -option is specified, all symbolic links are followed. -.It Fl P -If the -.Fl R -option is specified, no symbolic links are followed. -.It Fl R -Change the modes of the file hierarchies rooted in the files -instead of just the files themselves. -.It Fl f -Do not display a diagnostic message or modify the exit status if -.Nm -fails to change the mode of a file. -.It Fl h -If -.Ar file -is symbolic link, the mode of the link is changed. -.El -.Pp -The -.Fl H , -.Fl L -and -.Fl P -options are ignored unless the -.Fl R -option is specified. -In addition, these options override each other and the -command's actions are determined by the last one specified. -The default is as if the -.Fl P -option had been specified. -.Pp -Only the owner of a file or the super-user is permitted to change -the mode of a file. -.Sh EXIT STATUS -The -.Nm -utility exits 0 on success, and \*[Gt]0 if an error occurs. -.Sh MODES -Modes may be absolute or symbolic. -An absolute mode is an octal number constructed by -.Em or Ap ing -the following values: -.Pp -.Bl -tag -width 6n -compact -offset indent -.It Li 4000 -set-user-ID-on-execution -.It Li 2000 -set-group-ID-on-execution -.It Li 1000 -sticky bit, see -.Xr chmod 2 -.It Li 0400 -read by owner -.It Li 0200 -write by owner -.It Li 0100 -execute (or search for directories) by owner -.It Li 0070 -read, write, execute/search by group -.It Li 0007 -read, write, execute/search by others -.El -.Pp -The read, write, and execute/search values for group and others -are encoded as described for owner. -.Pp -The symbolic mode is described by the following grammar: -.Bd -literal -offset indent -mode ::= clause [, clause ...] -clause ::= [who ...] [action ...] last_action -action ::= op [perm ...] -last_action ::= op [perm ...] -who ::= a | u | g | o -op ::= + | \- | = -perm ::= r | s | t | w | x | X | u | g | o -.Ed -.Pp -The -.Ar who -symbols ``u'', ``g'', and ``o'' specify the user, group, and other parts -of the mode bits, respectively. -The -.Ar who -symbol ``a'' is equivalent to ``ugo''. -.Pp -The -.Ar perm -symbols represent the portions of the mode bits as follows: -.Pp -.Bl -tag -width Ds -compact -offset indent -.It r -The read bits. -.It s -The set-user-ID-on-execution and set-group-ID-on-execution bits. -.It t -The sticky bit. -.It w -The write bits. -.It x -The execute/search bits. -.It X -The execute/search bits if the file is a directory or any of the -execute/search bits are set in the original (unmodified) mode. -Operations with the -.Ar perm -symbol ``X'' are only meaningful in conjunction with the -.Ar op -symbol ``+'', and are ignored in all other cases. -.It u -The user permission bits in the mode of the original file. -.It g -The group permission bits in the mode of the original file. -.It o -The other permission bits in the mode of the original file. -.El -.Pp -The -.Ar op -symbols represent the operation performed, as follows: -.Bl -tag -width 4n -.It + -If no value is supplied for -.Ar perm , -the ``+'' operation has no effect. -If no value is supplied for -.Ar who , -each permission bit specified in -.Ar perm , -for which the corresponding bit in the file mode creation mask -is clear, is set. -Otherwise, the mode bits represented by the specified -.Ar who -and -.Ar perm -values are set. -.It \&\- -If no value is supplied for -.Ar perm , -the ``\-'' operation has no effect. -If no value is supplied for -.Ar who , -each permission bit specified in -.Ar perm , -for which the corresponding bit in the file mode creation mask -is clear, is cleared. -Otherwise, the mode bits represented by the specified -.Ar who -and -.Ar perm -values are cleared. -.It = -The mode bits specified by the -.Ar who -value are cleared, or, if no who value is specified, the owner, group -and other mode bits are cleared. -Then, if no value is supplied for -.Ar who , -each permission bit specified in -.Ar perm , -for which the corresponding bit in the file mode creation mask -is clear, is set. -Otherwise, the mode bits represented by the specified -.Ar who -and -.Ar perm -values are set. -.El -.Pp -Each -.Ar clause -specifies one or more operations to be performed on the mode -bits, and each operation is applied to the mode bits in the -order specified. -.Pp -Operations upon the other permissions only (specified by the symbol -``o'' by itself), in combination with the -.Ar perm -symbols ``s'' or ``t'', are ignored. -.Sh EXAMPLES -.Bl -tag -width "u=rwx,go=u-w" -compact -.It Li 644 -make a file readable by anyone and writable by the owner only. -.Pp -.It Li go-w -deny write permission to group and others. -.Pp -.It Li =rw,+X -set the read and write permissions to the usual defaults, but -retain any execute permissions that are currently set. -.Pp -.It Li +X -make a directory or file searchable/executable by everyone if it is -already searchable/executable by anyone. -.Pp -.It Li 755 -.It Li u=rwx,go=rx -.It Li u=rwx,go=u-w -make a file readable/executable by everyone and writable by the owner only. -.Pp -.It Li go= -clear all mode bits for group and others. -.Pp -.It Li g=u-w -set the group bits equal to the user bits, but clear the group write bit. -.El -.Sh SEE ALSO -.Xr chflags 1 , -.Xr install 1 , -.Xr chmod 2 , -.Xr stat 2 , -.Xr umask 2 , -.Xr fts 3 , -.Xr setmode 3 , -.Xr symlink 7 , -.Xr chown 8 -.Sh STANDARDS -The -.Nm -utility is expected to be -.St -p1003.2-92 -compatible with the exception of the -.Ar perm -symbol -.Dq t -which is not included in that standard. -.Sh HISTORY -A -.Nm -utility appeared in -.At v1 . -.Sh BUGS -There's no -.Ar perm -option for the naughty bits. diff --git a/bin/chmod/chmod.c b/bin/chmod/chmod.c deleted file mode 100644 index c10101e54..000000000 --- a/bin/chmod/chmod.c +++ /dev/null @@ -1,239 +0,0 @@ -/* $NetBSD: chmod.c,v 1.38 2012/10/22 18:00:46 christos Exp $ */ - -/* - * Copyright (c) 1989, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT( -"@(#) Copyright (c) 1989, 1993, 1994\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)chmod.c 8.8 (Berkeley) 4/1/94"; -#else -__RCSID("$NetBSD: chmod.c,v 1.38 2012/10/22 18:00:46 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -__dead static void usage(void); - -struct option chmod_longopts[] = { - { "reference", required_argument, 0, - 1 }, - { NULL, 0, 0, - 0 }, -}; - -int -main(int argc, char *argv[]) -{ - FTS *ftsp; - FTSENT *p; - void *set; - mode_t mval; - int Hflag, Lflag, Rflag, ch, fflag, fts_options, hflag, rval; - char *mode, *reference; - int (*change_mode)(const char *, mode_t); - - setprogname(argv[0]); - (void)setlocale(LC_ALL, ""); - - Hflag = Lflag = Rflag = fflag = hflag = 0; - reference = NULL; - while ((ch = getopt_long(argc, argv, "HLPRXfghorstuwx", - chmod_longopts, NULL)) != -1) - switch (ch) { - case 1: - reference = optarg; - break; - case 'H': - Hflag = 1; - Lflag = 0; - break; - case 'L': - Lflag = 1; - Hflag = 0; - break; - case 'P': - Hflag = Lflag = 0; - break; - case 'R': - Rflag = 1; - break; - case 'f': - fflag = 1; - break; - case 'h': - /* - * In System V the -h option causes chmod to - * change the mode of the symbolic link. - * 4.4BSD's symbolic links didn't have modes, - * so it was an undocumented noop. In NetBSD - * 1.3, lchmod(2) is introduced and this - * option does real work. - */ - hflag = 1; - break; - /* - * XXX - * "-[rwx]" are valid mode commands. If they are the entire - * argument, getopt has moved past them, so decrement optind. - * Regardless, we're done argument processing. - */ - case 'g': case 'o': case 'r': case 's': - case 't': case 'u': case 'w': case 'X': case 'x': - if (argv[optind - 1][0] == '-' && - argv[optind - 1][1] == ch && - argv[optind - 1][2] == '\0') - --optind; - goto done; - case '?': - default: - usage(); - } -done: argv += optind; - argc -= optind; - - if (argc == 0 || (argc == 1 && reference == NULL)) - usage(); - - fts_options = FTS_PHYSICAL; - if (Rflag) { - if (hflag) { - errx(EXIT_FAILURE, - "the -R and -h options may not be specified together."); - /* NOTREACHED */ - } - if (Hflag) - fts_options |= FTS_COMFOLLOW; - if (Lflag) { - fts_options &= ~FTS_PHYSICAL; - fts_options |= FTS_LOGICAL; - } - } else if (!hflag) - fts_options |= FTS_COMFOLLOW; - if (hflag) - change_mode = lchmod; - else - change_mode = chmod; - - if (reference == NULL) { - mode = *argv++; - if ((set = setmode(mode)) == NULL) { - err(EXIT_FAILURE, "Cannot set file mode `%s'", mode); - /* NOTREACHED */ - } - mval = 0; - } else { - struct stat st; - - if (stat(reference, &st) == -1) - err(EXIT_FAILURE, "Cannot stat `%s'", reference); - mval = st.st_mode; - set = NULL; - } - - if ((ftsp = fts_open(argv, fts_options, 0)) == NULL) { - err(EXIT_FAILURE, "fts_open"); - /* NOTREACHED */ - } - for (rval = 0; (p = fts_read(ftsp)) != NULL;) { - switch (p->fts_info) { - case FTS_D: - if (!Rflag) - (void)fts_set(ftsp, p, FTS_SKIP); - break; - case FTS_DNR: /* Warn, chmod, continue. */ - warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); - rval = 1; - break; - case FTS_DP: /* Already changed at FTS_D. */ - continue; - case FTS_ERR: /* Warn, continue. */ - case FTS_NS: - warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); - rval = 1; - continue; - case FTS_SL: /* Ignore. */ - case FTS_SLNONE: - /* - * The only symlinks that end up here are ones that - * don't point to anything and ones that we found - * doing a physical walk. - */ - if (!hflag) - continue; - /* else */ - /* FALLTHROUGH */ - default: - break; - } - if ((*change_mode)(p->fts_accpath, - set ? getmode(set, p->fts_statp->st_mode) : mval) - && !fflag) { - warn("%s", p->fts_path); - rval = 1; - } - } - if (errno) { - err(EXIT_FAILURE, "fts_read"); - /* NOTREACHED */ - } - exit(rval); - /* NOTREACHED */ -} - -static void -usage(void) -{ - (void)fprintf(stderr, - "Usage: %s [-R [-H | -L | -P]] [-fh] mode file ...\n" - "\t%s [-R [-H | -L | -P]] [-fh] --reference=rfile file ...\n", - getprogname(), getprogname()); - exit(1); - /* NOTREACHED */ -} diff --git a/bin/csh/Makefile b/bin/csh/Makefile deleted file mode 100644 index 7212712ca..000000000 --- a/bin/csh/Makefile +++ /dev/null @@ -1,72 +0,0 @@ -# $NetBSD: Makefile,v 1.41 2014/07/05 23:12:33 dholland Exp $ -# @(#)Makefile 8.1 (Berkeley) 5/31/93 -# -# C Shell with process control; VM/UNIX VAX Makefile -# Bill Joy UC Berkeley; Jim Kulp IIASA, Austria -# -# To profile, put -DPROF in DFLAGS and -pg in COPTS, and recompile. - -.include -WARNS=6 - -PROG= csh -DFLAGS=-DBUILTIN -DFILEC -DNLS -DSHORT_STRINGS -# - Editor history not always aligned with shell history, -# should implement internally -# - Does not handle escaped prompts. -# - Does not do completion -.ifndef SMALLPROG -DFLAGS+=-DEDIT -.endif -CPPFLAGS+=-I${.CURDIR} -I. ${DFLAGS} -SRCS= alloc.c char.c const.c csh.c dir.c dol.c err.c exec.c exp.c file.c \ - func.c glob.c hist.c init.c lex.c misc.c parse.c printf.c proc.c \ - sem.c set.c str.c time.c -.PATH: ${NETBSDSRCDIR}/usr.bin/printf - -MLINKS= csh.1 limit.1 csh.1 alias.1 csh.1 bg.1 csh.1 dirs.1 csh.1 fg.1 \ - csh.1 foreach.1 csh.1 history.1 csh.1 jobs.1 csh.1 popd.1 \ - csh.1 pushd.1 csh.1 rehash.1 csh.1 repeat.1 csh.1 suspend.1 \ - csh.1 stop.1 csh.1 source.1 - -DPSRCS+= errnum.h const.h -CLEANFILES+= errnum.h const.h - -errnum.h: err.c - ${_MKTARGET_CREATE} - rm -f ${.TARGET} - (\ - echo '/* Do not edit this file, make creates it. */' ;\ - echo '#ifndef _h_sh_errnum' ;\ - echo '#define _h_sh_errnum' ;\ - egrep 'ERR_' ${.ALLSRC} | egrep '^#define' ;\ - echo '#endif /* _h_sh_errnum */' ;\ - ) > ${.TARGET} - -const.c: errnum.h -const.h: const.c - ${_MKTARGET_CREATE} - rm -f ${.TARGET} - echo '/* Do not edit this file, make creates it. */' > ${.TARGET} - ${CC} -E ${CPPFLAGS} ${.ALLSRC} | egrep 'Char STR' | \ - ${TOOL_SED} -e 's/Char \([a-zA-Z0-9_]*\)\(.*\)/extern Char \1[];/' | \ - sort >> ${.TARGET} - -.if !defined(__MINIX) -SUBDIR+=USD.doc -.endif # !defined(__MINIX) - -COPTS.err.c = -Wno-format-nonliteral -COPTS.printf.c = -Wno-format-nonliteral -COPTS.proc.c = -Wno-format-nonliteral - -.if !empty(DFLAGS:M*EDIT) -LDADD+=-ledit -lterminfo -lutil -DPADD+=${LIBEDIT} ${LIBUTIL} -.else -LDADD+=-lutil -DPADD+=${LIBUTIL} -.endif - -.include -.include diff --git a/bin/csh/USD.doc/Makefile b/bin/csh/USD.doc/Makefile deleted file mode 100644 index e53b2688d..000000000 --- a/bin/csh/USD.doc/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# $NetBSD: Makefile,v 1.9 2014/07/05 19:22:41 dholland Exp $ -# @(#)Makefile 8.1 (Berkeley) 8/14/93 - -SECTION=reference/ref1 -ARTICLE=csh -SRCS= tabs csh.1 csh.2 csh.3 csh.4 csh.ap csh.g -MACROS= -ms -EXTRAHTMLFILES=\ - csh1.png csh2.png csh3.png csh4.png csh5.png csh6.png csh7.png \ - csh8.png csh9.png - -.include diff --git a/bin/csh/USD.doc/csh.1 b/bin/csh/USD.doc/csh.1 deleted file mode 100644 index 9f44af796..000000000 --- a/bin/csh/USD.doc/csh.1 +++ /dev/null @@ -1,1010 +0,0 @@ -.\" $NetBSD: csh.1,v 1.5 2003/08/07 09:05:08 agc Exp $ -.\" -.\" Copyright (c) 1980, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)csh.1 8.1 (Berkeley) 6/8/93 -.\" -.EH 'USD:4-%''An Introduction to the C shell' -.OH 'An Introduction to the C shell''USD:4-%' -.\".RP -.TL -An Introduction to the C shell -.AU -William Joy -(revised for 4.3BSD by Mark Seiden) -.AI -Computer Science Division -.br -Department of Electrical Engineering and Computer Science -.br -University of California, Berkeley -.br -Berkeley, California 94720 -.AB -.I Csh -is a new command language interpreter for -.UX -systems. -It incorporates good features of other shells and a -.I history -mechanism similar to the -.I redo -of \s-2INTERLISP\s0. -While incorporating many features of other shells which make -writing shell programs (shell scripts) easier, -most of the features unique to -.I csh -are designed more for the interactive \s-2UNIX\s0 user. -.PP -\s-2UNIX\s0 -users who have read a general introduction to the system -will find a valuable basic explanation of the shell here. -Simple terminal interaction with -.I csh -is possible after reading just the first section of this document. -The second section describes the shell's capabilities which you can -explore after you have begun to become acquainted with the shell. -Later sections introduce features which are useful, but not necessary -for all users of the shell. -.PP -Additional information includes an appendix listing special characters of the shell -and a glossary of terms and commands introduced in this manual. -.AE -.SH -.if n .ND -Introduction -.PP -A -.I shell -is a command language interpreter. -.I Csh -is the name of one particular command interpreter on -\s-2UNIX\s0. -The primary purpose of -.I csh -is to translate command lines typed at a terminal into -system actions, such as invocation of other programs. -.I Csh -is a user program just like any you might write. -Hopefully, -.I csh -will be a very useful program for you -in interacting with the \s-2UNIX\s0 system. -.PP -In addition to this document, you will want to refer to a copy -of the \s-2UNIX\s0 User Reference Manual. -The -.I csh -documentation in section 1 of the manual provides a full description of all -features of the shell and is the definitive reference for questions -about the shell. -.PP -Many words in this document are shown in -.I italics. -These are important words; -names of commands, and words which have special meaning in discussing -the shell and \s-2UNIX\s0. -Many of the words are defined in a glossary at the end of this document. -If you don't know what is meant by a word, you should look -for it in the glossary. -.SH -Acknowledgements -.PP -Numerous people have provided good input about previous versions -of -.I csh -and aided in its debugging and in the debugging of its documentation. -I would especially like to thank Michael Ubell -who made the crucial observation that history commands could be -done well over the word structure of input text, and implemented -a prototype history mechanism in an older version of the shell. -Eric Allman has also provided a large number of useful comments on the -shell, helping to unify those concepts which are present and to identify -and eliminate useless and marginally useful features. -Mike O'Brien suggested the pathname hashing -mechanism which speeds command execution. -Jim Kulp added the job control and directory stack primitives and -added their documentation to this introduction. -.br -.bp -.NH -Terminal usage of the shell -.NH 2 -The basic notion of commands -.PP -A -.I shell -in -\s-2UNIX\s0 -acts mostly as a medium through which other -.I programs -are invoked. -While it has a set of -.I builtin -functions which it performs directly, -most commands cause execution of programs that are, in fact, -external to the shell. -The shell is thus distinguished from the command interpreters of other -systems both by the fact that it is just a user program, and by the fact -that it is used almost exclusively as a mechanism for invoking other programs. -.PP -.I Commands -in the \s-2UNIX\s0 system consist of a list of strings or -.I words -interpreted as a -.I "command name" -followed by -.I arguments. -Thus the command -.DS -mail bill -.DE -consists of two words. -The first word -.I mail -names the command to be executed, in this case the -mail program which sends messages to other users. -The shell uses the name of the command in attempting to execute it for you. -It will look in a number of -.I directories -for a file with the name -.I mail -which is expected to contain the mail program. -.PP -The rest of the words of the command are given as -.I arguments -to the command itself when it is executed. -In this case we specified also the argument -.I bill -which is interpreted by the -.I mail -program to be the name of a user to whom mail is to be sent. -In normal terminal usage we might use the -.I mail -command as follows. -.DS -% mail bill -I have a question about the csh documentation. -My document seems to be missing page 5. -Does a page five exist? - Bill -EOT -% -.DE -.PP -Here we typed a message to send to -.I bill -and ended this message with a ^D which sent an end-of-file to -the mail program. -(Here and throughout this document, the notation ``^\fIx\fR'' -is to be read ``control-\fIx\fR'' and represents the striking of the \fIx\fR -key while the control key is held down.) -The mail program -then echoed the characters `EOT' and transmitted our message. -The characters `% ' were printed before and after the mail command -by the shell to indicate that input was needed. -.PP -After typing the `% ' prompt the shell was reading command input from -our terminal. -We typed a complete command `mail bill'. -The shell then executed the -.I mail -program with argument -.I bill -and went dormant waiting for it to complete. -The mail program then read input from our terminal until we signalled -an end-of-file via typing a ^D after which the shell noticed -that mail had completed -and signaled us that it was ready to read from the terminal again by -printing another `% ' prompt. -.PP -This is the essential pattern of all interaction with \s-2UNIX\s0 -through the shell. -A complete command is typed at the terminal, the shell executes -the command and when this execution completes, it prompts for a new command. -If you run the editor for an hour, the shell will patiently wait for -you to finish editing and obediently prompt you again whenever you finish -editing. -.PP -An example of a useful command you can execute now is the -.I tset -command, which sets the default -.I erase -and -.I kill -characters on your terminal \- the erase character erases the last -character you typed and the kill character erases the entire line you -have entered so far. -By default, the erase character is the delete key (equivalent to `^?') -and the kill character is `^U'. Some people prefer to make the erase character -the backspace key (equivalent to `^H'). -You can make this be true by typing -.DS -tset \-e -.DE -which tells the program -.I tset -to set the erase character to tset's default setting for this character -(a backspace). -.NH 2 -Flag arguments -.PP -A useful notion in \s-2UNIX\s0 is that of a -.I flag -argument. -While many arguments to commands specify file names or user names, -some arguments rather specify an optional capability of the command -which you wish to invoke. -By convention, such arguments begin with the character `\-' (hyphen). -Thus the command -.DS -ls -.DE -will produce a list of the files in the current -.I "working directory" . -The option -.I \-s -is the size option, and -.DS -ls \-s -.DE -causes -.I ls -to also give, for each file the size of the file in blocks of 512 -characters. -The manual section for each command in the \s-2UNIX\s0 reference manual -gives the available options for each command. -The -.I ls -command has a large number of useful and interesting options. -Most other commands have either no options or only one or two options. -It is hard to remember options of commands which are not used very -frequently, so most \s-2UNIX\s0 utilities perform only one or two functions -rather than having a large number of hard to remember options. -.NH 2 -Output to files -.PP -Commands that normally read input or write output on the terminal -can also be executed with this input and/or output done to -a file. -.PP -Thus suppose we wish to save the current date in a file called `now'. -The command -.DS -date -.DE -will print the current date on our terminal. -This is because our terminal is the default -.I "standard output" -for the date command and the date command prints the date on its -standard output. -The shell lets us -.I redirect -the -.I "standard output" -of a command through a -notation using the -.I metacharacter -`>' and the name of the file where output is to be placed. -Thus the command -.DS -date > now -.DE -runs the -.I date -command such that its standard output is -the file `now' rather than the terminal. -Thus this command places the current date and time into the file `now'. -It is important to know that the -.I date -command was unaware that its output was going to a file rather than -to the terminal. -The shell performed this -.I redirection -before the command began executing. -.PP -One other thing to note here is that the file `now' -need not have existed before the -.I date -command was executed; the shell would have created the file if it did -not exist. -And if the file did exist? -If it had existed previously these previous contents would have been discarded! -A shell option -.I noclobber -exists to prevent this from happening accidentally; -it is discussed in section 2.2. -.PP -The system normally keeps files which you create with `>' and all other files. -Thus the default is for files to be permanent. If you wish to create a file -which will be removed automatically, you can begin its name with a `#' -character, this `scratch' character denotes the fact that the file will -be a scratch file.* -.FS -*Note that if your erase character is a `#', you will have to precede the -`#' with a `\e'. The fact that the `#' character is the old (pre-\s-2CRT\s0) -standard erase character means that it seldom appears in a file name, and -allows this convention to be used for scratch files. If you are using a -\s-2CRT\s0, your erase character should be a ^H, as we demonstrated -in section 1.1 how this could be set up. -.FE -The system will remove such files after a couple of days, -or sooner if file space becomes very tight. -Thus, in running the -.I date -command above, we don't really want to save the output forever, so we -would more likely do -.DS -date > #now -.DE -.NH 2 -Metacharacters in the shell -.PP -The shell has a large number of -special characters (like `>') -which indicate special functions. -We say that these notations have -.I syntactic -and -.I semantic -meaning to the shell. -In general, most characters which are neither letters nor digits -have special meaning to the shell. -We shall shortly learn a means of -.I quotation -which allows us to use -.I metacharacters -without the shell treating them in any special way. -.PP -Metacharacters normally have effect only when the shell is reading -our input. -We need not worry about placing shell metacharacters in a letter -we are sending via -.I mail, -or when we are typing in text or data to some other program. -Note that the shell is only reading input when it has prompted with -`% ' (although we can type our input even before it prompts). -.NH 2 -Input from files; pipelines -.PP -We learned above how to -.I redirect -the -.I "standard output" -of a command -to a file. -It is also possible to redirect the -.I "standard input" -of a command from a file. -This is not often necessary since most commands will read from -a file whose name is given as an argument. -We can give the command -.DS -sort < data -.DE -to run the -.I sort -command with standard input, where the command normally -reads its input, from the file -`data'. -We would more likely say -.DS -sort data -.DE -letting the -.I sort -command open the file -`data' -for input itself since this is less to type. -.PP -We should note that if we just typed -.DS -sort -.DE -then the sort program would sort lines from its -.I "standard input." -Since we did not -.I redirect -the standard input, it would sort lines as we typed them on the terminal -until we typed a ^D to indicate an end-of-file. -.PP -A most useful capability is the ability to combine the standard output -of one command with the standard input of another, i.e. to run the -commands in a sequence known as a -.I pipeline. -For instance the command -.DS -ls \-s -.DE -normally produces a list of the files in our directory with the size -of each in blocks of 512 characters. -If we are interested in learning which of our files is largest we -may wish to have this sorted by size rather than by name, which is -the default way in which -.I ls -sorts. -We could look at the many options of -.I ls -to see if there was an option to do this but would eventually discover -that there is not. -Instead we can use a couple of simple options of the -.I sort -command, combining it with -.I ls -to get what we want. -.PP -The -.I \-n -option of sort specifies a numeric sort rather than an alphabetic sort. -Thus -.DS -ls \-s | sort \-n -.DE -specifies that the output of the -.I ls -command run with the option -.I \-s -is to be -.I piped -to the command -.I sort -run with the numeric sort option. -This would give us a sorted list of our files by size, but with the -smallest first. -We could then use the -.I \-r -reverse sort option and the -.I head -command in combination with the previous command doing -.DS -ls \-s | sort \-n \-r | head \-5 -.DE -Here we have taken a list of our files sorted alphabetically, -each with the size in blocks. -We have run this to the standard input of the -.I sort -command asking it to sort numerically in reverse order (largest first). -This output has then been run into the command -.I head -which gives us the first few lines. -In this case we have asked -.I head -for the first 5 lines. -Thus this command gives us the names and sizes of our 5 largest files. -.PP -The notation introduced above is called the -.I pipe -mechanism. -Commands separated by `\||\|' characters are connected together by the -shell and the standard output of each is run into the standard input of the -next. -The leftmost command in a pipeline will normally take its standard -input from the terminal and the rightmost will place its standard -output on the terminal. -Other examples of pipelines will be given later when we discuss the -history mechanism; -one important use of pipes which is illustrated there is in the -routing of information to the line printer. -.NH 2 -Filenames -.PP -Many commands to be executed will need the names of files as arguments. -\s-2UNIX\s0 -.I pathnames -consist of a number of -.I components -separated by `/'. -Each component except the last names a directory in which the next -component resides, in effect specifying the -.I path -of directories to follow to reach the file. -Thus the pathname -.DS -/etc/motd -.DE -specifies a file in the directory -`etc' -which is a subdirectory of the -.I root -directory `/'. -Within this directory the file named is `motd' which stands -for `message of the day'. -A -.I pathname -that begins with a slash is said to be an -.I absolute -pathname since it is specified from the absolute top of the entire -directory hierarchy of the system (the -.I root ). -.I Pathnames -which do not begin with `/' are interpreted as starting in the current -.I "working directory" , -which is, by default, your -.I home -directory and can be changed dynamically by the -.I cd -change directory command. -Such pathnames are said to be -.I relative -to the working directory since they are found by starting -in the working directory and descending to lower levels of directories -for each -.I component -of the pathname. If the pathname contains no slashes at all then the -file is contained in the working directory itself and the pathname is merely -the name of the file in this directory. -Absolute pathnames have no relation -to the working directory. -.PP -Most filenames consist of a number of alphanumeric characters and -`.'s (periods). -In fact, all printing characters except `/' (slash) may appear in filenames. -It is inconvenient to have most non-alphabetic characters in filenames -because many of these have special meaning to the shell. -The character `.' (period) is not a shell-metacharacter and is often used -to separate the -.I extension -of a file name from the base of the name. -Thus -.DS -prog.c prog.o prog.errs prog.output -.DE -are four related files. -They share a -.I base -portion of a name -(a base portion being that part of the name that is left when a trailing -`.' and following characters which are not `.' are stripped off). -The file -`prog.c' -might be the source for a C program, -the file `prog.o' the corresponding object file, -the file -`prog.errs' the errors resulting from a compilation of the program -and the file -`prog.output' the output of a run of the program. -.PP -If we wished to refer to all four of these files in a command, we could -use the notation -.DS -prog.* -.DE -This expression is expanded by the shell, before the command to which it is -an argument is executed, into a list of names which begin with `prog.'. -The character `*' here matches any sequence (including the empty sequence) -of characters in a file name. -The names which match are alphabetically sorted and placed in the -.I "argument list" -of the command. -Thus the command -.DS -echo prog.* -.DE -will echo the names -.DS -prog.c prog.errs prog.o prog.output -.DE -Note that the names are in sorted order here, and a different -order than we listed them above. -The -.I echo -command receives four words as arguments, even though we only typed -one word as as argument directly. -The four words were generated by -.I "filename expansion" -of the one input word. -.PP -Other notations for -.I "filename expansion" -are also available. -The character `?' matches any single character in a filename. -Thus -.DS -echo ? \|?? \|??? -.DE -will echo a line of filenames; first those with one character names, -then those with two character names, and finally those with three -character names. -The names of each length will be independently sorted. -.PP -Another mechanism consists of a sequence of characters between `[' and `]'. -This metasequence matches any single character from the enclosed set. -Thus -.DS -prog.[co] -.DE -will match -.DS -prog.c prog.o -.DE -in the example above. -We can also place two characters around a `\-' in this notation to denote -a range. -Thus -.DS -chap.[1\-5] -.DE -might match files -.DS -chap.1 chap.2 chap.3 chap.4 chap.5 -.DE -if they existed. -This is shorthand for -.DS -chap.[12345] -.DE -and otherwise equivalent. -.PP -An important point to note is that if a list of argument words to -a command (an -.I "argument list)" -contains filename expansion syntax, and if this filename expansion syntax -fails to match any existing file names, then the shell considers this -to be an error and prints a diagnostic -.DS -No match. -.DE -and does not execute the command. -.PP -Another very important point is that files with the character `.' at the -beginning are treated specially. -Neither `*' or `?' or the `[' `]' mechanism will match it. -This prevents accidental matching of the filenames `.' and `..' -in the working directory which have special meaning to the system, -as well as other files such as -.I \&.cshrc -which are not normally -visible. -We will discuss the special role of the file -.I \&.cshrc -later. -.PP -Another filename expansion mechanism gives access to the pathname of -the -.I home -directory of other users. -This notation consists of the character `~' (tilde) followed by another user's -login name. -For instance the word `~bill' would map to the pathname `/usr/bill' -if the home directory for `bill' was `/usr/bill'. -Since, on large systems, users may have login directories scattered over -many different disk volumes with different prefix directory names, -this notation provides a convenient way of accessing the files -of other users. -.PP -A special case of this notation consists of a `~' alone, e.g. `~/mbox'. -This notation is expanded by the shell into the file `mbox' in your -.I home -directory, i.e. into `/usr/bill/mbox' for me on Ernie Co-vax, the UCB -Computer Science Department VAX machine, where this document was prepared. -This can be very useful if you have used -.I cd -to change to another directory and have found a file you wish to -copy using -.I cp. -If I give the command -.DS -cp thatfile ~ -.DE -the shell will expand this command to -.DS -cp thatfile /usr/bill -.DE -since my home directory is /usr/bill. -.PP -There also exists a mechanism using the characters `{' and `}' for -abbreviating a set of words which have common parts but cannot -be abbreviated by the above mechanisms because they are not files, -are the names of files which do not yet exist, -are not thus conveniently described. -This mechanism will be described much later, -in section 4.2, -as it is used less frequently. -.NH 2 -Quotation -.PP -We have already seen a number of metacharacters used by the shell. -These metacharacters pose a problem in that we cannot use them directly -as parts of words. -Thus the command -.DS -echo * -.DE -will not echo the character `*'. -It will either echo an sorted list of filenames in the -current -.I "working directory," -or print the message `No match' if there are -no files in the working directory. -.PP -The recommended mechanism for placing characters which are neither numbers, -digits, `/', `.' or `\-' in an argument word to a command is to enclose -it with single quotation characters `\'', i.e. -.DS -echo \'*\' -.DE -There is one special character `!' which is used by the -.I history -mechanism of the shell and which cannot be -.I escaped -by placing it within `\'' characters. -It and the character `\'' itself can be preceded by a single `\e' -to prevent their special meaning. -Thus -.DS -echo \e\'\e! -.DE -prints -.DS -\'! -.DE -These two mechanisms suffice to place any printing character into a word -which is an argument to a shell command. They can be combined, as in -.DS -echo \e\'\'*\' -.DE -which prints -.DS -\'* -.DE -since the first `\e' escaped the first `\'' and the `*' was enclosed -between `\'' characters. -.NH 2 -Terminating commands -.PP -When you are executing a command and the shell is -waiting for it to complete there are several ways -to force it to stop. -For instance if you type the command -.DS -cat /etc/passwd -.DE -the system will print a copy of a list of all users of the system -on your terminal. -This is likely to continue for several minutes unless you stop it. -You can send an -\s-2INTERRUPT\s0 -.I signal -to the -.I cat -command by typing ^C on your terminal.* -.FS -*On some older Unix systems the \s-2DEL\s0 or \s-2RUBOUT\s0 key -has the same effect. "stty all" will tell you the INTR key value. -.FE -Since -.I cat -does not take any precautions to avoid or otherwise handle this signal -the -\s-2INTERRUPT\s0 -will cause it to terminate. -The shell notices that -.I cat -has terminated and prompts you again with `% '. -If you hit \s-2INTERRUPT\s0 again, the shell will just -repeat its prompt since it handles \s-2INTERRUPT\s0 signals -and chooses to continue to execute commands rather than terminating -like -.I cat -did, which would have the effect of logging you out. -.PP -Another way in which many programs terminate is when they get an end-of-file -from their standard input. -Thus the -.I mail -program in the first example above was terminated when we typed a ^D -which generates an end-of-file from the standard input. -The shell also terminates when it gets an end-of-file printing `logout'; -\s-2UNIX\s0 then logs you off the system. -Since this means that typing too many ^D's can accidentally log us off, -the shell has a mechanism for preventing this. -This -.I ignoreeof -option will be discussed in section 2.2. -.PP -If a command has its standard input redirected from a file, then it will -normally terminate when it reaches the end of this file. -Thus if we execute -.DS -mail bill < prepared.text -.DE -the mail command will terminate without our typing a ^D. -This is because it read to the end-of-file of our file -`prepared.text' in which we placed a message for `bill' with an editor program. -We could also have done -.DS -cat prepared.text \||\| mail bill -.DE -since the -.I cat -command would then have written the text through the pipe to the -standard input of the mail command. -When the -.I cat -command completed it would have terminated, -closing down the pipeline -and the -.I mail -command would have received an end-of-file from it and terminated. -Using a pipe here is more complicated than redirecting input -so we would more likely use the first form. -These commands could also have been stopped by sending an \s-2INTERRUPT\s0. -.PP -Another possibility for stopping a command is to suspend its execution -temporarily, with the possibility of continuing execution later. This is -done by sending a \s-2STOP\s0 signal via typing a ^Z. -This signal causes all commands running on the terminal -(usually one but more if a pipeline is executing) to become suspended. -The shell notices that the command(s) have been suspended, types -`Stopped' and then prompts for a new command. -The previously executing command has been suspended, but otherwise -unaffected by the \s-2STOP\s0 signal. Any other commands can be executed -while the original command remains suspended. The suspended command can -be continued using the -.I fg -command with no arguments. The shell will then retype the command -to remind you which command is being continued, and cause the command -to resume execution. Unless any input files in use by the suspended -command have been changed in the meantime, the suspension has no effect -whatsoever on the execution of the command. This feature can be very useful -during editing, when you need to look at another file before continuing. An -example of command suspension follows. -.DS -% mail harold -Someone just copied a big file into my directory and its name is -^Z -Stopped -% ls -funnyfile -prog.c -prog.o -% jobs -.ta 1.75i -[1] + Stopped mail harold -% fg -mail harold -funnyfile. Do you know who did it? -EOT -% -.so tabs -.DE -In this example someone was sending a message to Harold and forgot the -name of the file he wanted to mention. The mail command was suspended -by typing ^Z. When the shell noticed that the mail program was -suspended, it typed `Stopped' and prompted for a new command. Then the -.I ls -command was typed to find out the name of the file. The -.I jobs -command was run to find out which command was suspended. At this time the -.I fg -command was typed to continue execution of the mail program. Input -to the mail program was then continued and ended with a ^D -which indicated the end of the message at which time the mail -program typed EOT. The -.I jobs -command will show which commands are suspended. -The ^Z should only be typed at the beginning of a line since -everything typed on the current line is discarded when a signal is sent -from the keyboard. This also happens on \s-2INTERRUPT\s0, and \s-2QUIT\s0 -signals. More information on -suspending jobs and controlling them is given in -section 2.6. -.PP -If you write or run programs which are not fully debugged then it may -be necessary to stop them somewhat ungracefully. -This can be done by sending them a \s-2QUIT\s0 -signal, sent by typing a ^\e. -This will usually provoke the shell to produce a message like: -.DS -Quit (Core dumped) -.DE -indicating that a file -`core' has been created containing information about the running program's -state when it terminated due to the \s-2QUIT\s0 signal. -You can examine this file yourself, or forward information to the -maintainer of the program telling him/her where the -.I "core file" -is. -.PP -If you run background commands (as explained in section 2.6) then these -commands will ignore \s-2INTERRUPT\s0 and \s-2QUIT\s0 signals at the -terminal. To stop them you must use the -.I kill -command. See section 2.6 for an example. -.PP -If you want to examine the output of a command without having it move -off the screen as the output of the -.DS -cat /etc/passwd -.DE -command will, you can use the command -.DS -more /etc/passwd -.DE -The -.I more -program pauses after each complete screenful and types `\-\-More\-\-' -at which point you can hit a space to get another screenful, a return -to get another line, a `?' to get some help on other commands, or a `q' to end the -.I more -program. You can also use more as a filter, i.e. -.DS -cat /etc/passwd | more -.DE -works just like the more simple more command above. -.PP -For stopping output of commands not involving -.I more -you can use the -^S key to stop the typeout. The typeout will resume when you -hit ^Q or any other key, but ^Q is normally used because -it only restarts the output and does not become input to the program -which is running. This works well on low-speed terminals, but at 9600 -baud it is hard to type ^S and ^Q fast enough to paginate -the output nicely, and a program like -.I more -is usually used. -.PP -An additional possibility is to use the ^O flush output -character; when this character is typed, all output from the current -command is thrown away (quickly) until the next input read occurs -or until the next shell prompt. This can be used to allow a command -to complete without having to suffer through the output on a slow -terminal; ^O is a toggle, so flushing can be turned off by -typing ^O again while output is being flushed. -.NH 2 -What now? -.PP -We have so far seen a number of mechanisms of the shell and learned a lot -about the way in which it operates. -The remaining sections will go yet further into the internals of the -shell, but you will surely want to try using the -shell before you go any further. -To try it you can log in to \s-2UNIX\s0 and type the following -command to the system: -.DS -chsh myname /bin/csh -.DE -Here `myname' should be replaced by the name you typed to -the system prompt of `login:' to get onto the system. -Thus I would use `chsh bill /bin/csh'. -.B -You only have to do this once; it takes effect at next login. -.R -You are now ready to try using -.I csh. -.PP -Before you do the `chsh' command, the shell you are using when -you log into the system is `/bin/sh'. -In fact, much of the above discussion is applicable to `/bin/sh'. -The next section will introduce many features particular to -.I csh -so you should change your shell to -.I csh -before you begin reading it. -.bp diff --git a/bin/csh/USD.doc/csh.2 b/bin/csh/USD.doc/csh.2 deleted file mode 100644 index 803434b19..000000000 --- a/bin/csh/USD.doc/csh.2 +++ /dev/null @@ -1,1303 +0,0 @@ -.\" $NetBSD: csh.2,v 1.7 2003/08/07 09:05:08 agc Exp $ -.\" -.\" Copyright (c) 1980, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)csh.2 8.1 (Berkeley) 6/8/93 -.\" -.nr H1 1 -.NH -Details on the shell for terminal users -.NH 2 -Shell startup and termination -.PP -When you login, the shell is started by the system in your -.I home -directory and begins by reading commands from a file -.I \&.cshrc -in this directory. -All shells which you may start during your terminal session will -read from this file. -We will later see what kinds of commands are usefully placed there. -For now we need not have this file and the shell does not complain about -its absence. -.PP -A -.I "login shell" , -executed after you login to the system, -will, after it reads commands from -.I \&.cshrc, -read commands from a file -.I \&.login -also in your home directory. -This file contains commands which you wish to do each time you login -to the \s-2UNIX\s0 system. -My -.I \&.login -file looks something like: -.DS -set ignoreeof -set mail=(/var/mail/bill) -echo "${prompt}users" ; users -alias ts \e - \'set noglob ; eval \`tset \-s \-m dialup:c100rv4pna \-m plugboard:?hp2621nl \!*\`\'; -ts; stty intr ^C kill ^U crt -set time=15 history=10 -msgs \-f -if (\-e $mail) then - echo "${prompt}mail" - mail -endif -.DE -.PP -This file contains several commands to be executed by \s-2UNIX\s0 -each time I login. -The first is a -.I set -command which is interpreted directly by the shell. It sets the shell -variable -.I ignoreeof -which causes the shell to not log me off if I hit ^D. Rather, -I use the -.I logout -command to log off of the system. -By setting the -.I mail -variable, I ask the shell to watch for incoming mail to me. Every 5 minutes -the shell looks for this file and tells me if more mail has arrived there. -An alternative to this is to put the command -.DS -biff y -.DE -in place of this -.I set; -this will cause me to be notified immediately when mail arrives, and to -be shown the first few lines of the new message. -.PP -Next I set the shell variable `time' to `15' causing the shell to automatically -print out statistics lines for commands which execute for at least 15 seconds -of \s-2CPU\s+2 time. The variable `history' is set to 10 indicating that -I want the shell to remember the last 10 commands I type in its -.I "history list" , -(described later). -.PP -I create an -.I alias -``ts'' which executes a -\fItset\fR\|(1) command setting up the modes of the terminal. -The parameters to -.I tset -indicate the kinds of terminal which I usually use when not on a hardwired -port. I then execute ``ts'' and also use the -.I stty -command to change the interrupt character to ^C and the line kill -character to ^U. -.PP -I then run the `msgs' program, which provides me with any -system messages which I have not seen before; the `\-f' option here prevents -it from telling me anything if there are no new messages. -Finally, if my mailbox file exists, then I run the `mail' program to -process my mail. -.PP -When the `mail' and `msgs' programs finish, the shell will finish -processing my -.I \&.login -file and begin reading commands from the terminal, prompting for each with -`% '. -When I log off (by giving the -.I logout -command) the shell -will print `logout' and execute commands from the file `.logout' -if it exists in my home directory. -After that the shell will terminate and \s-2UNIX\s0 will log -me off the system. -If the system is not going down, I will receive a new login message. -In any case, after the `logout' message the shell is committed to terminating -and will take no further input from my terminal. -.NH 2 -Shell variables -.PP -The shell maintains a set of -.I variables. -We saw above the variables -.I history -and -.I time -which had values `10' and `15'. -In fact, each shell variable has as value an array of -zero or more -.I strings. -Shell variables may be assigned values by the set command. It has -several forms, the most useful of which was given above and is -.DS -set name=value -.DE -.PP -Shell variables may be used to store values which are to -be used in commands later through a substitution mechanism. -The shell variables most commonly referenced are, however, those which the -shell itself refers to. -By changing the values of these variables one can directly affect the -behavior of the shell. -.PP -One of the most important variables is the variable -.I path. -This variable contains a sequence of directory names where the shell -searches for commands. -The -.I set -command with no arguments -shows the value of all variables currently defined (we usually say -.I set) -in the shell. -The default value for path will be shown by -.I set -to be -.DS -% set -.ta .75i -argv () -cwd /usr/bill -home /usr/bill -path (. /usr/ucb /bin /usr/bin) -prompt % -shell /bin/csh -status 0 -term c100rv4pna -user bill -% -.so tabs -.DE -This output indicates that the variable path points to the current -directory `.' and then `/usr/ucb', `/bin' and `/usr/bin'. -Commands which you may write might be in `.' (usually one of -your directories). -Commands developed at Berkeley, live in `/usr/ucb' -while commands developed at Bell Laboratories live in `/bin' and `/usr/bin'. -.PP -A number of locally developed programs on the system live in the directory -`/usr/local'. -If we wish that all shells which we invoke to have -access to these new programs we can place the command -.DS -set path=(. /usr/ucb /bin /usr/bin /usr/local) -.DE -in our file -.I \&.cshrc -in our home directory. -Try doing this and then logging out and back in and do -.DS -set -.DE -again to see that the value assigned to -.I path -has changed. -.FS \(dg -Another directory that might interest you is /usr/new, which contains -many useful user-contributed programs provided with Berkeley Unix. -.FE -.PP -One thing you should be aware of is that the shell examines each directory -which you insert into your path and determines which commands are contained -there. Except for the current directory `.', which the shell treats specially, -this means that if commands are added to a directory in your search path after -you have started the shell, they will not necessarily be found by the shell. -If you wish to use a command which has been added in this way, you should -give the command -.DS -rehash -.DE -to the shell, which will cause it to recompute its internal table of command -locations, so that it will find the newly added command. -Since the shell has to look in the current directory `.' on each command, -placing it at the end of the path specification usually works equivalently -and reduces overhead. -.PP -Other useful built in variables are the variable -.I home -which shows your home directory, -.I cwd -which contains your current working directory, -the variable -.I ignoreeof -which can be set in your -.I \&.login -file to tell the shell not to exit when it receives an end-of-file from -a terminal (as described above). -The variable `ignoreeof' -is one of several variables which the shell does not care about the -value of, only whether they are -.I set -or -.I unset. -Thus to set this variable you simply do -.DS -set ignoreeof -.DE -and to unset it do -.DS -unset ignoreeof -.DE -These give the variable `ignoreeof' no value, but none is desired or required. -.PP -Finally, some other built-in shell variables of use are the -variables -.I noclobber -and -.I mail. -The metasyntax -.DS -> filename -.DE -which redirects the standard output of a command -will overwrite and destroy the previous contents of the named file. -In this way you may accidentally overwrite a file which is valuable. -If you would prefer that the shell not overwrite files in this -way you can -.DS -set noclobber -.DE -in your -.I \&.login -file. -Then trying to do -.DS -date > now -.DE -would cause a diagnostic if `now' existed already. -You could type -.DS -date >! now -.DE -if you really wanted to overwrite the contents of `now'. -The `>!' is a special metasyntax indicating that clobbering the -file is ok.\(dg -.FS -\(dgThe space between the `!' and the word `now' is critical here, as `!now' -would be an invocation of the -.I history -mechanism, and have a totally different effect. -.FE -.NH 2 -The shell's history list -.PP -The shell can maintain a -.I "history list" -into which it places the words -of previous commands. -It is possible to use a notation to reuse commands or words -from commands in forming new commands. -This mechanism can be used to repeat previous commands or to -correct minor typing mistakes in commands. -.PP -The following figure gives a sample session involving typical usage of the -history mechanism of the shell. -.KF -.DS -% cat bug.c -main() - -{ - printf("hello); -} -% cc !$ -cc bug.c -"bug.c", line 4: newline in string or char constant -"bug.c", line 5: syntax error -% ed !$ -ed bug.c -29 -4s/);/"&/p - printf("hello"); -w -30 -q -% !c -cc bug.c -% a.out -hello% !e -ed bug.c -30 -4s/lo/lo\e\en/p - printf("hello\en"); -w -32 -q -% !c \-o bug -cc bug.c \-o bug -% size a.out bug -a.out: 2784+364+1028 = 4176b = 0x1050b -bug: 2784+364+1028 = 4176b = 0x1050b -% ls \-l !* -ls \-l a.out bug -\(mirwxr\(mixr\(mix 1 bill 3932 Dec 19 09:41 a.out -\(mirwxr\(mixr\(mix 1 bill 3932 Dec 19 09:42 bug -% bug -hello -% num bug.c | spp -spp: Command not found. -% ^spp^ssp -num bug.c | ssp - 1 main() - 3 { - 4 printf("hello\en"); - 5 } -% !! | lpr -num bug.c | ssp | lpr -% -.DE -.KE -In this example we have a very simple C program which has a bug (or two) -in it in the file `bug.c', which we `cat' out on our terminal. We then -try to run the C compiler on it, referring to the file again as `!$', -meaning the last argument to the previous command. Here the `!' is the -history mechanism invocation metacharacter, and the `$' stands for the last -argument, by analogy to `$' in the editor which stands for the end of the line. -The shell echoed the command, as it would have been typed without use of -the history mechanism, and then executed it. -The compilation yielded error diagnostics so we now run the editor on the -file we were trying to compile, fix the bug, and run the C compiler again, -this time referring to this command simply as `!c', which repeats the last -command which started with the letter `c'. If there were other -commands starting with `c' done recently we could have said `!cc' or even -`!cc:p' which would have printed the last command starting with `cc' -without executing it. -.PP -After this recompilation, we ran the resulting `a.out' file, and then -noting that there still was a bug, ran the editor again. After fixing -the program we ran the C compiler again, but tacked onto the command -an extra `\-o bug' telling the compiler to place the resultant binary in -the file `bug' rather than `a.out'. In general, the history mechanisms -may be used anywhere in the formation of new commands and other characters -may be placed before and after the substituted commands. -.PP -We then ran the `size' command to see how large the binary program images -we have created were, and then an `ls \-l' command with the same argument -list, denoting the argument list `\!*'. -Finally we ran the program `bug' to see that its output is indeed correct. -.PP -To make a numbered listing of the program we ran the `num' command on the file `bug.c'. -In order to compress out blank lines in the output of `num' we ran the -output through the filter `ssp', but misspelled it as spp. To correct this -we used a shell substitute, placing the old text and new text between `^' -characters. This is similar to the substitute command in the editor. -Finally, we repeated the same command with `!!', but sent its output to the -line printer. -.PP -There are other mechanisms available for repeating commands. The -.I history -command prints out a number of previous commands with numbers by which -they can be referenced. There is a way to refer to a previous command -by searching for a string which appeared in it, and there are other, -less useful, ways to select arguments to include in a new command. -A complete description of all these mechanisms -is given in the C shell manual pages in the \s-2UNIX\s0 Programmer's Manual. -.NH 2 -Aliases -.PP -The shell has an -.I alias -mechanism which can be used to make transformations on input commands. -This mechanism can be used to simplify the commands you type, -to supply default arguments to commands, -or to perform transformations on commands and their arguments. -The alias facility is similar to a macro facility. -Some of the features obtained by aliasing can be obtained also -using shell command files, but these take place in another instance -of the shell and cannot directly affect the current shells environment -or involve commands such as -.I cd -which must be done in the current shell. -.PP -As an example, suppose that there is a new version of the mail program -on the system called `newmail' -you wish to use, rather than the standard mail program which is called -`mail'. -If you place the shell command -.DS -alias mail newmail -.DE -in your -.I \&.cshrc -file, the shell will transform an input line of the form -.DS -mail bill -.DE -into a call on `newmail'. -More generally, suppose we wish the command `ls' to always show -sizes of files, that is to always do `\-s'. -We can do -.DS -alias ls ls \-s -.DE -or even -.DS -alias dir ls \-s -.DE -creating a new command syntax `dir' -which does an `ls \-s'. -If we say -.DS -dir ~bill -.DE -then the shell will translate this to -.DS -ls \-s /mnt/bill -.DE -.PP -Thus the -.I alias -mechanism can be used to provide short names for commands, -to provide default arguments, -and to define new short commands in terms of other commands. -It is also possible to define aliases which contain multiple -commands or pipelines, showing where the arguments to the original -command are to be substituted using the facilities of the -history mechanism. -Thus the definition -.DS -alias cd \'cd \e!* ; ls \' -.DE -would do an -.I ls -command after each change directory -.I cd -command. -We enclosed the entire alias definition in `\'' characters to prevent -most substitutions from occurring and the character `;' from being -recognized as a metacharacter. -The `!' here is escaped with a `\e' to prevent it from being interpreted -when the alias command is typed in. -The `\e!*' here substitutes the entire argument list to the pre-aliasing -.I cd -command, without giving an error if there were no arguments. -The `;' separating commands is used here -to indicate that one command is to be done and then the next. -Similarly the definition -.DS -alias whois \'grep \e!^ /etc/passwd\' -.DE -defines a command which looks up its first argument in the password file. -.PP -.B Warning: -The shell currently reads the -.I \&.cshrc -file each time it starts up. If you place a large number of commands -there, shells will tend to start slowly. A mechanism for saving the shell -environment after reading the \fI\&.cshrc\fR file and quickly restoring it is -under development, but for now you should try to limit the number of -aliases you have to a reasonable number... 10 or 15 is reasonable, -50 or 60 will cause a noticeable delay in starting up shells, and make -the system seem sluggish when you execute commands from within the editor -and other programs. -.NH 2 -More redirection; >> and >& -.PP -There are a few more notations useful to the terminal user -which have not been introduced yet. -.PP -In addition to the standard output, commands also have a -.I "diagnostic output" -which is normally directed to the terminal even when the standard output -is redirected to a file or a pipe. -It is occasionally desirable to direct the diagnostic output along with -the standard output. -For instance if you want to redirect the output of a long running command -into a file and wish to have a record of any error diagnostic it produces -you can do -.DS -command >& file -.DE -The `>&' here tells the shell to route both the diagnostic output and the -standard output into `file'. -Similarly you can give the command -.DS -command |\|& lpr -.DE -to route both standard and diagnostic output through the pipe -to the line printer daemon -.I lpr.\(dd -.FS -\(dd A command of the form -.br -.ti +5 -command >&! file -.br -exists, and is used when -.I noclobber -is set and -.I file -already exists. -.FE -.PP -Finally, it is possible to use the form -.DS -command >> file -.DE -to place output at the end of an existing file.\(dg -.FS -\(dg If -.I noclobber -is set, then an error will result if -.I file -does not exist, otherwise the shell will create -.I file -if it doesn't exist. -A form -.br -.ti +5 -command >>! file -.br -makes it not be an error for file to not exist when -.I noclobber -is set. -.FE -.NH 2 -Jobs; Background, Foreground, or Suspended -.PP -When one or more commands -are typed together as a pipeline or as a sequence of commands separated by -semicolons, a single -.I job -is created by the shell consisting of these commands together as a unit. -Single commands without pipes or semicolons create the simplest jobs. -Usually, every line typed to the shell creates a job. -Some lines that create jobs (one per line) are -.DS -sort < data -ls \-s | sort \-n | head \-5 -mail harold -.DE -.PP -If the metacharacter `&' is typed -at the end of the commands, then the job is started as a -.I background -job. This means that the shell does not wait for it to complete but -immediately prompts and is ready for another command. The job runs -.I "in the background" -at the same time that normal jobs, called -.I foreground -jobs, continue to be read and executed by the shell one at a time. -Thus -.DS -du > usage & -.DE -would run the -.I du -program, which reports on the disk usage of your working directory (as well as -any directories below it), put the output into the file `usage' and return -immediately with a prompt for the next command without out waiting for -.I du -to finish. The -.I du -program would continue executing in the background -until it finished, even though you can type and execute more commands in the -mean time. -When a background -job terminates, a message is typed by the shell just before the next prompt -telling you that the job has completed. -In the following example the -.I du -job finishes sometime during the -execution of the -.I mail -command and its completion is reported just before -the prompt after the -.I mail -job is finished. -.DS -% du > usage & -[1] 503 -% mail bill -How do you know when a background job is finished? -EOT -.ta 1.75i -[1] \- Done du > usage -% -.so tabs -.DE -If the job did not terminate normally the `Done' message might say -something else like `Killed'. -If you want the -terminations of background jobs to be reported at the time they occur -(possibly interrupting the output of other foreground jobs), you can set -the -.I notify -variable. In the previous example this would mean that the -`Done' message might have come right in the middle of the message to -Bill. -Background jobs are unaffected by any signals from the keyboard like -the \s-2STOP\s0, \s-2INTERRUPT\s0, or \s-2QUIT\s0 signals mentioned earlier. -.PP -Jobs are recorded in a table inside the shell until they terminate. -In this table, the shell remembers the command names, arguments and the -.I "process numbers" -of all commands in the job as well as the working directory where the job was -started. -Each job in the table is either running -.I "in the foreground" -with the shell waiting for it to terminate, running -.I "in the background," -or -.I suspended. -Only one job can be running in the foreground at one time, but several -jobs can be suspended or running in the background at once. As each job -is started, it is assigned a small identifying -number called the -.I "job number" -which can be used later to refer to the job in the commands described below. -Job numbers remain -the same until the job terminates and then are re-used. -.PP -When a job is started in the backgound using `&', its number, as well -as the process numbers of all its (top level) commands, is typed by the shell -before prompting you for another command. For example, -.DS -% ls \-s | sort \-n > usage & -[2] 2034 2035 -% -.DE -runs the `ls' program with the `\-s' options, pipes this output into -the `sort' program with the `\-n' option which puts its output into the -file `usage'. -Since the `&' was at the end of the line, these two programs were started -together as a background job. After starting the job, the shell prints -the job number in brackets (2 in this case) followed by the process number -of each program started in the job. Then the shell immediates prompts for -a new command, leaving the job running simultaneously. -.PP -As mentioned in section 1.8, foreground jobs become -.I suspended -by typing ^Z -which sends a \s-2STOP\s0 signal to the currently running -foreground job. A background job can become suspended by using the -.I stop -command described below. When jobs are suspended they merely stop -any further progress until started again, either in the foreground -or the backgound. The shell notices when a job becomes stopped and -reports this fact, much like it reports the termination of background jobs. -For foreground jobs this looks like -.DS -% du > usage -^Z -Stopped -% -.DE -`Stopped' message is typed by the shell when it notices that the -.I du -program stopped. -For background jobs, using the -.I stop -command, it is -.DS -% sort usage & -[1] 2345 -% stop %1 -.ta 1.75i -[1] + Stopped (signal) sort usage -% -.so tabs -.DE -Suspending foreground jobs can be very useful when you need to temporarily -change what you are doing (execute other commands) and then return to -the suspended job. Also, foreground jobs can be suspended and then -continued as background jobs using the -.I bg -command, allowing you to continue other work and -stop waiting for the foreground job to finish. Thus -.DS -% du > usage -^Z -Stopped -% bg -[1] du > usage & -% -.DE -starts `du' in the foreground, stops it before it finishes, then continues -it in the background allowing more foreground commands to be executed. -This is especially helpful -when a foreground job ends up taking longer than you expected and you -wish you had started it in the backgound in the beginning. -.PP -All -.I "job control" -commands can take an argument that identifies a particular -job. -All job name arguments begin with the character `%', since some of the -job control commands also accept process numbers (printed by the -.I ps -command.) -The default job (when no argument is given) is called the -.I current -job and is identified by a `+' in the output of the -.I jobs -command, which shows you which jobs you have. -When only one job is stopped or running in the background (the usual case) -it is always the current job thus no argument is needed. -If a job is stopped while running in the foreground it becomes the -.I current -job and the existing current job becomes the -.I previous -job \- identified by a `\-' in the output of -.I jobs. -When the current job terminates, the previous job becomes the current job. -When given, the argument is either `%\-' (indicating -the previous job); `%#', where # is the job number; -`%pref' where pref is some unique prefix of the command name -and arguments of one of the jobs; or `%?' followed by some string found -in only one of the jobs. -.PP -The -.I jobs -command types the table of jobs, giving the job number, -commands and status (`Stopped' or `Running') of each backgound or -suspended job. With the `\-l' option the process numbers are also -typed. -.DS -% du > usage & -[1] 3398 -% ls \-s | sort \-n > myfile & -[2] 3405 -% mail bill -^Z -Stopped -% jobs -.ta 1.75i -[1] \(mi Running du > usage -[2] Running ls \-s | sort \-n > myfile -[3] \(pl Stopped mail bill -% fg %ls -ls \-s | sort \-n > myfile -% more myfile -.so tabs -.DE -.PP -The -.I fg -command runs a suspended or background job in the foreground. It is -used to restart a previously suspended job or change a background job -to run in the foreground (allowing signals or input from the terminal). -In the above example we used -.I fg -to change the `ls' job from the -background to the foreground since we wanted to wait for it to -finish before looking at its output file. -The -.I bg -command runs a suspended job in the background. It is usually used -after stopping the currently running foreground job with the -\s-2STOP\s0 signal. The combination of the \s-2STOP\s0 signal and the -.I bg -command changes a foreground job into a background job. -The -.I stop -command suspends a background job. -.PP -The -.I kill -command terminates a background or suspended job immediately. -In addition to jobs, it may be given process numbers as arguments, -as printed by -.I ps. -Thus, in the example above, the running -.I du -command could have been terminated by the command -.DS -% kill %1 -.ta 1.75i -[1] Terminated du > usage -% -.so tabs -.DE -.PP -The -.I notify -command (not the variable mentioned earlier) indicates that the termination -of a specific job should be -reported at the time it finishes instead of waiting for the next prompt. -.PP -If a job running in the background tries to read input from the terminal -it is automatically stopped. When such a job is then run in the -foreground, input can be given to the job. If desired, the job can -be run in the background again until it requests input again. -This is illustrated in the following sequence where the `s' command in the -text editor might take a long time. -.ID -.nf -% ed bigfile -120000 -1,$s/thisword/thatword/ -^Z -Stopped -% bg -[1] ed bigfile & -% - . . . some foreground commands -.ta 1.75i -[1] Stopped (tty input) ed bigfile -% fg -ed bigfile -w -120000 -q -% -.so tabs -.DE -So after the `s' command was issued, the `ed' job was stopped with ^Z -and then put in the background using -.I bg. -Some time later when the `s' command was finished, -.I ed -tried to read another command and was stopped because jobs -in the backgound cannot read from the terminal. The -.I fg -command returned the `ed' job to the foreground where it could once again -accept commands from the terminal. -.PP -The command -.DS -stty tostop -.DE -causes all background jobs run on your terminal to stop -when they are about to -write output to the terminal. This prevents messages from background -jobs from interrupting foreground job output and allows you to run -a job in the background without losing terminal output. It also -can be used for interactive programs that sometimes have long -periods without interaction. Thus each time it outputs a prompt for more -input it will stop before the prompt. It can then be run in the -foreground using -.I fg, -more input can be given and, if necessary stopped and returned to -the background. This -.I stty -command might be a good thing to put in your -.I \&.login -file if you do not like output from background jobs interrupting -your work. It also can reduce the need for redirecting the output -of background jobs if the output is not very big: -.DS -% stty tostop -% wc hugefile & -[1] 10387 -% ed text -\&. . . some time later -q -.ta 1.75i -[1] Stopped (tty output) wc hugefile -% fg wc -wc hugefile - 13371 30123 302577 -% stty \-tostop -.so tabs -.DE -Thus after some time the `wc' command, which counts the lines, words -and characters in a file, had one line of output. When it tried to -write this to the terminal it stopped. By restarting it in the -foreground we allowed it to write on the terminal exactly when we were -ready to look at its output. -Programs which attempt to change the mode of the terminal will also -block, whether or not -.I tostop -is set, when they are not in the foreground, as -it would be very unpleasant to have a background job change the state -of the terminal. -.PP -Since the -.I jobs -command only prints jobs started in the currently executing shell, -it knows nothing about background jobs started in other login sessions -or within shell files. The -.I ps -can be used in this case to find out about background jobs not started -in the current shell. -.NH 2 -Working Directories -.PP -As mentioned in section 1.6, the shell is always in a particular -.I "working directory." -The `change directory' command -.I chdir -(its -short form -.I cd -may also be used) -changes the working directory of the shell, -that is, changes the directory you -are located in. -.PP -It is useful to make a directory for each project you wish to work on -and to place all files related to that project in that directory. -The `make directory' command, -.I mkdir, -creates a new directory. -The -.I pwd -(`print working directory') command -reports the absolute pathname of the working directory of the shell, -that is, the directory you are -located in. -Thus in the example below: -.DS -% pwd -/usr/bill -% mkdir newpaper -% chdir newpaper -% pwd -/usr/bill/newpaper -% -.DE -the user has created and moved to the -directory -.I newpaper. -where, for example, he might -place a group of related files. -.PP -No matter where you have moved to in a directory hierarchy, -you can return to your `home' login directory by doing just -.DS -cd -.DE -with no arguments. -The name `..' always means the directory above the current one in -the hierarchy, thus -.DS -cd .. -.DE -changes the shell's working directory to the one directly above the -current one. -The name `..' can be used in any -pathname, thus, -.DS -cd ../programs -.DE -means -change to the directory `programs' contained in the directory -above the current one. -If you have several directories for different -projects under, say, your home directory, -this shorthand notation -permits you to switch easily between them. -.PP -The shell always remembers the pathname of its current working directory in -the variable -.I cwd. -The shell can also be requested to remember the previous directory when -you change to a new working directory. If the `push directory' command -.I pushd -is used in place of the -.I cd -command, the shell saves the name of the current working directory -on a -.I "directory stack" -before changing to the new one. -You can see this list at any time by typing the `directories' -command -.I dirs. -.ID -.nf -% pushd newpaper/references -~/newpaper/references ~ -% pushd /usr/lib/tmac -/usr/lib/tmac ~/newpaper/references ~ -% dirs -/usr/lib/tmac ~/newpaper/references ~ -% popd -~/newpaper/references ~ -% popd -~ -% -.DE -The list is printed in a horizontal line, reading left to right, -with a tilde (~) as -shorthand for your home directory\(emin this case `/usr/bill'. -The directory stack is printed whenever there is more than one -entry on it and it changes. -It is also printed by a -.I dirs -command. -.I Dirs -is usually faster and more informative than -.I pwd -since it shows the current working directory as well as any -other directories remembered in the stack. -.PP -The -.I pushd -command with no argument -alternates the current directory with the first directory in the -list. -The `pop directory' -.I popd -command without an argument returns you to the directory you were in prior to -the current one, discarding the previous current directory from the -stack (forgetting it). -Typing -.I popd -several times in a series takes you backward through the directories -you had been in (changed to) by -.I pushd -command. -There are other options to -.I pushd -and -.I popd -to manipulate the contents of the directory stack and to change -to directories not at the top of the stack; see the -.I csh -manual page for details. -.PP -Since the shell remembers the working directory in which each job -was started, it warns you when you might be confused by restarting -a job in the foreground which has a different working directory than the -current working directory of the shell. Thus if you start a background -job, then change the shell's working directory and then cause the -background job to run in the foreground, the shell warns you that the -working directory of the currently running foreground job is different -from that of the shell. -.DS -% dirs \-l -/mnt/bill -% cd myproject -% dirs -~/myproject -% ed prog.c -1143 -^Z -Stopped -% cd .. -% ls -myproject -textfile -% fg -ed prog.c (wd: ~/myproject) -.DE -This way the shell warns you when there -is an implied change of working directory, even though no cd command was -issued. In the above example the `ed' job was still in `/mnt/bill/project' -even though the shell had changed to `/mnt/bill'. -A similar warning is given when such a foreground job -terminates or is suspended (using the \s-2STOP\s0 signal) since -the return to the shell again implies a change of working directory. -.DS -% fg -ed prog.c (wd: ~/myproject) - . . . after some editing -q -(wd now: ~) -% -.DE -These messages are sometimes confusing if you use programs that change -their own working directories, since the shell only remembers which -directory a job is started in, and assumes it stays there. -The `\-l' option of -.I jobs -will type the working directory -of suspended or background jobs when it is different -from the current working directory of the shell. -.NH 2 -Useful built-in commands -.PP -We now give a few of the useful built-in commands of the shell describing -how they are used. -.PP -The -.I alias -command described above is used to assign new aliases and to show the -existing aliases. -With no arguments it prints the current aliases. -It may also be given only one argument such as -.DS -alias ls -.DE -to show the current alias for, e.g., `ls'. -.PP -The -.I echo -command prints its arguments. -It is often used in -.I "shell scripts" -or as an interactive command -to see what filename expansions will produce. -.PP -The -.I history -command will show the contents of the history list. -The numbers given with the history events can be used to reference -previous events which are difficult to reference using the -contextual mechanisms introduced above. -There is also a shell variable called -.I prompt. -By placing a `!' character in its value the shell will there substitute -the number of the current command in the history list. -You can use this number to refer to this command in a history substitution. -Thus you could -.DS -set prompt=\'\e! % \' -.DE -Note that the `!' character had to be -.I escaped -here even within `\'' characters. -.PP -The -.I limit -command is used to restrict use of resources. -With no arguments it prints the current limitations: -.DS -.ta 1i -cputime unlimited -filesize unlimited -datasize 5616 kbytes -stacksize 512 kbytes -coredumpsize unlimited -.so tabs -.DE -Limits can be set, e.g.: -.DS -limit coredumpsize 128k -.DE -Most reasonable units abbreviations will work; see the -.I csh -manual page for more details. -.PP -The -.I logout -command can be used to terminate a login shell which has -.I ignoreeof -set. -.PP -The -.I rehash -command causes the shell to recompute a table of where commands are -located. This is necessary if you add a command to a directory -in the current shell's search path and wish the shell to find it, -since otherwise the hashing algorithm may tell the shell that the -command wasn't in that directory when the hash table was computed. -.PP -The -.I repeat -command can be used to repeat a command several times. -Thus to make 5 copies of the file -.I one -in the file -.I five -you could do -.DS -repeat 5 cat one >> five -.DE -.PP -The -.I setenv -command can be used -to set variables in the environment. -Thus -.DS -setenv TERM adm3a -.DE -will set the value of the environment variable \s-2TERM\s0 -to -`adm3a'. -A user program -.I printenv -exists which will print out the environment. -It might then show: -.DS -% printenv -HOME=/usr/bill -SHELL=/bin/csh -PATH=:/usr/ucb:/bin:/usr/bin:/usr/local -TERM=adm3a -USER=bill -% -.DE -.PP -The -.I source -command can be used to force the current shell to read commands from -a file. -Thus -.DS -source .cshrc -.DE -can be used after editing in a change to the -.I \&.cshrc -file which you wish to take effect right away. -.PP -The -.I time -command can be used to cause a command to be timed no matter how much -\s-2CPU\s0 time it takes. -Thus -.DS -% time cp /etc/rc /usr/bill/rc -0.0u 0.1s 0:01 8% 2+1k 3+2io 1pf+0w -% time wc /etc/rc /usr/bill/rc - 52 178 1347 /etc/rc - 52 178 1347 /usr/bill/rc - 104 356 2694 total -0.1u 0.1s 0:00 13% 3+3k 5+3io 7pf+0w -% -.DE -indicates that the -.I cp -command used a negligible amount of user time (u) -and about 1/10th of a system time (s); the elapsed time was 1 second (0:01), -there was an average memory usage of 2k bytes of program space and 1k -bytes of data space over the cpu time involved (2+1k); the program -did three disk reads and two disk writes (3+2io), and took one page fault -and was not swapped (1pf+0w). -The word count command -.I wc -on the other hand used 0.1 seconds of user time and 0.1 seconds of system -time in less than a second of elapsed time. -The percentage `13%' indicates that over the period when it was active -the command `wc' used an average of 13 percent of the available \s-2CPU\s0 -cycles of the machine. -.PP -The -.I unalias -and -.I unset -commands can be used -to remove aliases and variable definitions from the shell, and -.I unsetenv -removes variables from the environment. -.NH 2 -What else? -.PP -This concludes the basic discussion of the shell for terminal users. -There are more features of the shell to be discussed here, and all -features of the shell are discussed in its manual pages. -One useful feature which is discussed later is the -.I foreach -built-in command which can be used to run the same command -sequence with a number of different arguments. -.PP -If you intend to use \s-2UNIX\s0 a lot you you should look through -the rest of this document and the csh manual pages (section1) to become familiar -with the other facilities which are available to you. -.bp diff --git a/bin/csh/USD.doc/csh.3 b/bin/csh/USD.doc/csh.3 deleted file mode 100644 index a6a6f66e8..000000000 --- a/bin/csh/USD.doc/csh.3 +++ /dev/null @@ -1,648 +0,0 @@ -.\" $NetBSD: csh.3,v 1.5 2003/08/07 09:05:08 agc Exp $ -.\" -.\" Copyright (c) 1980, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)csh.3 8.1 (Berkeley) 6/8/93 -.\" -.nr H1 2 -.NH -Shell control structures and command scripts -.NH 2 -Introduction -.PP -It is possible to place commands in files and to cause shells to be -invoked to read and execute commands from these files, -which are called -.I "shell scripts." -We here detail those features of the shell useful to the writers of such -scripts. -.NH 2 -Make -.PP -It is important to first note what shell scripts are -.I not -useful for. -There is a program called -.I make -which is very useful for maintaining a group of related files -or performing sets of operations on related files. -For instance a large program consisting of one or more files -can have its dependencies described in a -.I makefile -which contains definitions of the commands used to create these -different files when changes occur. -Definitions of the means for printing listings, cleaning up the directory -in which the files reside, and installing the resultant programs -are easily, and most appropriately placed in this -.I makefile. -This format is superior and preferable to maintaining a group of shell -procedures to maintain these files. -.PP -Similarly when working on a document a -.I makefile -may be created which defines how different versions of the document -are to be created and which options of -.I nroff -or -.I troff -are appropriate. -.NH 2 -Invocation and the argv variable -.PP -A -.I csh -command script may be interpreted by saying -.DS -% csh script ... -.DE -where -.I script -is the name of the file containing a group of -.I csh -commands and -`\&...' is replaced by a sequence of arguments. -The shell places these arguments in the variable -.I argv -and then begins to read commands from the script. -These parameters are then available through the same mechanisms -which are used to reference any other shell variables. -.PP -If you make the file -`script' -executable by doing -.DS -chmod 755 script -.DE -and place a shell comment at the beginning of the shell script -(i.e. begin the file with a `#' character) -then a `/bin/csh' will automatically be invoked to execute `script' when -you type -.DS -script -.DE -If the file does not begin with a `#' then the standard shell -`/bin/sh' will be used to execute it. -This allows you to convert your older shell scripts to use -.I csh -at your convenience. -.NH 2 -Variable substitution -.PP -After each input line is broken into words and history substitutions -are done on it, the input line is parsed into distinct commands. -Before each command is executed a mechanism know as -.I "variable substitution" -is done on these words. -Keyed by the character `$' this substitution replaces the names -of variables by their values. -Thus -.DS -echo $argv -.DE -when placed in a command script would cause the current value of the -variable -.I argv -to be echoed to the output of the shell script. -It is an error for -.I argv -to be unset at this point. -.PP -A number of notations are provided for accessing components and attributes -of variables. -The notation -.DS -$?name -.DE -expands to `1' if name is -.I set -or to `0' -if name is not -.I set. -It is the fundamental mechanism used for checking whether particular -variables have been assigned values. -All other forms of reference to undefined variables cause errors. -.PP -The notation -.DS -$#name -.DE -expands to the number of elements in the variable -.I name. -Thus -.DS -% set argv=(a b c) -% echo $?argv -1 -% echo $#argv -3 -% unset argv -% echo $?argv -0 -% echo $argv -Undefined variable: argv. -% -.DE -.PP -It is also possible to access the components of a variable -which has several values. -Thus -.DS -$argv[1] -.DE -gives the first component of -.I argv -or in the example above `a'. -Similarly -.DS -$argv[$#argv] -.DE -would give `c', -and -.DS -$argv[1\-2] -.DE -would give `a b'. Other notations useful in shell scripts are -.DS -$\fIn\fR -.DE -where -.I n -is an integer as a shorthand for -.DS -$argv[\fIn\fR\|] -.DE -the -.I n\|th -parameter and -.DS -$* -.DE -which is a shorthand for -.DS -$argv -.DE -The form -.DS -$$ -.DE -expands to the process number of the current shell. -Since this process number is unique in the system it can -be used in generation of unique temporary file names. -The form -.DS -$< -.DE -is quite special and is replaced by the next line of input read from -the shell's standard input (not the script it is reading). This is -useful for writing shell scripts that are interactive, reading -commands from the terminal, or even writing a shell script that -acts as a filter, reading lines from its input file. Thus the sequence -.DS -echo 'yes or no?\ec' -set a=($<) -.DE -would write out the prompt `yes or no?' without a newline and then -read the answer into the variable `a'. In this case `$#a' would be -`0' if either a blank line or end-of-file (^D) was typed. -.PP -One minor difference between `$\fIn\fR\|' and `$argv[\fIn\fR\|]' -should be noted here. -The form -`$argv[\fIn\fR\|]' -will yield an error if -.I n -is not in the range -`1\-$#argv' -while `$n' -will never yield an out of range subscript error. -This is for compatibility with the way older shells handled parameters. -.PP -Another important point is that it is never an error to give a subrange -of the form `n\-'; if there are less than -.I n -components of the given variable then no words are substituted. -A range of the form `m\-n' likewise returns an empty vector without giving -an error when \fIm\fR exceeds the number of elements of the given variable, -provided the subscript \fIn\fR is in range. -.NH 2 -Expressions -.PP -In order for interesting shell scripts to be constructed it -must be possible to evaluate expressions in the shell based on the -values of variables. -In fact, all the arithmetic operations of the language C are available -in the shell -with the same precedence that they have in C. -In particular, the operations `==' and `!=' compare strings -and the operators `&&' and `|\|\||' implement the boolean and/or operations. -The special operators `=~' and `!~' are similar to `==' and `!=' except -that the string on the right side can have pattern matching characters -(like *, ? or []) and the test is whether the string on the left matches -the pattern on the right. -.PP -The shell also allows file enquiries of the form -.DS -\-? filename -.DE -where `?' is replace by a number of single characters. -For instance the expression primitive -.DS -\-e filename -.DE -tell whether the file -`filename' -exists. -Other primitives test for read, write and execute access to the file, -whether it is a directory, or has non-zero length. -.PP -It is possible to test whether a command terminates normally, -by a primitive of the -form `{ command }' which returns true, i.e. `1' if the command -succeeds exiting normally with exit status 0, or `0' if the command -terminates abnormally or with exit status non-zero. -If more detailed information about the execution status of a command -is required, it can be executed and the variable `$status' examined -in the next command. -Since `$status' is set by every command, it is very transient. -It can be saved if it is inconvenient to use it only in the single -immediately following command. -.PP -For a full list of expression components available see the manual -section for the shell. -.NH 2 -Sample shell script -.PP -A sample shell script which makes use of the expression mechanism -of the shell and some of its control structure follows: -.DS -% cat copyc -# -# Copyc copies those C programs in the specified list -# to the directory ~/backup if they differ from the files -# already in ~/backup -# -set noglob -foreach i ($argv) - - if ($i !~ *.c) continue # not a .c file so do nothing - - if (! \-r ~/backup/$i:t) then - echo $i:t not in backup... not cp\e\'ed - continue - endif - - cmp \-s $i ~/backup/$i:t # to set $status - - if ($status != 0) then - echo new backup of $i - cp $i ~/backup/$i:t - endif -end -.DE -.PP -This script makes use of the -.I foreach -command, which causes the shell to execute the commands between the -.I foreach -and the matching -.I end -for each of the values given between `(' and `)' with the named -variable, in this case `i' set to successive values in the list. -Within this loop we may use the command -.I break -to stop executing the loop -and -.I continue -to prematurely terminate one iteration -and begin the next. -After the -.I foreach -loop the iteration variable -(\fIi\fR in this case) -has the value at the last iteration. -.PP -We set the variable -.I noglob -here to prevent filename expansion of the members of -.I argv. -This is a good idea, in general, if the arguments to a shell script -are filenames which have already been expanded or if the arguments -may contain filename expansion metacharacters. -It is also possible to quote each use of a `$' variable expansion, -but this is harder and less reliable. -.PP -The other control construct used here is a statement of the form -.DS -\fBif\fR ( expression ) \fBthen\fR - command - ... -\fBendif\fR -.DE -The placement of the keywords here is -.B not -flexible due to the current implementation of the shell.\(dg -.FS -\(dgThe following two formats are not currently acceptable to the shell: -.sp -.in +5 -.nf -\fBif\fR ( expression ) # \fBWon't work!\fR -\fBthen\fR - command - ... -\fBendif\fR -.fi -.in -5 -.sp -and -.sp -.in +5 -.nf -\fBif\fR ( expression ) \fBthen\fR command \fBendif\fR # \fBWon't work\fR -.in -5 -.fi -.FE -.PP -The shell does have another form of the if statement of the form -.DS -\fBif\fR ( expression ) \fBcommand\fR -.DE -which can be written -.DS -\fBif\fR ( expression ) \e - command -.DE -Here we have escaped the newline for the sake of appearance. -The command must not involve `\||\|', `&' or `;' -and must not be another control command. -The second form requires the final `\e' to -.B immediately -precede the end-of-line. -.PP -The more general -.I if -statements above also admit a sequence of -.I else\-if -pairs followed by a single -.I else -and an -.I endif, -e.g.: -.DS -\fBif\fR ( expression ) \fBthen\fR - commands -\fBelse\fR \fBif\fR (expression ) \fBthen\fR - commands -\&... - -\fBelse\fR - commands -\fBendif\fR -.DE -.PP -Another important mechanism used in shell scripts is the `:' modifier. -We can use the modifier `:r' here to extract a root of a filename or -`:e' to extract the -.I extension. -Thus if the variable -.I i -has the value -`/mnt/foo.bar' -then -.sp -.in +5 -.nf -% echo $i $i:r $i:e -/mnt/foo.bar /mnt/foo bar -% -.sp -.in -5 -.fi -shows how the `:r' modifier strips off the trailing `.bar' and the -the `:e' modifier leaves only the `bar'. -Other modifiers will take off the last component of a pathname leaving -the head `:h' or all but the last component of a pathname leaving the -tail `:t'. -These modifiers are fully described in the -.I csh -manual pages in the User's Reference Manual. -It is also possible to use the -.I "command substitution" -mechanism described in the next major section to perform modifications -on strings to then reenter the shell's environment. -Since each usage of this mechanism involves the creation of a new process, -it is much more expensive to use than the `:' modification mechanism.\(dd -.FS -\(dd It is also important to note that -the current implementation of the shell limits the number of `:' modifiers -on a `$' substitution to 1. -Thus -.sp -.nf -.in +5 -% echo $i $i:h:t -/a/b/c /a/b:t -% -.in -5 -.fi -.sp -does not do what one would expect. -.FE -Finally, we note that the character `#' lexically introduces a shell -comment in shell scripts (but not from the terminal). -All subsequent characters on the input line after a `#' are discarded -by the shell. -This character can be quoted using `\'' or `\e' to place it in -an argument word. -.NH 2 -Other control structures -.PP -The shell also has control structures -.I while -and -.I switch -similar to those of C. -These take the forms -.DS -\fBwhile\fR ( expression ) - commands -\fBend\fR -.DE -and -.DS -\fBswitch\fR ( word ) - -\fBcase\fR str1: - commands - \fBbreaksw\fR - -\& ... - -\fBcase\fR strn: - commands - \fBbreaksw\fR - -\fBdefault:\fR - commands - \fBbreaksw\fR - -\fBendsw\fR -.DE -For details see the manual section for -.I csh. -C programmers should note that we use -.I breaksw -to exit from a -.I switch -while -.I break -exits a -.I while -or -.I foreach -loop. -A common mistake to make in -.I csh -scripts is to use -.I break -rather than -.I breaksw -in switches. -.PP -Finally, -.I csh -allows a -.I goto -statement, with labels looking like they do in C, i.e.: -.DS -loop: - commands - \fBgoto\fR loop -.DE -.NH 2 -Supplying input to commands -.PP -Commands run from shell scripts receive by default the standard -input of the shell which is running the script. -This is different from previous shells running -under \s-2UNIX\s0. It allows shell scripts to fully participate -in pipelines, but mandates extra notation for commands which are to take -inline data. -.PP -Thus we need a metanotation for supplying inline data to commands in -shell scripts. -As an example, consider this script which runs the editor to -delete leading blanks from the lines in each argument file: -.DS -% cat deblank -# deblank \-\- remove leading blanks -foreach i ($argv) -ed \- $i << \'EOF\' -1,$s/^[ ]*// -w -q -\&\'EOF\' -end -% -.DE -The notation `<< \'EOF\'' -means that the standard input for the -.I ed -command is to come from the text in the shell script file -up to the next line consisting of exactly `\'EOF\''. -The fact that the `EOF' is enclosed in `\'' characters, i.e. quoted, -causes the shell to not perform variable substitution on the -intervening lines. -In general, if any part of the word following the `<<' which the -shell uses to terminate the text to be given to the command is quoted -then these substitutions will not be performed. -In this case since we used the form `1,$' in our editor script -we needed to insure that this `$' was not variable substituted. -We could also have insured this by preceding the `$' here with a `\e', -i.e.: -.DS -1,\e$s/^[ ]*// -.DE -but quoting the `EOF' terminator is a more reliable way of achieving the -same thing. -.NH 2 -Catching interrupts -.PP -If our shell script creates temporary files, we may wish to catch -interruptions of the shell script so that we can clean up -these files. -We can then do -.DS -onintr label -.DE -where -.I label -is a label in our program. -If an interrupt is received the shell will do a -`goto label' -and we can remove the temporary files and then do an -.I exit -command (which is built in to the shell) -to exit from the shell script. -If we wish to exit with a non-zero status we can do -.DS -exit(1) -.DE -e.g. to exit with status `1'. -.NH 2 -What else? -.PP -There are other features of the shell useful to writers of shell -procedures. -The -.I verbose -and -.I echo -options and the related -.I \-v -and -.I \-x -command line options can be used to help trace the actions of the shell. -The -.I \-n -option causes the shell only to read commands and not to execute -them and may sometimes be of use. -.PP -One other thing to note is that -.I csh -will not execute shell scripts which do not begin with the -character `#', that is shell scripts that do not begin with a comment. -Similarly, the `/bin/sh' on your system may well defer to `csh' -to interpret shell scripts which begin with `#'. -This allows shell scripts for both shells to live in harmony. -.PP -There is also another quotation mechanism using `"' which allows -only some of the expansion mechanisms we have so far discussed to occur -on the quoted string and serves to make this string into a single word -as `\'' does. -.bp diff --git a/bin/csh/USD.doc/csh.4 b/bin/csh/USD.doc/csh.4 deleted file mode 100644 index d4760ce80..000000000 --- a/bin/csh/USD.doc/csh.4 +++ /dev/null @@ -1,176 +0,0 @@ -.\" $NetBSD: csh.4,v 1.4 2003/08/07 09:05:08 agc Exp $ -.\" -.\" Copyright (c) 1980, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)csh.4 8.1 (Berkeley) 6/8/93 -.\" -.nr H1 3 -.NH -Other, less commonly used, shell features -.NH 2 -Loops at the terminal; variables as vectors -.PP -It is occasionally useful to use the -.I foreach -control structure at the terminal to aid in performing a number -of similar commands. -For instance, there were at one point three shells in use on the Cory \s-2UNIX\s0 -system at Cory Hall, -`/bin/sh', -`/bin/nsh', -and -`/bin/csh'. -To count the number of persons using each shell one could have issued -the commands -.DS -% grep \-c csh$ /etc/passwd -27 -% grep \-c nsh$ /etc/passwd -128 -% grep \-c \-v sh$ /etc/passwd -430 -% -.DE -Since these commands are very similar we can use -.I foreach -to do this more easily. -.DS -% foreach i (\'sh$\' \'csh$\' \'\-v sh$\') -? grep \-c $i /etc/passwd -? end -27 -128 -430 -% -.DE -Note here that the shell prompts for -input with `? ' when reading the body of the loop. -.PP -Very useful with loops are variables which contain lists of filenames -or other words. -You can, for example, do -.DS -% set a=(\`ls\`) -% echo $a -csh.n csh.rm -% ls -csh.n -csh.rm -% echo $#a -2 -% -.DE -The -.I set -command here gave the variable -.I a -a list of all the filenames in the current directory as value. -We can then iterate over these names to perform any chosen function. -.PP -The output of a command within `\`' characters is converted by -the shell to a list of words. -You can also place the `\`' quoted string within `"' characters -to take each (non-empty) line as a component of the variable; -preventing the lines from being split into words at blanks and tabs. -A modifier `:x' exists which can be used later to expand each component -of the variable into another variable splitting it into separate words -at embedded blanks and tabs. -.NH 2 -Braces { ... } in argument expansion -.PP -Another form of filename expansion, alluded -to before involves the characters `{' and `}'. -These characters specify that the contained strings, separated by `,' -are to be consecutively substituted into the containing characters -and the results expanded left to right. -Thus -.DS -A{str1,str2,...strn}B -.DE -expands to -.DS -Astr1B Astr2B ... AstrnB -.DE -This expansion occurs before the other filename expansions, and may -be applied recursively (i.e. nested). -The results of each expanded string are sorted separately, left -to right order being preserved. -The resulting filenames are not required to exist if no other expansion -mechanisms are used. -This means that this mechanism can be used to generate arguments which are -not filenames, but which have common parts. -.PP -A typical use of this would be -.DS -mkdir ~/{hdrs,retrofit,csh} -.DE -to make subdirectories `hdrs', `retrofit' and `csh' -in your home directory. -This mechanism is most useful when the common prefix is longer -than in this example, i.e. -.DS -chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}} -.DE -.NH 2 -Command substitution -.PP -A command enclosed in `\`' characters is replaced, just before -filenames are expanded, by the output from that command. -Thus it is possible to do -.DS -set pwd=\`pwd\` -.DE -to save the current directory in the variable -.I pwd -or to do -.DS -ex \`grep \-l TRACE *.c\` -.DE -to run the editor -.I ex -supplying as arguments those files whose names end in `.c' -which have the string `TRACE' in them.* -.FS -*Command expansion also occurs in input redirected with `<<' -and within `"' quotations. -Refer to the shell manual section for full details. -.FE -.NH 2 -Other details not covered here -.PP -In particular circumstances it may be necessary to know the exact -nature and order of different substitutions performed by the shell. -The exact meaning of certain combinations of quotations is also -occasionally important. -These are detailed fully in its manual section. -.PP -The shell has a number of command line option flags mostly of use -in writing \s-2UNIX\s0 programs, -and debugging shell scripts. -See the csh(1) manual section for a list of these options. -.bp diff --git a/bin/csh/USD.doc/csh.ap b/bin/csh/USD.doc/csh.ap deleted file mode 100644 index 7e71070ad..000000000 --- a/bin/csh/USD.doc/csh.ap +++ /dev/null @@ -1,93 +0,0 @@ -.\" $NetBSD: csh.ap,v 1.1 2007/10/18 18:26:31 tls Exp $ -.\" -.\" Copyright (c) 1980, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)csh.a 8.1 (Berkeley) 6/8/93 -.\" -.SH -Appendix \- Special characters -.LP -The following table lists the special characters of -.I csh -and the \s-2UNIX\s0 system, giving for each the section(s) in which it -is discussed. -A number of these characters also have special meaning in expressions. -See the -.I csh -manual section -for a complete list. -.ta .75i 1.5i 2.25i -.LP -Syntactic metacharacters -.DS -; 2.4 separates commands to be executed sequentially -| 1.5 separates commands in a pipeline -( ) 2.2,3.6 brackets expressions and variable values -& 2.5 follows commands to be executed without waiting for completion -.DE -.LP -Filename metacharacters -.DS -/ 1.6 separates components of a file's pathname -\&. 1.6 separates root parts of a file name from extensions -? 1.6 expansion character matching any single character -* 1.6 expansion character matching any sequence of characters -[ ] 1.6 expansion sequence matching any single character from a set -~ 1.6 used at the beginning of a filename to indicate home directories -{ } 4.2 used to specify groups of arguments with common parts -.DE -.LP -Quotation metacharacters -.DS -\e 1.7 prevents meta-meaning of following single character -\' 1.7 prevents meta-meaning of a group of characters -" 4.3 like \', but allows variable and command expansion -.DE -.LP -Input/output metacharacters -.DS -< 1.5 indicates redirected input -> 1.3 indicates redirected output -.DE -.LP -Expansion/substitution metacharacters -.DS -$ 3.4 indicates variable substitution -! 2.3 indicates history substitution -: 3.6 precedes substitution modifiers -^ 2.3 used in special forms of history substitution -\` 4.3 indicates command substitution -.DE -.LP -Other metacharacters -.DS -# 1.3,3.6 begins scratch file names; indicates shell comments -\- 1.2 prefixes option (flag) arguments to commands -% 2.6 prefixes job name specifications -.DE -.bp diff --git a/bin/csh/USD.doc/csh.g b/bin/csh/USD.doc/csh.g deleted file mode 100644 index 09f2baf84..000000000 --- a/bin/csh/USD.doc/csh.g +++ /dev/null @@ -1,1719 +0,0 @@ -.\" $NetBSD: csh.g,v 1.5 2003/08/07 09:05:08 agc Exp $ -.\" -.\" Copyright (c) 1980, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)csh.g 8.1 (Berkeley) 6/8/93 -.\" -.SH -Glossary -.PP -This glossary lists the most important terms introduced in the -introduction to the -shell and gives references to sections of the shell -document for further information about them. -References of the form -`pr (1)' -indicate that the command -.I pr -is in the \s-2UNIX\s0 User Reference manual in section 1. -You can look at an online copy of its manual page by doing -.DS -man 1 pr -.DE -References of the form (2.5) -indicate that more information can be found in section 2.5 of this -manual. -.IP \&\fB.\fR 15n -Your current directory has the name `.' as well as the name printed -by the command -.I pwd; -see also -.I dirs. -The current directory `.' is usually the first -.I component -of the search path contained in the variable -.I path , -thus commands which are in `.' are found first (2.2). -The character `.' is also used in separating -.I components -of filenames -(1.6). -The character `.' at the beginning of a -.I component -of a -.I pathname -is treated specially and not matched by the -.I "filename expansion" -metacharacters `?', `*', and `[' `]' pairs (1.6). -.IP \&\fB..\fR -Each directory has a file `..' in it which is a reference to its -parent directory. -After changing into the directory with -.I chdir , -i.e. -.DS -chdir paper -.DE -you can return to the parent directory by doing -.DS -chdir .. -.DE -The current directory is printed by -.I pwd -(2.7). -.IP a.out -Compilers which create executable images create them, by default, in the -file -.I a.out. -for historical reasons (2.3). -.IP "absolute pathname" -.br -A -.I pathname -which begins with a `/' is -.I absolute -since it specifies the -.I path -of directories from the beginning -of the entire directory system \- called the -.I root -directory. -.I Pathname s -which are not -.I absolute -are called -.I relative -(see definition of -.I "relative pathname" ) -(1.6). -.IP alias -An -.I alias -specifies a shorter or different name for a \s-2UNIX\s0 -command, or a transformation on a command to be performed in -the shell. -The shell has a command -.I alias -which establishes -.I aliases -and can print their current values. -The command -.I unalias -is used to remove -.I aliases -(2.4). -.IP argument -Commands in \s-2UNIX\s0 receive a list of -.I argument -words. -Thus the command -.DS -echo a b c -.DE -consists of the -.I "command name" -`echo' and three -.I argument -words `a', `b' and `c'. -The set of -.I arguments -after the -.I "command name" -is said to be the -.I "argument list" -of the command (1.1). -.IP argv -The list of arguments to a command written in the shell language -(a shell script or shell procedure) is stored in a variable called -.I argv -within the shell. -This name is taken from the conventional name in the -C programming language (3.4). -.IP background -Commands started without waiting for them to complete are called -.I background -commands (2.6). -.IP base -A filename is sometimes thought of as consisting of a -.I base -part, before any `.' character, and an -.I extension -\- the part after -the `.'. See -.I filename -and -.I extension -(1.6) and basename (1). -.IP bg -The -.I bg -command causes a -.I suspended -job to continue execution in the -.I background -(2.6). -.IP bin -A directory containing binaries of programs and shell scripts to be -executed is typically called a -.I bin -directory. -The standard system -.I bin -directories are `/bin' containing the most -heavily used commands and `/usr/bin' which contains most other user -programs. -Programs developed at UC Berkeley live in `/usr/ucb', while locally -written programs live in `/usr/local'. Games are kept in the directory -`/usr/games'. -You can place binaries in any directory. -If you wish to execute them often, the name of the directories -should be a -.I component -of the variable -.I path . -.IP break -.I Break -is a builtin command used to exit from loops within the control -structure of the shell (3.7). -.IP breaksw -The -.I breaksw -builtin command is used to exit from a -.I switch -control structure, like a -.I break -exits from loops (3.7). -.IP builtin -A command executed directly by the shell is called a -.I builtin -command. -Most commands in \s-2UNIX\s0 are not built into the shell, -but rather exist as files in -.I bin -directories. -These commands are accessible because the directories in which -they reside are named in the -.I path -variable. -.IP case -A -.I case -command is used as a label in a -.I switch -statement in the shell's control structure, similar to that of the -language C. -Details are given in the shell documentation `csh (1)' (3.7). -.IP cat -The -.I cat -program catenates a list of specified files on the -.I "standard output" . -It is usually used to look at the contents of a single file on the terminal, -to `cat a file' (1.8, 2.3). -.IP cd -The -.I cd -command is used to change the -.I "working directory" . -With no arguments, -.I cd -changes your -.I "working directory" -to be your -.I home -directory (2.4, 2.7). -.IP chdir -The -.I chdir -command is a synonym for -.I cd . -.I Cd -is usually used because it is easier to type. -.IP chsh -The -.I chsh -command is used to change the shell which you use on \s-2UNIX\s0. -By default, you use an different version of the shell -which resides in `/bin/sh'. -You can change your shell to `/bin/csh' by doing -.DS -chsh your-login-name /bin/csh -.DE -Thus I would do -.DS -chsh bill /bin/csh -.DE -It is only necessary to do this once. -The next time you log in to \s-2UNIX\s0 after doing this command, -you will be using -.I csh -rather than the shell in `/bin/sh' (1.9). -.IP cmp -.I Cmp -is a program which compares files. -It is usually used on binary files, or to see if two files are identical (3.6). -For comparing text files the program -.I diff , -described in `diff (1)' is used. -.IP command -A function performed by the system, either by the shell -(a builtin -.I command ) -or by a program residing in a file in -a directory within the \s-2UNIX\s0 system, is called a -.I command -(1.1). -.IP "command name" -.br -When a command is issued, it consists of a -.I "command name" , -which is the first word of the command, -followed by arguments. -The convention on \s-2UNIX\s0 is that the first word of a -command names the function to be performed (1.1). -.IP "command substitution" -.br -The replacement of a command enclosed in `\`' characters -by the text output by that command -is called -.I "command substitution" -(4.3). -.IP component -A part of a -.I pathname -between `/' characters is called a -.I component -of that -.I pathname . -A variable -which has multiple strings as value is said to have -several -.I component s; -each string is a -.I component -of the variable. -.IP continue -A builtin command which causes execution of the enclosing -.I foreach -or -.I while -loop to cycle prematurely. -Similar to the -.I continue -command in the programming language C (3.6). -.IP control- -Certain special characters, called -.I control -characters, are produced by holding down the \s-2CONTROL\s0 key -on your terminal and simultaneously pressing another character, much like -the \s-2SHIFT\s0 key is used to produce upper case characters. Thus -.I control- c -is produced by holding down the \s-2CONTROL\s0 key while pressing the -`c' key. Usually \s-2UNIX\s0 prints an caret (^) followed by the -corresponding letter when you type a -.I control -character (e.g. `^C' for -.I control- c -(1.8). -.IP "core\ dump" -When a program terminates abnormally, the system places an image -of its current state in a file named `core'. -This -.I "core dump" -can be examined with the system debugger `adb (1)' -or `sdb (1)' in order to determine what went wrong with the program (1.8). -If the shell produces a message of the form -.DS -Illegal instruction (core dumped) -.DE -(where `Illegal instruction' is only one of several possible -messages), you should report this to the author of the program -or a system administrator, -saving the `core' file. -.IP cp -The -.I cp -(copy) program is used to copy the contents of one file into another -file. -It is one of the most commonly used \s-2UNIX\s0 commands (1.6). -.IP csh -The name of the shell -program that this document describes. -.IP \&.cshrc -The file -.I \&.cshrc -in your -.I home -directory is read by each shell as it begins execution. -It is usually used to change the setting of the variable -.I path -and to set -.I alias -parameters which are to take effect globally (2.1). -.IP cwd -The -.I cwd -variable in the shell holds the -.I "absolute pathname" -of the current -.I "working directory" \&. -It is changed by the shell whenever your current -.I "working directory" -changes and should not be changed otherwise (2.2). -.IP date -The -.I date -command prints the current date and time (1.3). -.IP debugging -.I Debugging -is the process of correcting mistakes in programs and shell scripts. -The shell has several options and variables which may be used -to aid in shell -.I debugging -(4.4). -.IP default: -The label -.I default: -is used within shell -.I switch -statements, as it is in the C language -to label the code to be executed if none of the -.I case -labels matches the value switched on (3.7). -.IP \s-2DELETE\s0 -The -\s-2DELETE\s0 -or -\s-2RUBOUT\s0 -key on the terminal normally causes an interrupt to be sent to the current job. -Many users change the interrupt character to be ^C. -.IP detached -A command that continues running in the -.I background -after you logout is said to be -.I detached . -.IP diagnostic -An error message produced by a program is often referred to as a -.I diagnostic . -Most error messages are not written to the -.I "standard output" , -since that is often directed away from the terminal (1.3, 1.5). -Error messsages are instead written to the -.I "diagnostic output" -which may be directed away from the terminal, but usually is not. -Thus -.I diagnostics -will usually appear on the terminal (2.5). -.IP directory -A structure which contains files. -At any time you are in one particular -.I directory -whose names can be printed by the command -.I pwd . -The -.I chdir -command will change you to another -.I directory , -and make the files -in that -.I directory -visible. The -.I directory -in which you are when you first login is your -.I home -directory (1.1, 2.7). -.IP "directory\ stack" -The shell saves the names of previous -.I "working directories" -in the -.I "directory stack" -when you change your current -.I "working directory" -via the -.I pushd -command. The -.I "directory stack" -can be printed by using the -.I dirs -command, which includes your current -.I "working directory" -as the first directory name on the left (2.7). -.IP dirs -The -.I dirs -command prints the shell's -.I "directory stack" -(2.7). -.IP du -The -.I du -command is a program (described in `du (1)') which -prints the number of disk blocks is all directories below -and including your current -.I "working directory" -(2.6). -.IP echo -The -.I echo -command prints its arguments (1.6, 3.6). -.IP else -The -.I else -command is part of the `if-then-else-endif' control -command construct (3.6). -.IP endif -If an -.I if -statement is ended with the word -.I then , -all lines following the -.I if -up to a line starting with the word -.I endif -or -.I else -are executed if the condition between parentheses after the -.I if -is true (3.6). -.IP \s-2EOF\s0 -An -.I "end\f1-\fPof\f1-\fPfile" -is generated by the terminal by a control-d, -and whenever a command reads to the end of a file which -it has been given as input. -Commands receiving input from a -.I pipe -receive an -.I "end\f1-\fPof\f1-\fPfile" -when the command sending them input completes. -Most commands terminate when they receive an -.I "end\f1-\fPof\f1-\fPfile" . -The shell has an option to ignore -.I "end\f1-\fPof\f1-\fPfile" -from a terminal -input which may help you keep from logging out accidentally -by typing too many control-d's (1.1, 1.8, 3.8). -.IP escape -A character `\e' used to prevent the special meaning of a metacharacter -is said to -.I escape -the character from its special meaning. -Thus -.DS -echo \e* -.DE -will echo the character `*' while just -.DS -echo * -.DE -will echo the names of the file in the current directory. -In this example, \e -.I escape s -`*' (1.7). -There is also a non-printing character called -.I escape , -usually labelled -\s-2ESC\s0 -or -\s-2ALTMODE\s0 -on terminal keyboards. -Some older \s-2UNIX\s0 systems use this character to indicate that -output is to be -.I suspended . -Most systems use control-s to stop the output and control-q to start it. -.IP /etc/passwd -This file contains information about the accounts currently on the -system. -It consists of a line for each account with fields separated by -`:' characters (1.8). -You can look at this file by saying -.DS -cat /etc/passwd -.DE -The commands -.I finger -and -.I grep -are often used to search for information in this file. -See `finger (1)', `passwd(5)', and `grep (1)' for more details. -.IP exit -The -.I exit -command is used to force termination of a shell script, -and is built into the shell (3.9). -.IP "exit\ status" -A command which discovers a problem may reflect this back to the command -(such as a shell) which invoked (executed) it. -It does this by returning a non-zero number as its -.I "exit status" , -a status of zero being considered -`normal termination'. -The -.I exit -command can be used to force a shell command script to give a non-zero -.I "exit status" -(3.6). -.IP expansion -The replacement of strings in the shell input which contain metacharacters -by other strings is referred to as the process of -.I expansion . -Thus the replacement of the word `*' by a sorted list of files -in the current directory is a `filename expansion'. -Similarly the replacement of the characters `!!' by the text of -the last command is a `history expansion'. -.I Expansions -are also referred to as -.I substitutions -(1.6, 3.4, 4.2). -.IP expressions -.I Expressions -are used in the shell -to control the conditional structures used in the writing of shell -scripts and in calculating values for these scripts. -The operators available in shell -.I expressions -are those of the language -C (3.5). -.IP extension -Filenames often consist of a -.I base -name and an -.I extension -separated by the character `.'. -By convention, groups of related files often share the same -.I root -name. -Thus if `prog.c' were a C program, then the object file for this -program would be stored in `prog.o'. -Similarly a paper written with the -`\-me' -nroff macro package might be stored in -`paper.me' -while a formatted version of this paper might be kept in -`paper.out' and a list of spelling errors in -`paper.errs' (1.6). -.IP fg -The -.I "job control" -command -.I fg -is used to run a -.I background -or -.I suspended -job in the -.I foreground -(1.8, 2.6). -.IP filename -Each file in \s-2UNIX\s0 has a name consisting of up to 14 characters -and not including the character `/' which is used in -.I pathname -building. Most -.I filenames -do not begin with the character `.', and contain -only letters and digits with perhaps a `.' separating the -.I base -portion of the -.I filename -from an -.I extension -(1.6). -.IP "filename expansion" -.br -.I "Filename expansion" -uses the metacharacters `*', `?' and `[' and `]' -to provide a convenient mechanism for naming files. -Using -.I "filename expansion" -it is easy to name all the files in -the current directory, or all files which have a common -.I root -name. Other -.I "filename expansion" -mechanisms use the metacharacter `~' and allow -files in other users' directories to be named easily (1.6, 4.2). -.IP flag -Many \s-2UNIX\s0 commands accept arguments which are not the names -of files or other users but are used to modify the action of the commands. -These are referred to as -.I flag -options, and by convention consist of one or more letters preceded by -the character `\-' (1.2). -Thus the -.I ls -(list files) command has an option -`\-s' to list the sizes of files. -This is specified -.DS -ls \-s -.DE -.IP foreach -The -.I foreach -command is used in shell scripts and at the terminal to specify -repetition of a sequence of commands while the value of a certain -shell variable ranges through a specified list (3.6, 4.1). -.IP foreground -When commands are executing in the normal way such that the -shell is waiting for them to finish before prompting for another -command they are said to be -.I "foreground jobs" -or -.I "running in the foreground" \&. -This is as opposed to -.I background . -.I Foreground -jobs can be stopped by signals -from the terminal caused by typing different -control characters at the keyboard (1.8, 2.6). -.IP goto -The shell has a command -.I goto -used in shell scripts to transfer control to a given label (3.7). -.IP grep -The -.I grep -command searches through a list of argument files for a specified string. -Thus -.DS -grep bill /etc/passwd -.DE -will print each line in the file -.I "/etc/passwd" -which contains the string `bill'. -Actually, -.I grep -scans for -.I "regular expressions" -in the sense of the editors -`ed (1)' and `ex (1)'. -.I Grep -stands for -`globally find -.I "regular expression" -and print' (2.4). -.IP head -The -.I head -command prints the first few lines of one or more files. -If you have a bunch of files containing text which you are wondering -about it is sometimes useful to run -.I head -with these files as arguments. -This will usually show enough of what is in these files to let you decide -which you are interested in (1.5). -.br -.I Head -is also used to describe the part of a -.I pathname -before and including the last `/' character. The -.I tail -of a -.I pathname -is the part after the last `/'. The `:h' and `:t' modifiers allow the -.I head -or -.I tail -of a -.I pathname -stored in a shell variable to be used (3.6). -.IP history -The -.I history -mechanism of the shell allows previous commands to be repeated, -possibly after modification to correct typing mistakes or to change -the meaning of the command. -The shell has a -.I "history list" -where these commands are kept, and a -.I history -variable which controls how large this list is (2.3). -.IP "home\ directory" -.br -Each user has a -.I "home directory" , -which is given in your entry -in the password file, -.I /etc/passwd . -This is the directory which you are placed in when you first login. -The -.I cd -or -.I chdir -command with no arguments takes you back to this directory, whose -name is recorded in the shell variable -.I home . -You can also access the -.I "home directories" -of other users in forming -filenames using a -.I "filename expansion" -notation and the character `~' (1.6). -.IP if -A conditional command within the shell, the -.I if -command is used in shell command scripts to make decisions -about what course of action to take next (3.6). -.IP ignoreeof -Normally, your shell will exit, printing -`logout' -if you type a control-d at a prompt of `% '. -This is the way you usually log off the system. -You can -.I set -the -.I ignoreeof -variable if you wish in your -.I \&.login -file and then use the command -.I logout -to logout. -This is useful if you sometimes accidentally type too many control-d -characters, logging yourself off -(2.2). -.IP input -Many commands on \s-2UNIX\s0 take information from the terminal or from -files which they then act on. -This information is called -.I input . -Commands normally read for -.I input -from their -.I "standard input" -which is, by default, the terminal. -This -.I "standard input" -can be redirected from a file using a shell metanotation -with the character `<'. -Many commands will also read from a file specified as argument. -Commands placed in -.I pipelines -will read from the output of the previous -command in the -.I pipeline . -The leftmost command in a -.I pipeline -reads from the terminal if -you neither redirect its -.I input -nor give it a filename to use as -.I "standard input" . -Special mechanisms exist for supplying input to commands in shell -scripts (1.5, 3.8). -.IP interrupt -An -.I interrupt -is a signal to a program that is generated by typing ^C. (On older versions -of UNIX the \s-2RUBOUT\s0 or \s-2DELETE\s0 key were used for this purpose.) -It causes most programs to stop execution. -Certain programs, such as the shell and the editors, -handle an -.I interrupt -in special ways, usually by stopping what they -are doing and prompting for another command. -While the shell is executing another command and waiting for it -to finish, the shell does not listen to -.I interrupts. -The shell often wakes up when you hit -.I interrupt -because many commands -die when they receive an -.I interrupt -(1.8, 3.9). -.IP job -One or more commands -typed on the same input line separated by `|' or `;' characters -are run together and are called a -.I job \&. -Simple commands run by themselves without any `|' or `;' characters -are the simplest -.I jobs. -.I Jobs -are classified as -.I foreground , -.I background , -or -.I suspended -(2.6). -.IP "job\ control" -The builtin functions that control the execution of -jobs are called -.I "job control" -commands. These are -.I "bg, fg, stop, kill" -(2.6). -.IP "job\ number" -When each job -is started it is assigned a small number called a -.I "job number" -which is printed next to the job in the output of the -.I jobs -command. This number, preceded by a `%' character, can be used as an argument -to -.I "job control" -commands to indicate -a specific job (2.6). -.IP jobs -The -.I jobs -command prints a table showing -jobs that are either running in the -.I background -or are -.I suspended -(2.6). -.IP kill -A command which sends a -signal -to a job causing it to terminate (2.6). -.IP \&.login -The file -.I \&.login -in your -.I home -directory is read by the shell each time you login to \s-2UNIX\s0 -and the commands there are executed. -There are a number of commands which are usefully placed here, -especially -.I set -commands to the shell itself (2.1). -.IP "login\ shell" -The shell that is started on your terminal when you login is called -your -.I "login shell" . -It is different from other shells which you may run (e.g. on -shell scripts) -in that it reads the -.I \&.login -file before reading commands from the terminal and it reads the -.I \&.logout -file after you logout -(2.1). -.IP logout -The -.I logout -command causes a login shell to exit. -Normally, a login shell will exit when you hit control-d -generating an -.I end\f1-\fPof\f1-\fPfile, -but if you have set -.I ignoreeof -in you -.I \&.login -file then this will not work and you must use -.I logout -to log off the \s-2UNIX\s0 system (2.8). -.IP \&.logout -When you log off of \s-2UNIX\s0 the shell will execute commands from -the file -.I \&.logout -in your -.I home -directory after it prints `logout'. -.IP lpr -The command -.I lpr -is the line printer daemon. -The standard input of -.I lpr -spooled and printed on the \s-2UNIX\s0 line printer. -You can also give -.I lpr -a list of filenames as arguments to be printed. -It is most common to use -.I lpr -as the last component of a -.I pipeline -(2.3). -.IP ls -The -.I ls -(list files) command is one of the most commonly used \s-2UNIX\s0 -commands. -With no argument filenames it prints the names of the files in the -current directory. -It has a number of useful -.I flag -arguments, and can also be given the names of directories -as arguments, in which case it lists the names of the files in these -directories (1.2). -.IP mail -The -.I mail -program is used to send and receive messages from other \s-2UNIX\s0 -users (1.1, 2.1), whether they are logged on or not. -.IP make -The -.I make -command is used to maintain one or more related files and to -organize functions to be performed on these files. -In many ways -.I make -is easier to use, and more helpful than -shell command scripts (3.2). -.IP makefile -The file containing commands for -.I make -is called -.I makefile -or -.I Makefile -(3.2). -.IP manual -The -.I manual -often referred to is the -`\s-2UNIX\s0 manual'. -It contains 8 numbered sections with a description of each \s-2UNIX\s0 -program (section 1), system call (section 2), subroutine (section 3), -device (section 4), special data structure (section 5), game (section 6), -miscellaneous item (section 7) and system administration program (section 8). -There are also supplementary documents (tutorials and reference guides) -for individual programs which require explanation in more detail. -An online version of the -.I manual -is accessible through the -.I man -command. -Its documentation can be obtained online via -.DS -man man -.DE -If you can't decide what manual page to look in, try the -.I apropos (1) -command. -The supplementary documents are in subdirectories of /usr/doc. -.IP metacharacter -.br -Many characters which are neither letters nor digits have special meaning -either to the shell or to \s-2UNIX\s0. -These characters are called -.I metacharacters . -If it is necessary to place these characters in arguments to commands -without them having their special meaning then they must be -.I quoted . -An example of a -.I metacharacter -is the character `>' which is used -to indicate placement of output into a file. -For the purposes of the -.I history -mechanism, -most unquoted -.I metacharacters -form separate words (1.4). -The appendix to this user's manual lists the -.I metacharacters -in groups by their function. -.IP mkdir -The -.I mkdir -command is used to create a new directory. -.IP modifier -Substitutions with the -.I history -mechanism, keyed by the character `!' -or of variables using the metacharacter `$', are often subjected -to modifications, indicated by placing the character `:' after the -substitution and following this with the -.I modifier -itself. -The -.I "command substitution" -mechanism can also be used to perform modification in a similar way, -but this notation is less clear (3.6). -.IP more -The program -.I more -writes a file on your terminal allowing you to control how much text -is displayed at a time. -.I More -can move through the file screenful by screenful, line by line, -search forward for a string, or start again at the beginning of the file. -It is generally the easiest way of viewing a file (1.8). -.IP noclobber -The shell has a variable -.I noclobber -which may be set in the file -.I \&.login -to prevent accidental destruction of files by the `>' output redirection -metasyntax of the shell (2.2, 2.5). -.IP noglob -The shell variable -.I noglob -is set to suppress the -.I "filename expansion" -of arguments containing the metacharacters `~', `*', `?', `[' and `]' (3.6). -.IP notify -The -.I notify -command tells the shell to report on the termination of a specific -.I "background job" -at the exact time it occurs as opposed to waiting -until just before the next prompt to report the termination. -The -.I notify -variable, if set, causes the shell to always report the termination -of -.I background -jobs exactly when they occur (2.6). -.IP onintr -The -.I onintr -command is built into the shell and is used to control the action -of a shell command script when an -.I interrupt -signal is received (3.9). -.IP output -Many commands in \s-2UNIX\s0 result in some lines of text which are -called their -.I output. -This -.I output -is usually placed on what is known as the -.I "standard output" -which is normally connected to the user's terminal. -The shell has a syntax using the metacharacter `>' for redirecting -the -.I "standard output" -of a command to a file (1.3). -Using the -.I pipe -mechanism and the metacharacter `|' it is also possible for -the -.I "standard output" -of one command to become the -.I "standard input" -of another command (1.5). -Certain commands such as the line printer daemon -.I p -do not place their results on the -.I "standard output" -but rather in more -useful places such as on the line printer (2.3). -Similarly the -.I write -command places its output on another user's terminal rather than its -.I "standard output" -(2.3). -Commands also have a -.I "diagnostic output" -where they write their error messages. -Normally these go to the terminal even if the -.I "standard output" -has been sent to a file or another command, but it is possible -to direct error diagnostics along with -.I "standard output" -using a special metanotation (2.5). -.IP path -The shell has a variable -.I path -which gives the names of the directories in which it searches for -the commands which it is given. -It always checks first to see if the command it is given is -built into the shell. -If it is, then it need not search for the command as it can do it internally. -If the command is not builtin, then the shell searches for a file -with the name given in each of the directories in the -.I path -variable, left to right. -Since the normal definition of the -.I path -variable is -.DS -path (. /usr/ucb /bin /usr/bin) -.DE -the shell normally looks in the current directory, and then in -the standard system directories `/usr/ucb', `/bin' and `/usr/bin' for the named -command (2.2). -If the command cannot be found the shell will print an error diagnostic. -Scripts of shell commands will be executed using another shell to interpret -them if they have `execute' permission set. -This is normally true because a command of the form -.DS -chmod 755 script -.DE -was executed to turn this execute permission on (3.3). -If you add new commands to a directory in the -.I path , -you should issue -the command -.I rehash -(2.2). -.IP pathname -A list of names, separated by `/' characters, forms a -.I pathname. -Each -.I component, -between successive `/' characters, names a directory -in which the next -.I component -file resides. -.I Pathnames -which begin with the character `/' are interpreted relative -to the -.I root -directory in the filesystem. -Other -.I pathnames -are interpreted relative to the current directory -as reported by -.I pwd. -The last component of a -.I pathname -may name a directory, but -usually names a file. -.IP pipeline -A group of commands which are connected together, the -.I "standard output" -of each connected to the -.I "standard input" -of the next, -is called a -.I pipeline. -The -.I pipe -mechanism used to connect these commands is indicated by -the shell metacharacter `|' (1.5, 2.3). -.IP popd -The -.I popd -command changes the shell's -.I "working directory" -to the directory you most recently left using the -.I pushd -command. It returns to the directory without having to type its name, -forgetting the name of the current -.I "working directory" -before doing so (2.7). -.IP port -The part of a computer system to which each terminal is -connected is called a -.I port . -Usually the system has a fixed number of -.I ports , -some of which are connected to telephone lines -for dial-up access, and some of which are permanently -wired directly to specific terminals. -.IP pr -The -.I pr -command is used to prepare listings of the contents of files -with headers giving the name of the file and the date and -time at which the file was last modified (2.3). -.IP printenv -The -.I printenv -command is used -to print the current setting of variables in the environment -(2.8). -.IP process -An instance of a running program is called a -.I process -(2.6). -\s-2UNIX\s0 assigns each -.I process -a unique number when it is -started \- called the -.I "process number" . -.I "Process numbers" -can be used to stop individual -.I processes -using the -.I kill -or -.I stop -commands when the -.I processes -are part of a detached -.I background -job. -.IP program -Usually synonymous with -.I command ; -a binary file or shell command script -which performs a useful function is often -called a -.I program . -.IP prompt -Many programs will print a -.I prompt -on the terminal when they expect input. -Thus the editor -`ex (1)' will print a `:' when it expects input. -The shell -.I prompts -for input with `% ' and occasionally with `? ' when -reading commands from the terminal (1.1). -The shell has a variable -.I prompt -which may be set to a different value to change the shell's main -.I prompt . -This is mostly used when debugging the shell (2.8). -.IP pushd -The -.I pushd -command, which means `push directory', changes the shell's -.I "working directory" -and also remembers the current -.I "working directory" -before the change is made, allowing you to return to the same -directory via the -.I popd -command later without retyping its name (2.7). -.IP ps -The -.I ps -command is used to show the processes you are currently running. -Each process is shown with its unique process number, -an indication of the terminal name it is attached to, -an indication of the state of the process (whether it is running, -stopped, awaiting some event (sleeping), and whether it is swapped out), -and the amount of \s-2CPU\s0 time it has used so far. -The command is identified by printing some of the words used -when it was invoked (2.6). -Shells, such as the -.I csh -you use to run the -.I ps -command, are not normally shown in the output. -.IP pwd -The -.I pwd -command prints the full -.I pathname -of the current -.I "working directory" \&. -The -.I dirs -builtin command is usually a better and faster choice. -.IP quit -The -.I quit -signal, generated by a control-\e, -is used to terminate programs which are behaving unreasonably. -It normally produces a core image file (1.8). -.IP quotation -The process by which metacharacters are prevented their special -meaning, usually by using the character `\' in pairs, or by -using the character `\e', is referred to as -.I quotation -(1.7). -.IP redirection -The routing of input or output from or to a file is known -as -.I redirection -of input or output (1.3). -.IP rehash -The -.I rehash -command tells the shell to rebuild its internal table of which commands -are found in which directories in your -.I path . -This is necessary when a new program is installed in one of these -directories (2.8). -.IP "relative pathname" -.br -A -.I pathname -which does not begin with a `/' is called a -.I "relative pathname" -since it is interpreted -.I relative -to the current -.I "working directory" . -The first -.I component -of such a -.I pathname -refers to some file or directory in the -.I "working directory" , -and subsequent -.I components -between `/' characters refer to directories below the -.I "working directory" . -.I Pathnames -that are not -.I relative -are called -.I "absolute pathnames" -(1.6). -.IP repeat -The -.I repeat -command iterates another command a specified number of times. -.IP root -The directory -that is at the top of the entire directory structure is called the -.I root -directory since it is the `root' of the entire tree structure of -directories. The name used in -.I pathnames -to indicate the -.I root -is `/'. -.I Pathnames -starting with `/' are said to be -.I absolute -since they start at the -.I root -directory. -.I Root -is also used as the part of a -.I pathname -that is left after removing -the -.I extension . -See -.I filename -for a further explanation (1.6). -.IP \s-2RUBOUT\s0 -The \s-2RUBOUT\s0 or \s-2DELETE\s0 -key is often used to erase the previously typed character; some users -prefer the \s-2BACKSPACE\s0 for this purpose. On older versions of \s-2UNIX\s0 -this key served as the \s-2INTR\s0 character. -.IP "scratch file" -Files whose names begin with a `#' are referred to as -.I "scratch files" , -since they are automatically removed by the system after a couple of -days of non-use, or more frequently if disk space becomes tight (1.3). -.IP script -Sequences of shell commands placed in a file are called shell command -.I scripts . -It is often possible to perform simple tasks using these -.I scripts -without writing a program in a language such as C, by -using the shell to selectively run other programs (3.3, 3.10). -.IP set -The builtin -.I set -command is used to assign new values to shell variables -and to show the values of the current variables. -Many shell variables have special meaning to the shell itself. -Thus by using the -.I set -command the behavior of the shell can be affected (2.1). -.IP setenv -Variables in the environment `environ (5)' -can be changed by using the -.I setenv -builtin command (2.8). -The -.I printenv -command can be used to print the value of the variables in the environment. -.IP shell -A -.I shell -is a command language interpreter. -It is possible to write and run your own -.I shell , -as -.I shells -are no different than any other programs as far as the -system is concerned. -This manual deals with the details of one particular -.I shell , -called -.I csh. -.IP "shell script" -See -.I script -(3.3, 3.10). -.IP signal -A -.I signal -in \s-2UNIX\s0 is a short message that is sent to a running program -which causes something to happen to that process. -.I Signals -are sent either by typing special -.I control -characters on the keyboard or by using the -.I kill -or -.I stop -commands (1.8, 2.6). -.IP sort -The -.I sort -program sorts a sequence of lines in ways that can be controlled -by argument -.I flags -(1.5). -.IP source -The -.I source -command causes the shell to read commands from a specified file. -It is most useful for reading files such as -.I \&.cshrc -after changing them (2.8). -.IP "special character" -.br -See -.I metacharacters -and the -appendix to this manual. -.IP standard -We refer often to the -.I "standard input" -and -.I "standard output" -of commands. -See -.I input -and -.I output -(1.3, 3.8). -.IP status -A command normally returns a -.I status -when it finishes. -By convention a -.I status -of zero indicates that the command succeeded. -Commands may return non-zero -.I status -to indicate that some abnormal event has occurred. -The shell variable -.I status -is set to the -.I status -returned by the last command. -It is most useful in shell commmand scripts (3.6). -.IP stop -The -.I stop -command causes a -.I background -job to become -.I suspended -(2.6). -.IP string -A sequential group of characters taken together is called a -.I string \&. -.I Strings -can contain any printable characters (2.2). -.IP stty -The -.I stty -program changes certain parameters inside \s-2UNIX\s0 which determine -how your terminal is handled. See `stty (1)' for a complete description (2.6). -.IP substitution -The shell implements a number of -.I substitutions -where sequences indicated by metacharacters are replaced by other sequences. -Notable examples of this are history -.I substitution -keyed by the -metacharacter `!' and variable -.I substitution -indicated by `$'. -We also refer to -.I substitutions -as -.I expansions -(3.4). -.IP suspended -A job becomes -.I suspended -after a \s-2STOP\s0 signal is sent to it, either by typing a -.I control -z -at the terminal (for -.I foreground -jobs) or by using the -.I stop -command (for -.I background -jobs). When -.I suspended , -a job temporarily stops running until it is restarted by either the -.I fg -or -.I bg -command (2.6). -.IP switch -The -.I switch -command of the shell allows the shell -to select one of a number of sequences of commands based on an -argument string. -It is similar to the -.I switch -statement in the language C (3.7). -.IP termination -When a command which is being executed finishes we say it undergoes -.I termination -or -.I terminates. -Commands normally terminate when they read an -.I end\f1-\fPof\f1-\fPfile -from their -.I "standard input" . -It is also possible to terminate commands by sending them -an -.I interrupt -or -.I quit -signal (1.8). -The -.I kill -program terminates specified jobs (2.6). -.IP then -The -.I then -command is part of the shell's -`if-then-else-endif' control construct used in command scripts (3.6). -.IP time -The -.I time -command can be used to measure the amount of \s-2CPU\s0 -and real time consumed by a specified command as well -as the amount of disk i/o, memory used, and number -of page faults and swaps taken by the command (2.1, 2.8). -.IP tset -The -.I tset -program is used to set standard erase and kill characters -and to tell the system what kind of terminal you are using. -It is often invoked in a -.I \&.login -file (2.1). -.IP tty -The word -.I tty -is a historical abbreviation for `teletype' which is frequently used -in \s-2UNIX\s0 to indicate the -.I port -to which a given terminal is connected. The -.I tty -command will print the name of the -.I tty -or -.I port -to which your terminal is presently connected. -.IP unalias -The -.I unalias -command removes aliases (2.8). -.IP \s-2UNIX\s0 -\s-2UNIX\s0 is an operating system on which -.I csh -runs. -\s-2UNIX\s0 provides facilities which allow -.I csh -to invoke other programs such as editors and text formatters which -you may wish to use. -.IP unset -The -.I unset -command removes the definitions of shell variables (2.2, 2.8). -.IP "variable expansion" -.br -See -.I variables -and -.I expansion -(2.2, 3.4). -.IP variables -.I Variables -in -.I csh -hold one or more strings as value. -The most common use of -.I variables -is in controlling the behavior -of the shell. -See -.I path , -.I noclobber , -and -.I ignoreeof -for examples. -.I Variables -such as -.I argv -are also used in writing shell programs (shell command scripts) -(2.2). -.IP verbose -The -.I verbose -shell variable can be set to cause commands to be echoed -after they are history expanded. -This is often useful in debugging shell scripts. -The -.I verbose -variable is set by the shell's -.I \-v -command line option (3.10). -.IP wc -The -.I wc -program calculates the number of characters, words, and lines in the -files whose names are given as arguments (2.6). -.IP while -The -.I while -builtin control construct is used in shell command scripts (3.7). -.IP word -A sequence of characters which forms an argument to a command is called -a -.I word . -Many characters which are neither letters, digits, `\-', `.' nor `/' -form -.I words -all by themselves even if they are not surrounded -by blanks. -Any sequence of characters may be made into a -.I word -by surrounding it -with `\'' characters -except for the characters `\'' and `!' which require special treatment -(1.1). -This process of placing special characters in -.I words -without their special meaning is called -.I quoting . -.IP "working directory" -.br -At any given time you are in one particular directory, called -your -.I "working directory" . -This directory's name is printed by the -.I pwd -command and the files listed by -.I ls -are the ones in this directory. -You can change -.I "working directories" -using -.I chdir . -.IP write -The -.I write -command is an obsolete way of communicating with other users who are logged in to -\s-2UNIX\s0 (you have to take turns typing). If you are both using display -terminals, use \fItalk\fP(1), which is much more pleasant. diff --git a/bin/csh/USD.doc/tabs b/bin/csh/USD.doc/tabs deleted file mode 100644 index 77aa8da7e..000000000 --- a/bin/csh/USD.doc/tabs +++ /dev/null @@ -1,32 +0,0 @@ -.\" $NetBSD: tabs,v 1.4 2003/08/07 09:05:09 agc Exp $ -.\" -.\" Copyright (c) 1980, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)tabs 8.1 (Berkeley) 6/8/93 -.\" -.ta 5n 10n 15n 20n 25n 30n 35n 40n 45n 50n 55n 60n 65n 70n 75n 80n diff --git a/bin/csh/alloc.c b/bin/csh/alloc.c deleted file mode 100644 index 9d158c601..000000000 --- a/bin/csh/alloc.c +++ /dev/null @@ -1,91 +0,0 @@ -/* $NetBSD: alloc.c,v 1.13 2013/01/22 19:28:00 christos Exp $ */ - -/*- - * Copyright (c) 1983, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)alloc.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: alloc.c,v 1.13 2013/01/22 19:28:00 christos Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include -#include - -#include "csh.h" -#include "extern.h" - -ptr_t -Malloc(size_t n) -{ - ptr_t ptr; - - if ((ptr = malloc(n)) == (ptr_t) 0) { - child++; - stderror(ERR_NOMEM); - } - return (ptr); -} - -ptr_t -Realloc(ptr_t p, size_t n) -{ - ptr_t ptr; - - if ((ptr = realloc(p, n)) == (ptr_t) 0) { - child++; - stderror(ERR_NOMEM); - } - return (ptr); -} - -ptr_t -Calloc(size_t s, size_t n) -{ - ptr_t ptr; - - if ((ptr = calloc(s, n)) == (ptr_t) 0) { - child++; - stderror(ERR_NOMEM); - } - return (ptr); -} - -void -Free(ptr_t p) -{ - if (p) - free(p); -} diff --git a/bin/csh/char.c b/bin/csh/char.c deleted file mode 100644 index dd1160cb9..000000000 --- a/bin/csh/char.c +++ /dev/null @@ -1,315 +0,0 @@ -/* $NetBSD: char.c,v 1.10 2012/01/19 02:42:53 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)char.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: char.c,v 1.10 2012/01/19 02:42:53 christos Exp $"); -#endif -#endif /* not lint */ - -#include "char.h" - -/* on default same as original map */ -unsigned short _cmap[256] = { -/* 0 nul 1 soh 2 stx 3 etx */ - _CTR, _CTR, _CTR, _CTR, - -/* 4 eot 5 enq 6 ack 7 bel */ - _CTR, _CTR, _CTR, _CTR, - -/* 8 bs 9 ht 10 nl 11 vt */ - _CTR, _CTR|_SP|_META, _CTR|_NL|_META, _CTR, - -/* 12 np 13 cr 14 so 15 si */ - _CTR, _CTR, _CTR, _CTR, - -/* 16 dle 17 dc1 18 dc2 19 dc3 */ - _CTR, _CTR, _CTR, _CTR, - -/* 20 dc4 21 nak 22 syn 23 etb */ - _CTR, _CTR, _CTR, _CTR, - -/* 24 can 25 em 26 sub 27 esc */ - _CTR, _CTR, _CTR, _CTR, - -/* 28 fs 29 gs 30 rs 31 us */ - _CTR, _CTR, _CTR, _CTR, - -/* 32 sp 33 ! 34 " 35 # */ - _SP|_META, _PUN, _QF|_PUN, _META|_PUN, - -/* 36 $ 37 % 38 & 39 ' */ - _DOL|_PUN, _PUN, _META|_CMD|_PUN,_QF|_PUN, - -/* 40 ( 41 ) 42 * 43 + */ - _META|_CMD|_PUN,_META|_PUN, _GLOB|_PUN, _PUN, - -/* 44 , 45 - 46 . 47 / */ - _PUN, _PUN, _PUN, _PUN, - -/* 48 0 49 1 50 2 51 3 */ - _DIG|_XD, _DIG|_XD, _DIG|_XD, _DIG|_XD, - -/* 52 4 53 5 54 6 55 7 */ - _DIG|_XD, _DIG|_XD, _DIG|_XD, _DIG|_XD, - -/* 56 8 57 9 58 : 59 ; */ - _DIG|_XD, _DIG|_XD, _PUN, _META|_CMD|_PUN, - -/* 60 < 61 = 62 > 63 ? */ - _META|_PUN, _PUN, _META|_PUN, _GLOB|_PUN, - -/* 64 @ 65 A 66 B 67 C */ - _PUN, _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP|_XD, - -/* 68 D 69 E 70 F 71 G */ - _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP|_XD, _LET|_UP, - -/* 72 H 73 I 74 J 75 K */ - _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP, - -/* 76 L 77 M 78 N 79 O */ - _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP, - -/* 80 P 81 Q 82 R 83 S */ - _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP, - -/* 84 T 85 U 86 V 87 W */ - _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP, - -/* 88 X 89 Y 90 Z 91 [ */ - _LET|_UP, _LET|_UP, _LET|_UP, _GLOB|_PUN, - -/* 92 \ 93 ] 94 ^ 95 _ */ - _ESC|_PUN, _PUN, _PUN, _PUN, - -/* 96 ` 97 a 98 b 99 c */ - _QB|_GLOB|_META|_PUN, _LET|_LOW|_XD, _LET|_LOW|_XD, _LET|_LOW|_XD, - -/* 100 d 101 e 102 f 103 g */ - _LET|_LOW|_XD, _LET|_LOW|_XD, _LET|_LOW|_XD, _LET|_LOW, - -/* 104 h 105 i 106 j 107 k */ - _LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW, - -/* 108 l 109 m 110 n 111 o */ - _LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW, - -/* 112 p 113 q 114 r 115 s */ - _LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW, - -/* 116 t 117 u 118 v 119 w */ - _LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW, - -/* 120 x 121 y 122 z 123 { */ - _LET|_LOW, _LET|_LOW, _LET|_LOW, _GLOB|_PUN, - -/* 124 | 125 } 126 ~ 127 del */ - _META|_CMD|_PUN,_PUN, _PUN, _CTR, - -#ifdef SHORT_STRINGS -/****************************************************************/ -/* 128 - 255 The below is supposedly ISO 8859/1 */ -/****************************************************************/ -/* 128 (undef) 129 (undef) 130 (undef) 131 (undef) */ - _CTR, _CTR, _CTR, _CTR, - -/* 132 (undef) 133 (undef) 134 (undef) 135 (undef) */ - _CTR, _CTR, _CTR, _CTR, - -/* 136 (undef) 137 (undef) 138 (undef) 139 (undef) */ - _CTR, _CTR, _CTR, _CTR, - -/* 140 (undef) 141 (undef) 142 (undef) 143 (undef) */ - _CTR, _CTR, _CTR, _CTR, - -/* 144 (undef) 145 (undef) 146 (undef) 147 (undef) */ - _CTR, _CTR, _CTR, _CTR, - -/* 148 (undef) 149 (undef) 150 (undef) 151 (undef) */ - _CTR, _CTR, _CTR, _CTR, - -/* 152 (undef) 153 (undef) 154 (undef) 155 (undef) */ - _CTR, _CTR, _CTR, _CTR, - -/* 156 (undef) 157 (undef) 158 (undef) 159 (undef) */ - _CTR, _CTR, _CTR, _CTR, - -/* 160 nobreakspace 161 exclamdown 162 cent 163 sterling */ - _PUN, /* XXX */ _PUN, _PUN, _PUN, - -/* 164 currency 165 yen 166 brokenbar 167 section */ - _PUN, _PUN, _PUN, _PUN, - -/* 168 diaeresis 169 copyright 170 ordfeminine 171 guillemotleft*/ - _PUN, _PUN, _PUN, _PUN, - -/* 172 notsign 173 hyphen 174 registered 175 macron */ - _PUN, _PUN, _PUN, _PUN, - -/* 176 degree 177 plusminus 178 twosuperior 179 threesuperior*/ - _PUN, _PUN, _PUN, _PUN, - -/* 180 acute 181 mu 182 paragraph 183 periodcentered*/ - _PUN, _PUN, /*XXX*/ _PUN, _PUN, - -/* 184 cedilla 185 onesuperior 186 masculine 187 guillemotright*/ - _PUN, _PUN, _PUN, _PUN, - -/* 188 onequarter 189 onehalf 190 threequarters 191 questiondown*/ - _PUN, _PUN, _PUN, _PUN, - -/* 192 Agrave 193 Aacute 194 Acircumflex 195 Atilde */ - _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP, - -/* 196 Adiaeresis 197 Aring 198 AE 199 Ccedilla */ - _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP, - -/* 200 Egrave 201 Eacute 202 Ecircumflex 203 Ediaeresis */ - _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP, - -/* 204 Igrave 205 Iacute 206 Icircumflex 207 Idiaeresis */ - _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP, - -/* 208 ETH 209 Ntilde 210 Ograve 211 Oacute */ - _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP, - -/* 212 Ocircumflex 213 Otilde 214 Odiaeresis 215 multiply */ - _LET|_UP, _LET|_UP, _LET|_UP, _PUN, - -/* 216 Ooblique 217 Ugrave 218 Uacute 219 Ucircumflex */ - _LET|_UP, _LET|_UP, _LET|_UP, _LET|_UP, - -/* 220 Udiaeresis 221 Yacute 222 THORN 223 ssharp */ - _LET|_UP, _LET|_UP, _LET|_UP, _LET|_LOW, - -/* 224 agrave 225 aacute 226 acircumflex 227 atilde */ - _LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW, - -/* 228 adiaeresis 229 aring 230 ae 231 ccedilla */ - _LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW, - -/* 232 egrave 233 eacute 234 ecircumflex 235 ediaeresis */ - _LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW, - -/* 236 igrave 237 iacute 238 icircumflex 239 idiaeresis */ - _LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW, - -/* 240 eth 241 ntilde 242 ograve 243 oacute */ - _LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW, - -/* 244 ocircumflex 245 otilde 246 odiaeresis 247 division */ - _LET|_LOW, _LET|_LOW, _LET|_LOW, _PUN, - -/* 248 oslash 249 ugrave 250 uacute 251 ucircumflex */ - _LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW, - -/* 252 udiaeresis 253 yacute 254 thorn 255 ydiaeresis */ - _LET|_LOW, _LET|_LOW, _LET|_LOW, _LET|_LOW, -#endif /* SHORT_STRINGS */ -}; - -#ifndef NLS -/* _cmap_lower, _cmap_upper for ISO 8859/1 */ - -unsigned char _cmap_lower[256] = { - 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, - 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, - 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027, - 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037, - 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047, - 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057, - 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, - 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077, - 0100, 0141, 0142, 0143, 0144, 0145, 0146, 0147, - 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, - 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, - 0170, 0171, 0172, 0133, 0134, 0135, 0136, 0137, - 0140, 0141, 0142, 0143, 0144, 0145, 0146, 0147, - 0150, 0151, 0152, 0153, 0154, 0155, 0156, 0157, - 0160, 0161, 0162, 0163, 0164, 0165, 0166, 0167, - 0170, 0171, 0172, 0173, 0174, 0175, 0176, 0177, - 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, - 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, - 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, - 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, - 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, - 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, - 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, - 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, - 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, - 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, - 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0327, - 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0337, - 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, - 0350, 0351, 0352, 0353, 0354, 0355, 0356, 0357, - 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, - 0370, 0371, 0372, 0373, 0374, 0375, 0376, 0377, -}; - -unsigned char _cmap_upper[256] = { - 0000, 0001, 0002, 0003, 0004, 0005, 0006, 0007, - 0010, 0011, 0012, 0013, 0014, 0015, 0016, 0017, - 0020, 0021, 0022, 0023, 0024, 0025, 0026, 0027, - 0030, 0031, 0032, 0033, 0034, 0035, 0036, 0037, - 0040, 0041, 0042, 0043, 0044, 0045, 0046, 0047, - 0050, 0051, 0052, 0053, 0054, 0055, 0056, 0057, - 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, - 0070, 0071, 0072, 0073, 0074, 0075, 0076, 0077, - 0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107, - 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, - 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, - 0130, 0131, 0132, 0133, 0134, 0135, 0136, 0137, - 0140, 0101, 0102, 0103, 0104, 0105, 0106, 0107, - 0110, 0111, 0112, 0113, 0114, 0115, 0116, 0117, - 0120, 0121, 0122, 0123, 0124, 0125, 0126, 0127, - 0130, 0131, 0132, 0173, 0174, 0175, 0176, 0177, - 0200, 0201, 0202, 0203, 0204, 0205, 0206, 0207, - 0210, 0211, 0212, 0213, 0214, 0215, 0216, 0217, - 0220, 0221, 0222, 0223, 0224, 0225, 0226, 0227, - 0230, 0231, 0232, 0233, 0234, 0235, 0236, 0237, - 0240, 0241, 0242, 0243, 0244, 0245, 0246, 0247, - 0250, 0251, 0252, 0253, 0254, 0255, 0256, 0257, - 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, - 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, - 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, - 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, - 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0327, - 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, - 0300, 0301, 0302, 0303, 0304, 0305, 0306, 0307, - 0310, 0311, 0312, 0313, 0314, 0315, 0316, 0317, - 0320, 0321, 0322, 0323, 0324, 0325, 0326, 0367, - 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0377, -}; -#endif /* NLS */ diff --git a/bin/csh/char.h b/bin/csh/char.h deleted file mode 100644 index 966d46142..000000000 --- a/bin/csh/char.h +++ /dev/null @@ -1,100 +0,0 @@ -/* $NetBSD: char.h,v 1.9 2012/01/19 02:42:53 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)char.h 8.1 (Berkeley) 5/31/93 - */ - -#ifndef _CHAR_H_ -#define _CHAR_H_ - -#include - -extern unsigned short _cmap[]; - -#ifndef NLS -extern unsigned char _cmap_lower[], _cmap_upper[]; - -#endif - -#define _QF 0x0001 /* '" (Forward quotes) */ -#define _QB 0x0002 /* ` (Backquote) */ -#define _SP 0x0004 /* space and tab */ -#define _NL 0x0008 /* \n */ -#define _META 0x0010 /* lex meta characters, sp #'`";&<>()|\t\n */ -#define _GLOB 0x0020 /* glob characters, *?{[` */ -#define _ESC 0x0040 /* \ */ -#define _DOL 0x0080 /* $ */ -#define _DIG 0x0100 /* 0-9 */ -#define _LET 0x0200 /* a-z, A-Z, _ */ -#define _UP 0x0400 /* A-Z */ -#define _LOW 0x0800 /* a-z */ -#define _XD 0x1000 /* 0-9, a-f, A-F */ -#define _CMD 0x2000 /* lex end of command chars, ;&(|` */ -#define _CTR 0x4000 /* control */ -#define _PUN 0x8000 /* punctuation */ - -#define cmap(c, bits) \ - (((c) & QUOTE) ? 0 : (_cmap[(unsigned char)(c)] & (bits))) - -#define isglob(c) cmap(c, _GLOB) -#define isspc(c) cmap(c, _SP) -#define ismeta(c) cmap(c, _META) -#define iscmdmeta(c) cmap(c, _CMD) -#define letter(c) (((c) & QUOTE) ? 0 : \ - (isalpha((unsigned char) (c)) || (c) == '_')) -#define alnum(c) (((c) & QUOTE) ? 0 : \ - (isalnum((unsigned char) (c)) || (c) == '_')) -#ifdef NLS -#define Isspace(c) (((c) & QUOTE) ? 0 : isspace((unsigned char) (c))) -#define Isdigit(c) (((c) & QUOTE) ? 0 : isdigit((unsigned char) (c))) -#define Isalpha(c) (((c) & QUOTE) ? 0 : isalpha((unsigned char) (c))) -#define Islower(c) (((c) & QUOTE) ? 0 : islower((unsigned char) (c))) -#define Isupper(c) (((c) & QUOTE) ? 0 : isupper((unsigned char) (c))) -#define Tolower(c) (((c) & QUOTE) ? 0 : tolower((unsigned char) (c))) -#define Toupper(c) (((c) & QUOTE) ? 0 : toupper((unsigned char) (c))) -#define Isxdigit(c) (((c) & QUOTE) ? 0 : isxdigit((unsigned char) (c))) -#define Isalnum(c) (((c) & QUOTE) ? 0 : isalnum((unsigned char) (c))) -#define Iscntrl(c) (((c) & QUOTE) ? 0 : iscntrl((unsigned char) (c))) -#define Isprint(c) (((c) & QUOTE) ? 0 : isprint((unsigned char) (c))) -#else -#define Isspace(c) cmap(c, _SP|_NL) -#define Isdigit(c) cmap(c, _DIG) -#define Isalpha(c) (cmap(c,_LET) && !(((c) & META) && AsciiOnly)) -#define Islower(c) (cmap(c,_LOW) && !(((c) & META) && AsciiOnly)) -#define Isupper(c) (cmap(c, _UP) && !(((c) & META) && AsciiOnly)) -#define Tolower(c) (_cmap_lower[(unsigned char)(c)]) -#define Toupper(c) (_cmap_upper[(unsigned char)(c)]) -#define Isxdigit(c) cmap(c, _XD) -#define Isalnum(c) (cmap(c, _DIG|_LET) && !(((c) & META) && AsciiOnly)) -#define Iscntrl(c) (cmap(c,_CTR) && !(((c) & META) && AsciiOnly)) -#define Isprint(c) (!cmap(c,_CTR) && !(((c) & META) && AsciiOnly)) -#endif - -#endif /* !_CHAR_H_ */ diff --git a/bin/csh/const.c b/bin/csh/const.c deleted file mode 100644 index 7693580f0..000000000 --- a/bin/csh/const.c +++ /dev/null @@ -1,164 +0,0 @@ -/* $NetBSD: const.c,v 1.10 2013/01/22 20:35:29 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)const.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: const.c,v 1.10 2013/01/22 20:35:29 christos Exp $"); -#endif -#endif /* not lint */ - -/* - * tc.const.c: String constants for csh. - */ - -#include "csh.h" - -Char STR0[] = { '0', '\0' }; -Char STR1[] = { '1', '\0' }; -Char STRHOME[] = { 'H', 'O', 'M', 'E', '\0' }; -Char STRLANG[] = { 'L', 'A', 'N', 'G', '\0' }; -Char STRLC_CTYPE[] = { 'L', 'C', '_', 'C', 'T', 'Y', 'P', 'E' ,'\0' }; -Char STRLOGNAME[] = { 'L', 'O', 'G', 'N', 'A', 'M', 'E', '\0' }; -Char STRLbrace[] = { '{', '\0' }; -Char STRLparen[] = { '(', '\0' }; -Char STRLparensp[] = { '(', ' ', '\0' }; -Char STRNULL[] = { '\0' }; -Char STRPATH[] = { 'P', 'A', 'T', 'H', '\0' }; -Char STRPWD[] = { 'P', 'W', 'D', '\0' }; -Char STRQNULL[] = { '\0' | QUOTE, '\0' }; -Char STRRbrace[] = { '}', '\0' }; -Char STRspRparen[] = { ' ', ')', '\0' }; -Char STRTERM[] = { 'T', 'E', 'R', 'M', '\0' }; -Char STRUSER[] = { 'U', 'S', 'E', 'R', '\0' }; -Char STRalias[] = { 'a', 'l', 'i', 'a', 's', '\0' }; -Char STRand[] = { '&', '\0' }; -Char STRand2[] = { '&', '&', '\0' }; -Char STRaout[] = { 'a', '.', 'o', 'u', 't', '\0' }; -Char STRargv[] = { 'a', 'r', 'g', 'v', '\0' }; -Char STRbang[] = { '!', '\0' }; -Char STRcaret[] = { '^', '\0' }; -Char STRcdpath[] = { 'c', 'd', 'p', 'a', 't', 'h', '\0' }; -Char STRcent2[] = { '%', '%', '\0' }; -Char STRcenthash[] = { '%', '#', '\0' }; -Char STRcentplus[] = { '%', '+', '\0' }; -Char STRcentminus[] = { '%', '-', '\0' }; -Char STRchase_symlinks[] = { 'c', 'h', 'a', 's', 'e', '_', 's', 'y', 'm', 'l', - 'i', 'n', 'k', 's', '\0' }; -Char STRchild[] = { 'c', 'h', 'i', 'l', 'd', '\0' }; -Char STRcolon[] = { ':', '\0' }; -Char STRcwd[] = { 'c', 'w', 'd', '\0' }; -Char STRdefault[] = { 'd', 'e', 'f', 'a', 'u', 'l', 't', '\0' }; -Char STRdot[] = { '.', '\0' }; -Char STRdotdotsl[] = { '.', '.', '/', '\0' }; -Char STRdotsl[] = { '.', '/', '\0' }; -Char STRecho[] = { 'e', 'c', 'h', 'o', '\0' }; -Char STRedit[] = { 'e', 'd', 'i', 't', '\0' }; -Char STRequal[] = { '=', '\0' }; -Char STRfakecom[] = { '{', ' ', '.', '.', '.', ' ', '}', '\0' }; -Char STRfakecom1[] = { '`', ' ', '.', '.', '.', ' ', '`', '\0' }; -Char STRfignore[] = { 'f', 'i', 'g', 'n', 'o', 'r', 'e', '\0' }; -#ifdef FILEC -Char STRfilec[] = { 'f', 'i', 'l', 'e', 'c', '\0' }; -#endif /* FILEC */ -Char STRhistchars[] = { 'h', 'i', 's', 't', 'c', 'h', 'a', 'r', 's', '\0' }; -Char STRtildothist[] = { '~', '/', '.', 'h', 'i', 's', 't', 'o', 'r', - 'y', '\0' }; -Char STRhistfile[] = { 'h', 'i', 's', 't', 'f', 'i', 'l', 'e', '\0' }; -Char STRhistory[] = { 'h', 'i', 's', 't', 'o', 'r', 'y', '\0' }; -Char STRhome[] = { 'h', 'o', 'm', 'e', '\0' }; -Char STRignore_symlinks[] = { 'i', 'g', 'n', 'o', 'r', 'e', '_', 's', 'y', 'm', - 'l', 'i', 'n', 'k', 's', '\0' }; -Char STRignoreeof[] = { 'i', 'g', 'n', 'o', 'r', 'e', 'e', 'o', 'f', '\0' }; -Char STRjobs[] = { 'j', 'o', 'b', 's', '\0' }; -Char STRlistjobs[] = { 'l', 'i', 's', 't', 'j', 'o', 'b', 's', '\0' }; -Char STRlogout[] = { 'l', 'o', 'g', 'o', 'u', 't', '\0' }; -Char STRlong[] = { 'l', 'o', 'n', 'g', '\0' }; -Char STRmail[] = { 'm', 'a', 'i', 'l', '\0' }; -Char STRmh[] = { '-', 'h', '\0' }; -Char STRminus[] = { '-', '\0' }; -Char STRml[] = { '-', 'l', '\0' }; -Char STRmn[] = { '-', 'n', '\0' }; -Char STRmquestion[] = { '?' | QUOTE, ' ', '\0' }; -Char STRnice[] = { 'n', 'i', 'c', 'e', '\0' }; -Char STRnoambiguous[] = { 'n', 'o', 'a', 'm', 'b', 'i', 'g', 'u', 'o', 'u', - 's', '\0' }; -Char STRnobeep[] = { 'n', 'o', 'b', 'e', 'e', 'p', '\0' }; -Char STRnoclobber[] = { 'n', 'o', 'c', 'l', 'o', 'b', 'b', 'e', 'r', '\0' }; -Char STRnoglob[] = { 'n', 'o', 'g', 'l', 'o', 'b', '\0' }; -Char STRnohup[] = { 'n', 'o', 'h', 'u', 'p', '\0' }; -Char STRnonomatch[] = { 'n', 'o', 'n', 'o', 'm', 'a', 't', 'c', 'h', '\0' }; -Char STRnormal[] = { 'n', 'o', 'r', 'm', 'a', 'l', '\0' }; -Char STRnotify[] = { 'n', 'o', 't', 'i', 'f', 'y', '\0' }; -Char STRor[] = { '|', '\0' }; -Char STRor2[] = { '|', '|', '\0' }; -Char STRpath[] = { 'p', 'a', 't', 'h', '\0' }; -Char STRprintexitvalue[] = { 'p', 'r', 'i', 'n', 't', 'e', 'x', 'i', 't', 'v', - 'a', 'l', 'u', 'e', '\0' }; -Char STRprompt[] = { 'p', 'r', 'o', 'm', 'p', 't', '\0' }; -Char STRprompt2[] = { 'p', 'r', 'o', 'm', 'p', 't', '2', '\0' }; -Char STRpushdsilent[] = { 'p', 'u', 's', 'h', 'd', 's', 'i', 'l', 'e', 'n', - 't', '\0' }; -Char STRret[] = { '\n', '\0' }; -Char STRsavehist[] = { 's', 'a', 'v', 'e', 'h', 'i', 's', 't', '\0' }; -Char STRsemisp[] = { ';', ' ', '\0' }; -Char STRshell[] = { 's', 'h', 'e', 'l', 'l', '\0' }; -Char STRslash[] = { '/', '\0' }; -Char STRsldotcshrc[] = { '/', '.', 'c', 's', 'h', 'r', 'c', '\0' }; -Char STRsldotlogin[] = { '/', '.', 'l', 'o', 'g', 'i', 'n', '\0' }; -Char STRsldthist[] = { '/', '.', 'h', 'i', 's', 't', 'o', 'r', 'y', '\0' }; -Char STRsldtlogout[] = { '/', '.', 'l', 'o', 'g', 'o', 'u', 't', '\0' }; -Char STRsource[] = { 's', 'o', 'u', 'r', 'c', 'e', '\0' }; -Char STRsp3dots[] = { ' ', '.', '.', '.', '\0' }; -Char STRspLarrow2sp[] = { ' ', '<', '<', ' ', '\0' }; -Char STRspLarrowsp[] = { ' ', '<', ' ', '\0' }; -Char STRspRarrow[] = { ' ', '>', '\0' }; -Char STRspRarrow2[] = { ' ', '>', '>', '\0' }; -Char STRRparen[] = { ')', '\0' }; -Char STRspace[] = { ' ', '\0' }; -Char STRspand2sp[] = { ' ', '&', '&', ' ', '\0' }; -Char STRspor2sp[] = { ' ', '|', '|', ' ', '\0' }; -Char STRsporsp[] = { ' ', '|', ' ', '\0' }; -Char STRstar[] = { '*', '\0' }; -Char STRstatus[] = { 's', 't', 'a', 't', 'u', 's', '\0' }; -Char STRsymcent[] = { '%', ' ', '\0' }; -Char STRsymhash[] = { '#', ' ', '\0' }; -Char STRterm[] = { 't', 'e', 'r', 'm', '\0' }; -Char STRthen[] = { 't', 'h', 'e', 'n', '\0' }; -Char STRtilde[] = { '~', '\0' }; -Char STRtime[] = { 't', 'i', 'm', 'e', '\0' }; -Char STRtmpsh[] = { '/', 't', 'm', 'p', '/', 's', 'h', '\0' }; -Char STRunalias[] = { 'u', 'n', 'a', 'l', 'i', 'a', 's', '\0' }; -Char STRuser[] = { 'u', 's', 'e', 'r', '\0' }; -Char STRverbose[] = { 'v', 'e', 'r', 'b', 'o', 's', 'e', '\0' }; -Char STRwordchars[] = { 'w', 'o', 'r', 'd', 'c', 'h', 'a', 'r', 's', '\0' }; diff --git a/bin/csh/csh.1 b/bin/csh/csh.1 deleted file mode 100644 index 3c3763c1c..000000000 --- a/bin/csh/csh.1 +++ /dev/null @@ -1,2293 +0,0 @@ -.\" $NetBSD: csh.1,v 1.53 2016/08/10 17:16:47 sevan Exp $ -.\" -.\" Copyright (c) 1980, 1990, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)csh.1 8.2 (Berkeley) 1/21/94 -.\" -.Dd August 8, 2016 -.Dt CSH 1 -.Os -.Sh NAME -.Nm csh -.Nd a shell (command interpreter) with C-like syntax -.Sh SYNOPSIS -.Nm -.Op Fl bcefinstvVxX -.Op arg ... -.Nm -.Op Fl l -.Sh DESCRIPTION -The -.Nm -is a command language interpreter -incorporating a history mechanism (see -.Sx History substitutions ) , -job control facilities (see -.Sx Jobs ) , -interactive file name -and user name completion (see -.Sx File Name Completion ) , -and a C-like syntax. -It is used both as an interactive -login shell and a shell script command processor. -.Ss Argument list processing -If the first argument (argument 0) to the shell is -.Ql Fl \& , -then this is a login shell. -A login shell also can be specified by invoking the shell with the -.Ql Fl l -flag as the only argument. -.Pp -The rest of the flag arguments are interpreted as follows: -.Bl -tag -width 5n -.It Fl b -This flag forces a ``break'' from option processing, causing any further -shell arguments to be treated as non-option arguments. -The remaining arguments will not be interpreted as shell options. -This may be used to pass options to a shell script without confusion -or possible subterfuge. -The shell will not run a set-user ID script without this option. -.It Fl c -Commands are read from the (single) following argument which must -be present. -Any remaining arguments are placed in -.Ar argv . -.It Fl e -The shell exits if any invoked command terminates abnormally -or yields a non-zero exit status. -.It Fl f -The shell will start faster, because it will neither search for nor -execute commands from the file -.Pa \&.cshrc -in the invoker's home directory. -.It Fl i -The shell is interactive and prompts for its top-level input, -even if it appears not to be a terminal. -Shells are interactive without this option if their inputs -and outputs are terminals. -.It Fl l -The shell is a login shell (only applicable if -.Fl l -is the only flag specified). -.It Fl m -Read -.Pa \&.cshrc -even if not owned by the user. -This flag is normally given only by -.Xr su 1 . -.It Fl n -Commands are parsed, but not executed. -This aids in syntactic checking of shell scripts. -.It Fl s -Command input is taken from the standard input. -.It Fl t -A single line of input is read and executed. -A -.Ql \e -may be used to escape the newline at the end of this -line and continue onto another line. -.It Fl v -Causes the -.Ar verbose -variable to be set, with the effect -that command input is echoed after history substitution. -.It Fl x -Causes the -.Ar echo -variable to be set, so that commands are echoed immediately before execution. -.It Fl V -Causes the -.Ar verbose -variable to be set even before -.Pa .cshrc -is executed. -.It Fl X -Is to -.Fl x -as -.Fl V -is to -.Fl v . -.El -.Pp -After processing of flag arguments, if arguments remain but none of the -.Fl c , -.Fl i , -.Fl s , -or -.Fl t -options were given, the first argument is taken as the name of a file of -commands to be executed. -The shell opens this file, and saves its name for possible resubstitution -by `$0'. -Since many systems use either the standard version 6 or version 7 shells -whose shell scripts are not compatible with this shell, the shell will -execute such a `standard' shell if the first character of a script -is not a `#', i.e., if the script does not start with a comment. -Remaining arguments initialize the variable -.Ar argv . -.Pp -An instance of -.Nm -begins by executing commands from the file -.Pa /etc/csh.cshrc -and, -if this is a login shell, -.Pa \&/etc/csh.login . -It then executes -commands from -.Pa \&.cshrc -in the -.Ar home -directory of the invoker, and, if this is a login shell, the file -.Pa \&.login -in the same location. -It is typical for users on crt's to put the command ``stty crt'' -in their -.Pa \&.login -file, and to also invoke -.Xr tset 1 -there. -.Pp -In the normal case, the shell will begin reading commands from the -terminal, prompting with `% '. -Processing of arguments and the use of the shell to process files -containing command scripts will be described later. -.Pp -The shell repeatedly performs the following actions: -a line of command input is read and broken into -.Ar words . -This sequence of words is placed on the command history list and parsed. -Finally each command in the current line is executed. -.Pp -When a login shell terminates it executes commands from the files -.Pa .logout -in the user's -.Ar home -directory and -.Pa /etc/csh.logout . -.Ss Lexical structure -The shell splits input lines into words at blanks and tabs with the -following exceptions. -The characters -`\*[Am]' `\&|' `;' `\*[Lt]' `\*[Gt]' `(' `)' -form separate words. -If doubled in `\*[Am]\*[Am]', -`\&|\&|', `\*[Lt]\*[Lt]' or `\*[Gt]\*[Gt]' these pairs form single words. -These parser metacharacters may be made part of other words, or prevented their -special meaning, by preceding them with `\e'. -A newline preceded by a `\e' is equivalent to a blank. -.Pp -Strings enclosed in matched pairs of quotations, -`'\|', `\*(ga' or `"', -form parts of a word; metacharacters in these strings, including blanks -and tabs, do not form separate words. -These quotations have semantics to be described later. -Within pairs of `\'' or `"' characters, a newline preceded by a `\e' gives -a true newline character. -.Pp -When the shell's input is not a terminal, -the character `#' introduces a comment that continues to the end of the -input line. -It is prevented this special meaning when preceded by `\e' -and in quotations using `\`', `\'', and `"'. -.Ss Commands -A simple command is a sequence of words, the first of which -specifies the command to be executed. -A simple command or -a sequence of simple commands separated by `\&|' characters -forms a pipeline. -The output of each command in a pipeline is connected to the input of the next. -Sequences of pipelines may be separated by `;', and are then executed -sequentially. -A sequence of pipelines may be executed without immediately -waiting for it to terminate by following it with an `\*[Am]'. -.Pp -Any of the above may be placed in `(' `)' to form a simple command (that -may be a component of a pipeline, etc.). -It is also possible to separate pipelines with `\&|\&|' -or `\*[Am]\*[Am]' showing, as in the C language, -that the second is to be executed only if the first fails or succeeds -respectively. -(See -.Sx Expressions . ) -.Ss Jobs -The shell associates a -.Ar job -with each pipeline. -It keeps -a table of current jobs, printed by the -.Ar jobs -command, and assigns them small integer numbers. -When a job is started asynchronously with `\*[Am]', -the shell prints a line that looks like: -.Bd -filled -offset indent -.Op 1 -1234 -.Ed -.Pp -showing that the job which was started asynchronously was job number -1 and had one (top-level) process, whose process id was 1234. -.Pp -If you are running a job and wish to do something else you may hit the key -.Ic ^Z -(control-Z) which sends a STOP signal to the current job. -The shell will then normally show that the job has been `Stopped', -and print another prompt. -You can then manipulate the state of this job, putting it in the -.Em background -with the -.Ar bg -command, or run some other -commands and eventually bring the job back into the foreground with -the -.Em foreground -command -.Ar fg . -A -.Ic ^Z -takes effect immediately and -is like an interrupt in that pending output and unread input are discarded -when it is typed. -There is another special key -.Ic ^Y -that does not generate a STOP signal until a program attempts to -.Xr read 2 -it. -This request can usefully be typed ahead when you have prepared some commands -for a job that you wish to stop after it has read them. -.Pp -A job being run in the background will stop if it tries to read -from the terminal. -Background jobs are normally allowed to produce output, -but this can be disabled by giving the command ``stty tostop''. -If you set this -tty option, then background jobs will stop when they try to produce -output like they do when they try to read input. -.Pp -There are several ways to refer to jobs in the shell. -The character `%' introduces a job name. -If you wish to refer to job number 1, you can name it as `%1'. -Just naming a job brings it to the foreground; thus -`%1' is a synonym for `fg %1', bringing job number 1 back into the foreground. -Similarly saying `%1 \*[Am]' resumes job number 1 in the background. -Jobs can also be named by prefixes of the string typed in to start them, -if these prefixes are unambiguous, thus `%ex' would normally restart -a suspended -.Xr ex 1 -job, if there were only one suspended job whose name began with -the string `ex'. -It is also possible to say `%?string' -which specifies a job whose text contains -.Ar string , -if there is only one such job. -.Pp -The shell maintains a notion of the current and previous jobs. -In output about jobs, the current job is marked with a `+' -and the previous job with a `\-'. -The abbreviation `%+' refers -to the current job and `%\-' refers to the previous job. -For close analogy with the syntax of the -.Ar history -mechanism (described below), -`%%' is also a synonym for the current job. -.Pp -The job control mechanism requires that the -.Xr stty 1 -option -.Ic new -be set. -It is an artifact from a -.Em new -implementation -of the -tty driver that allows generation of interrupt characters from -the keyboard to tell jobs to stop. -See -.Xr stty 1 -for details on setting options in the new tty driver. -.Ss Status reporting -The shell learns immediately whenever a process changes state. -It normally informs you whenever a job becomes blocked so that -no further progress is possible, but only just before it prints -a prompt. -This is done so that it does not otherwise disturb your work. -If, however, you set the shell variable -.Ar notify , -the shell will notify you immediately of changes of status in background -jobs. -There is also a shell command -.Ar notify -that marks a single process so that its status changes will be immediately -reported. -By default -.Ar notify -marks the current process; -simply say `notify' after starting a background job to mark it. -.Pp -When you try to leave the shell while jobs are stopped, you will -be warned that `You have stopped jobs.' -You may use the -.Ar jobs -command to see what they are. -If you try to exit again immediately, -the shell will not warn you a second time, and the suspended -jobs will be terminated. -.Ss File Name Completion -When the file name completion feature is enabled by setting -the shell variable -.Ar filec -(see -.Ic set ) , -.Nm -will -interactively complete file names and user names from unique -prefixes, when they are input from the terminal followed by -the escape character (the escape key, or control-[) -For example, -if the current directory looks like -.Bd -literal -offset indent -DSC.OLD bin cmd lib xmpl.c -DSC.NEW chaosnet cmtest mail xmpl.o -bench class dev mbox xmpl.out -.Ed -.Pp -and the input is -.Pp -.Dl % vi ch\*[Lt]escape\*[Gt] -.Pp -.Nm -will complete the prefix ``ch'' -to the only matching file name ``chaosnet'', changing the input -line to -.Pp -.Dl % vi chaosnet -.Pp -However, given -.Pp -.Dl % vi D\*[Lt]escape\*[Gt] -.Pp -.Nm -will only expand the input to -.Pp -.Dl % vi DSC. -.Pp -and will sound the terminal bell to indicate that the expansion is -incomplete, since there are two file names matching the prefix ``D''. -.Pp -If a partial file name is followed by the end-of-file character -(usually control-D), then, instead of completing the name, -.Nm -will list all file names matching the prefix. -For example, -the input -.Pp -.Dl % vi D\*[Lt]control-D\*[Gt] -.Pp -causes all files beginning with ``D'' to be listed: -.Pp -.Dl DSC.NEW DSC.OLD -.Pp -while the input line remains unchanged. -.Pp -The same system of escape and end-of-file can also be used to -expand partial user names, if the word to be completed -(or listed) begins with the character ``~''. -For example, typing -.Pp -.Dl cd ~ro\*[Lt]escape\*[Gt] -.Pp -may produce the expansion -.Pp -.Dl cd ~root -.Pp -The use of the terminal bell to signal errors or multiple matches -can be inhibited by setting the variable -.Ar nobeep . -.Pp -Normally, all files in the particular directory are candidates -for name completion. -Files with certain suffixes can be excluded -from consideration by setting the variable -.Ar fignore -to the -list of suffixes to be ignored. -Thus, if -.Ar fignore -is set by -the command -.Pp -.Dl % set fignore = (.o .out) -.Pp -then typing -.Pp -.Dl % vi x\*[Lt]escape\*[Gt] -.Pp -would result in the completion to -.Pp -.Dl % vi xmpl.c -.Pp -ignoring the files "xmpl.o" and "xmpl.out". -However, if the only completion possible requires not ignoring these -suffixes, then they are not ignored. -In addition, -.Ar fignore -does not affect the listing of file names by control-D. -All files -are listed regardless of their suffixes. -.Ss Substitutions -We now describe the various transformations the shell performs on the -input in the order in which they occur. -.Ss History substitutions -History substitutions place words from previous command input as portions -of new commands, making it easy to repeat commands, repeat arguments -of a previous command in the current command, or fix spelling mistakes -in the previous command with little typing and a high degree of confidence. -History substitutions begin with the character `!' and may begin -.Ar anywhere -in the input stream (with the proviso that they -.Em do not -nest.) -This `!' may be preceded by a `\e' to prevent its special meaning; for -convenience, an `!' is passed unchanged when it is followed by a blank, -tab, newline, `=' or `('. -(History substitutions also occur when an input line begins with `\*(ua'. -This special abbreviation will be described later.) -Any input line that contains history substitution is echoed on the terminal -before it is executed as it would have been typed without history substitution. -.Pp -Commands input from the terminal that consist of one or more words -are saved on the history list. -The history substitutions reintroduce sequences of words from these -saved commands into the input stream. -The size of the history list is controlled by the -.Ar history -variable; the previous command is always retained, -regardless of the value of the history variable. -Commands are numbered sequentially from 1. -.Pp -For example, consider the following output from the -.Ar history -command: -.Bd -literal -offset indent -09 write michael -10 ex write.c -11 cat oldwrite.c -12 diff *write.c -.Ed -.Pp -The commands are shown with their event numbers. -It is not usually necessary to use event numbers, but the current event -number can be made part of the -.Ar prompt -by placing an `!' in the prompt string. -.Pp -With the current event 13 we can refer to previous events by event -number `!11', relatively as in `!\-2' (referring to the same event), -by a prefix of a command word -as in `!d' for event 12 or `!wri' for event 9, or by a string contained in -a word in the command as in `!?mic?' also referring to event 9. -These forms, without further change, simply reintroduce the words -of the specified events, each separated by a single blank. -As a special case, `!!' refers to the previous command; thus `!!' alone is a -.Ar redo . -.Pp -To select words from an event we can follow the event specification by -a `:' and a designator for the desired words. -The words of an input line are numbered from 0, -the first (usually command) word being 0, the second word (first argument) -being 1, etc. -The basic word designators are: -.Pp -.Bl -tag -width Ds -compact -offset indent -.It \&0 -first (command) word -.It Ar n -.Ar n Ns 'th -argument -.It \*(ua -first argument, i.e., `1' -.It $ -last argument -.It % -word matched by (immediately preceding) -.No \&? Ns Ar s Ns \&? -search -.It Ar \&x\-y -range of words -.It Ar \&\-y -abbreviates -.Ar `\&0\-y\' -.It * -abbreviates `\*(ua\-$', or nothing if only 1 word in event -.It Ar x* -abbreviates -.Ar `x\-$\' -.It Ar x\- -like -.Ar `x*\' -but omitting word `$' -.El -.Pp -The `:' separating the event specification from the word designator -can be omitted if the argument selector begins with a `\*(ua', `$', `*', -`\-' or `%'. -After the optional word designator can be -placed a sequence of modifiers, each preceded by a `:'. -The following modifiers are defined: -.Pp -.Bl -tag -width Ds -compact -offset indent -.It h -Remove a trailing pathname component, leaving the head. -.It r -Remove a trailing `.xxx' component, leaving the root name. -.It e -Remove all but the extension `.xxx' part. -.It s Ns Ar /l/r/ -Substitute -.Ar l -for -.Ar r -.It t -Remove all leading pathname components, leaving the tail. -.It \&\*[Am] -Repeat the previous substitution. -.It g -Apply the change once on each word, prefixing the above, e.g., `g\*[Am]'. -.It a -Apply the change as many times as possible on a single word, prefixing -the above. -It can be used together with `g' to apply a substitution -globally. -.It p -Print the new command line but do not execute it. -.It q -Quote the substituted words, preventing further substitutions. -.It x -Like q, but break into words at blanks, tabs and newlines. -.El -.Pp -Unless preceded by a `g' the change is applied only to the first -modifiable word. -With substitutions, it is an error for no word to be applicable. -.Pp -The left hand side of substitutions are not regular expressions in the sense -of the editors, but instead strings. -Any character may be used as the delimiter in place of `/'; -a `\e' quotes the delimiter into the -.Ar l -and -.Ar r -strings. -The character `\*[Am]' in the right hand side is replaced by the text from -the left. -A `\e' also quotes `\*[Am]'. -A null -.Ar l -(`//') -uses the previous string either from an -.Ar l -or from a -contextual scan string -.Ar s -in -.No \&`!? Ns Ar s Ns \e?' . -The trailing delimiter in the substitution may be omitted if a newline -follows immediately as may the trailing `?' in a contextual scan. -.Pp -A history reference may be given without an event specification, e.g., `!$'. -Here, the reference is to the previous command unless a previous -history reference occurred on the same line in which case this form repeats -the previous reference. -Thus `!?foo?\*(ua !$' gives the first and last arguments -from the command matching `?foo?'. -.Pp -A special abbreviation of a history reference occurs when the first -non-blank character of an input line is a `\*(ua'. -This is equivalent to `!:s\*(ua' providing a convenient -shorthand for substitutions on the text of the previous line. -Thus `\*(ualb\*(ualib' fixes the spelling of -`lib' -in the previous command. -Finally, a history substitution may be surrounded with `{' and `}' -if necessary to insulate it from the characters that follow. -Thus, after `ls \-ld ~paul' we might do `!{l}a' to do `ls \-ld ~paula', -while `!la' would look for a command starting with `la'. -.Ss Quotations with \' and \&" -The quotation of strings by `\'' and `"' can be used -to prevent all or some of the remaining substitutions. -Strings enclosed in `\'' are prevented any further interpretation. -Strings enclosed in `"' may be expanded as described below. -.Pp -In both cases the resulting text becomes (all or part of) a single word; -only in one special case (see -.Em Command Substitution -below) does a `"' quoted string yield parts of more than one word; -`\'' quoted strings never do. -.Ss Alias substitution -The shell maintains a list of aliases that can be established, displayed -and modified by the -.Ar alias -and -.Ar unalias -commands. -After a command line is scanned, it is parsed into distinct commands and -the first word of each command, left-to-right, is checked to see if it -has an alias. -If it does, then the text that is the alias for that command is reread -with the history mechanism available -as though that command were the previous input line. -The resulting words replace the -command and argument list. -If no reference is made to the history list, then the argument list is -left unchanged. -.Pp -Thus if the alias for `ls' is `ls \-l' the command `ls /usr' would map to -`ls \-l /usr', the argument list here being undisturbed. -Similarly if the alias for `lookup' was `grep !\*(ua /etc/passwd' then -`lookup bill' would map to `grep bill /etc/passwd'. -.Pp -If an alias is found, the word transformation of the input text -is performed and the aliasing process begins again on the reformed input line. -Looping is prevented if the first word of the new text is the same as the old -by flagging it to prevent further aliasing. -Other loops are detected and cause an error. -.Pp -Note that the mechanism allows aliases to introduce parser metasyntax. -Thus, we can `alias print \'pr \e!* \&| lpr\'' to make a command that -.Ar pr Ns 's -its arguments to the line printer. -.Ss Variable substitution -The shell maintains a set of variables, each of which has as value a list -of zero or more words. -Some of these variables are set by the shell or referred to by it. -For instance, the -.Ar argv -variable is an image of the shell's argument list, and words of this -variable's value are referred to in special ways. -.Pp -The values of variables may be displayed and changed by using the -.Ar set -and -.Ar unset -commands. -Of the variables referred to by the shell a number are toggles; -the shell does not care what their value is, -only whether they are set or not. -For instance, the -.Ar verbose -variable is a toggle that causes command input to be echoed. -The setting of this variable results from the -.Fl v -command line option. -.Pp -Other operations treat variables numerically. -The `@' command permits numeric calculations to be performed and the result -assigned to a variable. -Variable values are, however, always represented as (zero or more) strings. -For the purposes of numeric operations, the null string is considered to be -zero, and the second and additional words of multiword values are ignored. -.Pp -After the input line is aliased and parsed, and before each command -is executed, variable substitution -is performed keyed by `$' characters. -This expansion can be prevented by preceding the `$' with a `\e' except -within `"'s where it -.Em always -occurs, and within `\''s where it -.Em never -occurs. -Strings quoted by `\*(ga' are interpreted later (see -.Sx Command substitution -below), so `$' substitution does not occur there until later, if at all. -A `$' is passed unchanged if followed by a blank, tab, or end-of-line. -.Pp -Input/output redirections are recognized before variable expansion, -and are variable expanded separately. -Otherwise, the command name and entire argument list are expanded together. -It is thus possible for the first (command) word (to this point) to generate -more than one word, the first of which becomes the command name, -and the rest of which become arguments. -.Pp -Unless enclosed in `"' or given the `:q' modifier the results of variable -substitution may eventually be command and filename substituted. -Within `"', a variable whose value consists of multiple words expands to a -(portion of) a single word, with the words of the variable's value -separated by blanks. -When the `:q' modifier is applied to a substitution -the variable will expand to multiple words with each word separated -by a blank and quoted to prevent later command or filename substitution. -.Pp -The following metasequences are provided for introducing variable values into -the shell input. -Except as noted, it is an error to reference a variable that is not set. -.Pp -.Bl -tag -width Ds -compact -offset indent -.It $name -.It ${name} -Are replaced by the words of the value of variable -.Ar name , -each separated by a blank. -Braces insulate -.Ar name -from following characters that would otherwise be part of it. -Shell variables have names consisting of up to 20 letters and digits -starting with a letter. -The underscore character is considered a letter. -If -.Ar name -is not a shell variable, but is set in the environment, then -that value is returned (but `:' modifiers and the other forms -given below are not available here). -.It $name Ns Op selector -.It ${name Ns [ selector ] Ns } -May be used to select only some of the words from the value of -.Ar name . -The selector is subjected to `$' substitution and may consist of a single -number or two numbers separated by a `\-'. -The first word of a variable's value is numbered `1'. -If the first number of a range is omitted it defaults to `1'. -If the last number of a range is omitted it defaults to `$#name'. -The selector `*' selects all words. -It is not an error for a range to be empty if the second argument is omitted -or in range. -.It $#name -.It ${#name} -Gives the number of words in the variable. -This is useful for later use in a -`$argv[selector]'. -.It $0 -Substitutes the name of the file from which command input is being read. -An error occurs if the name is not known. -.It $number -.It ${number} -Equivalent to -`$argv[number]'. -.It $* -Equivalent to -`$argv[*]'. -.El -.Pp -The modifiers `:e', `:h', `:t', `:r', `:q' and `:x' may be applied to -the substitutions above as may `:gh', `:gt' and `:gr'. -If braces `{' '}' appear in the command form then the modifiers -must appear within the braces. -The current implementation allows only one `:' modifier on each `$' expansion. -.Pp -The following substitutions may not be modified with `:' modifiers. -.Bl -tag -width Ds -compact -offset indent -.It $?name -.It ${?name} -Substitutes the string `1' if name is set, `0' if it is not. -.It $?0 -Substitutes `1' if the current input filename is known, `0' if it is not. -.It \&$\&$\& -Substitute the (decimal) process number of the (parent) shell. -.It $! -Substitute the (decimal) process number of the last background process -started by this shell. -.It $\*[Lt] -Substitutes a line from the standard -input, with no further interpretation. -It can be used to read from the keyboard in a shell script. -.El -.Ss Command and filename substitution -The remaining substitutions, command and filename substitution, -are applied selectively to the arguments of builtin commands. -By selectively, we mean that portions of expressions which are -not evaluated are not subjected to these expansions. -For commands that are not internal to the shell, the command -name is substituted separately from the argument list. -This occurs very late, -after input-output redirection is performed, and in a child -of the main shell. -.Ss Command substitution -Command substitution is shown by a command enclosed in `\*(ga'. -The output from such a command is normally broken into separate words -at blanks, tabs and newlines, with null words being discarded; -this text then replaces the original string. -Within `"'s, only newlines force new words; blanks and tabs are preserved. -.Pp -In any case, the single final newline does not force a new word. -Note that it is thus possible for a command substitution to yield -only part of a word, even if the command outputs a complete line. -.Ss Filename substitution -If a word contains any of the characters `*', `?', `[' or `{' -or begins with the character `~', then that word is a candidate for -filename substitution, also known as `globbing'. -This word is then regarded as a pattern, and replaced with an alphabetically -sorted list of file names that match the pattern. -In a list of words specifying filename substitution it is an error for -no pattern to match an existing file name, but it is not required -for each pattern to match. -Only the metacharacters `*', `?' and `[' imply pattern matching, -the characters `~' and `{' being more akin to abbreviations. -.Pp -In matching filenames, the character `.' at the beginning of a filename -or immediately following a `/', as well as the character `/' must -be matched explicitly. -The character `*' matches any string of characters, including the null -string. -The character `?' matches any single character. -The sequence -.Sq Op ... -matches any one of the characters enclosed. -Within -.Sq Op ... , -a pair of characters separated by `\-' matches any character lexically between -the two (inclusive). -.Pp -The character `~' at the beginning of a filename refers to home -directories. -Standing alone, i.e., `~' it expands to the invoker's home directory as reflected -in the value of the variable -.Ar home . -When followed by a name consisting of letters, digits and `\-' characters, -the shell searches for a user with that name and substitutes their -home directory; thus `~ken' might expand to `/usr/ken' and `~ken/chmach' -to `/usr/ken/chmach'. -If the character `~' is followed by a character other than a letter or `/' -or does not appear at the beginning of a word, -it is left undisturbed. -.Pp -The metanotation `a{b,c,d}e' is a shorthand for `abe ace ade'. -Left to right order is preserved, with results of matches being sorted -separately at a low level to preserve this order. -This construct may be nested. -Thus, `~source/s1/{oldls,ls}.c' expands to -`/usr/source/s1/oldls.c /usr/source/s1/ls.c' -without chance of error -if the home directory for `source' is `/usr/source'. -Similarly `../{memo,*box}' might expand to `../memo ../box ../mbox'. -(Note that `memo' was not sorted with the results of the match to `*box'.) -As a special case `{', `}' and `{}' are passed undisturbed. -.Ss Input/output -The standard input and the standard output of a command may be redirected -with the following syntax: -.Pp -.Bl -tag -width Ds -compact -offset indent -.It \*[Lt] name -Open file -.Ar name -(which is first variable, command and filename expanded) as the standard -input. -.It \*[Lt]\*[Lt] word -Read the shell input up to a line that is identical to -.Ar word . -.Ar Word -is not subjected to variable, filename or command substitution, -and each input line is compared to -.Ar word -before any substitutions are done on the input line. -Unless a quoting `\e', `"', `\*(aa' or `\*(ga' appears in -.Ar word , -variable and command substitution is performed on the intervening lines, -allowing `\e' to quote `$', `\e' and `\*(ga'. -Commands that are substituted have all blanks, tabs, and newlines -preserved, except for the final newline which is dropped. -The resultant text is placed in an anonymous temporary file that -is given to the command as its standard input. -.It \*[Gt] name -.It \*[Gt]! name -.It \*[Gt]\*[Am] name -.It \*[Gt]\*[Am]! name -The file -.Ar name -is used as the standard output. -If the file does not exist then it is created; -if the file exists, it is truncated; its previous contents are lost. -.Pp -If the variable -.Ar noclobber -is set, then the file must not exist or be a character special file (e.g., a -terminal or `/dev/null') or an error results. -This helps prevent accidental destruction of files. -Here, the `!' forms can be used to suppress this check. -.Pp -The forms involving `\*[Am]' route the standard error output into the specified -file as well as the standard output. -.Ar Name -is expanded in the same way as `\*[Lt]' input filenames are. -.It \*[Gt]\*[Gt] name -.It \*[Gt]\*[Gt]\*[Am] name -.It \*[Gt]\*[Gt]! name -.It \*[Gt]\*[Gt]\*[Am]! name -Uses file -.Ar name -as the standard output; -like `\*[Gt]' but places output at the end of the file. -If the variable -.Ar noclobber -is set, then it is an error for the file not to exist unless -one of the `!' forms is given. -Otherwise similar to `\*[Gt]'. -.El -.Pp -A command receives the environment in which the shell was -invoked as modified by the input-output parameters and -the presence of the command in a pipeline. -Thus, unlike some previous shells, commands run from a file of shell commands -have no access to the text of the commands by default; -instead they receive the original standard input of the shell. -The `\*[Lt]\*[Lt]' mechanism should be used to present inline data. -This permits shell command scripts to function as components of pipelines -and allows the shell to block read its input. -Note that the default standard input for a command run detached is -.Ar not -modified to be the empty file -.Pa /dev/null ; -instead the standard input -remains as the original standard input of the shell. -If this is a terminal -and if the process attempts to read from the terminal, then the process -will block and the user will be notified (see -.Sx Jobs -above). -.Pp -The standard error output may be directed through -a pipe with the standard output. -Simply use the form `\&|\*[Am]' instead of just `\&|'. -.Ss Expressions -Several of the builtin commands (to be described later) -take expressions, in which the operators are similar to those of C, with -the same precedence, but with the -.Em opposite grouping : -right to left. -These expressions appear in the -.Ar @ , -.Ar exit , -.Ar if , -and -.Ar while -commands. -The following operators are available: -.Bd -ragged -offset indent -\&|\&| \*[Am]\*[Am] \&| \*(ua \*[Am] == != =~ !~ \*[Le] \*[Ge] -\*[Lt] \*[Gt] \*[Lt]\*[Lt] \*[Gt]\*[Gt] + \- * / % ! ~ ( ) -.Ed -.Pp -Here the precedence increases to the right, -`==' `!=' `=~' and `!~', `\*[Le]' `\*[Ge]' `\*[Lt]' -and `\*[Gt]', `\*[Lt]\*[Lt]' and `\*[Gt]\*[Gt]', `+' and `\-', -`*' `/' and `%' being, in groups, at the same level. -The `==' `!=' `=~' and `!~' operators compare their arguments as strings; -all others operate on numbers. -The operators `=~' and `!~' are like `!=' and `==' except that the right -hand side is a -.Ar pattern -(containing, e.g., `*'s, `?'s and instances of `[...]') -against which the left hand operand is matched. -This reduces the need for use of the -.Ar switch -statement in shell scripts when all that is really needed is pattern matching. -.Pp -Strings that begin with `0' are considered octal numbers. -Null or missing arguments are considered `0'. -The result of all expressions are strings, -which represent decimal numbers. -It is important to note that no two components of an expression can appear -in the same word; except when adjacent to components of expressions that -are syntactically significant to the parser -(`\*[Am]' `\&|' `\*[Lt]' `\*[Gt]' `(' `)'), -they should be surrounded by spaces. -.Pp -Also available in expressions as primitive operands are command executions -enclosed in `{' and `}' -and file enquiries of the form -.Fl l -.Ar name -where -.Ic l -is one of: -.Bd -literal -offset indent -r read access -w write access -x execute access -e existence -o ownership -z zero size -f plain file -d directory -.Ed -.Pp -The specified name is command and filename expanded and then tested -to see if it has the specified relationship to the real user. -If the file does not exist or is inaccessible then all enquiries return -false, i.e., `0'. -Command executions succeed, returning true, i.e., `1', -if the command exits with status 0, otherwise they fail, returning -false, i.e., `0'. -If more detailed status information is required then the command -should be executed outside an expression and the variable -.Ar status -examined. -.Ss Control flow -The shell contains several commands that can be used to regulate the -flow of control in command files (shell scripts) and -(in limited but useful ways) from terminal input. -These commands all operate by forcing the shell to reread or skip in its -input and, because of the implementation, restrict the placement of some -of the commands. -.Pp -The -.Ic foreach , -.Ic switch , -and -.Ic while -statements, as well as the -.Ic if\-then\-else -form of the -.Ic if -statement require that the major keywords appear in a single simple command -on an input line as shown below. -.Pp -If the shell's input is not seekable, -the shell buffers up input whenever a loop is being read -and performs seeks in this internal buffer to accomplish the rereading -implied by the loop. -(To the extent that this allows, backward goto's will succeed on -non-seekable inputs.) -.Ss Builtin commands -Builtin commands are executed within the shell. -If a builtin command occurs as any component of a pipeline -except the last then it is executed in a subshell. -.Pp -.Bl -tag -width Ds -compact -offset indent -.It Ic alias -.It Ic alias Ar name -.It Ic alias Ar name wordlist -The first form prints all aliases. -The second form prints the alias for name. -The final form assigns the specified -.Ar wordlist -as the alias of -.Ar name ; -.Ar wordlist -is command and filename substituted. -.Ar Name -is not allowed to be -.Ar alias -or -.Ar unalias . -.Pp -.It Ic bg -.It Ic bg \&% Ns Ar job ... -Puts the current or specified jobs into the background, continuing them -if they were stopped. -.Pp -.It Ic break -Causes execution to resume after the -.Ic end -of the nearest enclosing -.Ic foreach -or -.Ic while . -The remaining commands on the current line are executed. -Multi-level breaks are thus possible by writing them all on one line. -.Pp -.It Ic breaksw -Causes a break from a -.Ic switch , -resuming after the -.Ic endsw . -.Pp -.It Ic case Ar label : -A label in a -.Ic switch -statement as discussed below. -.Pp -.It Ic cd -.It Ic cd Ar name -.It Ic chdir -.It Ic chdir Ar name -Change the shell's working directory to directory -.Ar name . -If no argument is given then change to the home directory of the user. -If -.Ar name -is not found as a subdirectory of the current directory (and does not begin -with `/', `./' or `../'), then each -component of the variable -.Ic cdpath -is checked to see if it has a subdirectory -.Ar name . -Finally, if all else fails but -.Ar name -is a shell variable whose value begins with `/', then this -is tried to see if it is a directory. -.Pp -.It Ic continue -Continue execution of the nearest enclosing -.Ic while -or -.Ic foreach . -The rest of the commands on the current line are executed. -.Pp -.It Ic default : -Labels the default case in a -.Ic switch -statement. -The default should come after all -.Ic case -labels. -.Pp -.It Ic dirs -Prints the directory stack; the top of the stack is at the left, -the first directory in the stack being the current directory. -.Pp -.It Ic echo Ar wordlist -.It Ic echo Fl n Ar wordlist -The specified words are written to the shell's standard output, separated -by spaces, and terminated with a newline unless the -.Fl n -option is specified. -.Pp -.It Ic else -.It Ic end -.It Ic endif -.It Ic endsw -See the description of the -.Ic foreach , -.Ic if , -.Ic switch , -and -.Ic while -statements below. -.Pp -.It Ic eval Ar arg ... -(As in -.Xr sh 1 . ) -The arguments are read as input to the shell and the resulting -command(s) executed in the context of the current shell. -This is usually used to execute commands -generated as the result of command or variable substitution, since -parsing occurs before these substitutions. -See -.Xr tset 1 -for an example of using -.Ic eval . -.Pp -.It Ic exec Ar command -The specified command is executed in place of the current shell. -.Pp -.It Ic exit -.It Ic exit Ar ( expr ) -The shell exits either with the value of the -.Ic status -variable (first form) or with the value of the specified -.Ic expr -(second form). -.Pp -.It Ic fg -.It Ic fg % Ns Ar job ... -Brings the current or specified jobs into the foreground, continuing them if -they were stopped. -.Pp -.It Ic foreach Ar name ( wordlist ) -.It ... -.It Ic end -The variable -.Ic name -is successively set to each member of -.Ic wordlist -and the sequence of commands between this command and the matching -.Ic end -are executed. -(Both -.Ic foreach -and -.Ic end -must appear alone on separate lines.) -The builtin command -.Ic continue -may be used to continue the loop prematurely and the builtin -command -.Ic break -to terminate it prematurely. -When this command is read from the terminal, the loop is read once -prompting with `?' before any statements in the loop are executed. -If you make a mistake typing in a loop at the terminal you can rub it out. -.Pp -.It Ic glob Ar wordlist -Like -.Ic echo -but no `\e' escapes are recognized and words are delimited -by null characters in the output. -Useful for programs that wish to use the shell to filename expand a list -of words. -.Pp -.It Ic goto Ar word -The specified -.Ic word -is filename and command expanded to yield a string of the form `label'. -The shell rewinds its input as much as possible -and searches for a line of the form `label:' -possibly preceded by blanks or tabs. -Execution continues after the specified line. -.Pp -.It Ic hashstat -Print a statistics line showing how effective the internal hash -table has been at locating commands (and avoiding -.Ic exec Ns \'s ) . -An -.Ic exec -is attempted for each component of the -.Em path -where the hash function indicates a possible hit, and in each component -that does not begin with a `/'. -.Pp -.It Ic history -.It Ic history Ar n -.It Ic history Fl r Ar n -.It Ic history Fl h Ar n -Displays the history event list; if -.Ar n -is given only the -.Ar n -most recent events are printed. -The -.Fl r -option reverses the order of printout to be most recent first -instead of oldest first. -The -.Fl h -option causes the history list to be printed without leading numbers. -This format produces files suitable for sourcing using the \-h -option to -.Ic source . -.Pp -.It Ic if Ar ( expr ) No command -If the specified expression evaluates true, then the single -.Ar command -with arguments is executed. -Variable substitution on -.Ar command -happens early, at the same -time it does for the rest of the -.Ic if -command. -.Ar Command -must be a simple command, not -a pipeline, a command list, or a parenthesized command list. -Input/output redirection occurs even if -.Ar expr -is false, i.e., when command is -.Em not -executed (this is a bug). -.Pp -.It Ic if Ar ( expr ) Ic then -.It ... -.It Ic else if Ar ( expr2 ) Ic then -.It ... -.It Ic else -.It ... -.It Ic endif -If the specified -.Ar expr -is true then the commands up to the first -.Ic else -are executed; otherwise if -.Ar expr2 -is true then the commands up to the -second -.Ic else -are executed, etc. -Any number of -.Ic else-if -pairs are possible; only one -.Ic endif -is needed. -The -.Ic else -part is likewise optional. -(The words -.Ic else -and -.Ic endif -must appear at the beginning of input lines; -the -.Ic if -must appear alone on its input line or after an -.Ic else . ) -.Pp -.It Ic jobs -.It Ic jobs Fl l -Lists the active jobs; the -.Fl l -option lists process id's in addition to the normal information. -.Pp -.It Ic kill % Ns Ar job -.It Ic kill Ar pid ... -.It Ic kill Fl l Op Ar exit_status -.It Ic kill Fl s Ar signal_name pid ... -.It Ic kill Fl Ar signal_name Ar pid ... -.It Ic kill Fl Ar signal_number Ar pid ... -Sends either the TERM (terminate) signal or the -specified signal to the specified jobs or processes. -Signals are either given by number or by names (as given in -.In signal.h , -stripped of the prefix ``SIG''). -The signal names are listed by ``kill \-l''; -if an -.Ar exit_status -is specified, only the corresponding signal name will be written. -There is no default, just saying `kill' does not -send a signal to the current job. -If the signal being sent is TERM (terminate) or HUP (hangup), -then the job or process will be sent a CONT (continue) signal as well. -.Pp -.It Ic limit -.It Ic limit Ar resource -.It Ic limit Ar resource maximum-use -.It Ic limit Fl h -.It Ic limit Fl h Ar resource -.It Ic limit Fl h Ar resource maximum-use -Manipulates per-process system resource limits via the -.Xr getrlimit 2 -and -.Xr setrlimit 2 -system calls; this -limits the consumption by the current process and each process -it creates to not individually exceed -.Ar maximum-use -on the -specified -.Ar resource . -If no -.Ar maximum-use -is given, then -the current limit is printed; if no -.Ar resource -is given, then -all limitations are given. -.Pp -If the -.Fl h -flag is given, the hard limits are used instead of the current -limits. -The hard limits impose a ceiling on the values of the current limits. -Only the super-user may raise the hard limits, -but a user may lower or raise the current limits within the legal range. -.Pp -Resources controllable currently include: -.Bl -tag -width coredumpsize -.It Ar cputime -The maximum number of CPU-seconds to be used by each process. -.It Ar filesize -The largest single file (in bytes) that can be created. -.It Ar datasize -The maximum growth of the data+stack region via -.Xr sbrk 2 -beyond the end of the program text. -.It Ar stacksize -The maximum -size of the automatically-extended stack region. -.It Ar coredumpsize -The size of the largest core dump (in bytes) that will be created. -.It Ar memoryuse -The maximum size (in bytes) to which a process's resident set -size (RSS) may grow. -.It Ar memorylocked -The maximum size (in bytes) which a process may lock into memory using the -.Xr mlock 2 -function. -.It Ar maxproc -The maximum number of simultaneous processes for this user id. -.It Ar openfiles -The maximum number of simultaneous open files for this user id. -.It Ar sbsize -The maximum socket buffer size of a process (in bytes). -.It Ar vmemoryuse -The maximum size (in bytes) which a process can obtain. -.El -.Pp -The -.Ar maximum-use -may be given as a (floating point or integer) -number followed by a scale factor. -For all limits other than -.Ar cputime -the default scale is `k' or `kilobytes' (1024 bytes); -a scale factor of `m' or `megabytes' may also be used. -For -.Ar cputime -the default scale is `seconds'; -a scale factor of `m' for minutes -or `h' for hours, or a time of the form `mm:ss' giving minutes -and seconds also may be used. -.Pp -For both -.Ar resource -names and scale factors, unambiguous prefixes -of the names suffice. -.Pp -Limits of an arbitrary process can be displayed or set using the -.Xr sysctl 8 -utility. -See the -.Xr getrlimit 2 -and -.Xr setrlimit 2 -man pages for an additional description of system resource limits. -.Pp -.It Ic login -Terminate a login shell, replacing it with an instance of -.Pa /usr/bin/login . -This is one way to log off, included for compatibility with -.Xr sh 1 . -.Pp -.It Ic logout -Terminate a login shell. -Especially useful if -.Ic ignoreeof -is set. -.Pp -.It Ic nice -.It Ic nice Ar +number -.It Ic nice Ar command -.It Ic nice Ar +number command -The first form sets the -scheduling priority -for this shell to 4. -The second form sets the -priority -to the given -.Ar number . -The final two forms run command at priority 4 and -.Ar number -respectively. -The greater the number, the less CPU the process will get. -The super-user may specify negative priority by using `nice \-number ...'. -.Ar Command -is always executed in a sub-shell, and the restrictions -placed on commands in simple -.Ic if -statements apply. -.Pp -.It Ic nohup -.It Ic nohup Ar command -The first form can be used in shell scripts to cause hangups to be -ignored for the remainder of the script. -The second form causes the specified command to be run with hangups -ignored. -All processes detached with `\*[Am]' are effectively -.Ic nohup Ns \'ed . -.Pp -.It Ic notify -.It Ic notify % Ns Ar job ... -Causes the shell to notify the user asynchronously when the status of the -current or specified jobs change; normally notification is presented -before a prompt. -This is automatic if the shell variable -.Ic notify -is set. -.Pp -.It Ic onintr -.It Ic onintr Fl -.It Ic onintr Ar label -Control the action of the shell on interrupts. -The first form restores the default action of the shell on interrupts -which is to terminate shell scripts or to return to the terminal command -input level. -The second form `onintr \-' causes all interrupts to be ignored. -The final form causes the shell to execute a `goto label' when -an interrupt is received or a child process terminates because -it was interrupted. -.Pp -In any case, if the shell is running detached and interrupts are -being ignored, all forms of -.Ic onintr -have no meaning and interrupts -continue to be ignored by the shell and all invoked commands. -Finally -.Ic onintr -statements are ignored in the system startup files where interrupts -are disabled (/etc/csh.cshrc, /etc/csh.login). -.Pp -.It Ic popd -.It Ic popd Ar +n -Pops the directory stack, returning to the new top directory. -With an argument -.Ns \`+ Ar n Ns \' -discards the -.Ar n Ns \'th -entry in the stack. -The members of the directory stack are numbered from the top starting at 0. -.Pp -.It Ic pushd -.It Ic pushd Ar name -.It Ic pushd Ar +n -With no arguments, -.Ic pushd -exchanges the top two elements of the directory stack. -Given a -.Ar name -argument, -.Ic pushd -changes to the new directory (ala -.Ic cd ) -and pushes the old current working directory -(as in -.Ic cwd ) -onto the directory stack. -With a numeric argument, -.Ic pushd -rotates the -.Ar n Ns \'th -argument of the directory -stack around to be the top element and changes to it. -The members -of the directory stack are numbered from the top starting at 0. -.Pp -.It Ic rehash -Causes the internal hash table of the contents of the directories in -the -.Ic path -variable to be recomputed. -This is needed if new commands are added to directories in the -.Ic path -while you are logged in. -This should only be necessary if you add -commands to one of your own directories, or if a systems programmer -changes the contents of a system directory. -.Pp -.It Ic repeat Ar count command -The specified -.Ar command , -which is subject to the same restrictions -as the -.Ar command -in the one line -.Ic if -statement above, -is executed -.Ar count -times. -I/O redirections occur exactly once, even if -.Ar count -is 0. -.Pp -.It Ic set -.It Ic set Ar name -.It Ic set Ar name Ns =word -.It Ic set Ar name[index] Ns =word -.It Ic set Ar name Ns =(wordlist) -The first form of the command shows the value of all shell variables. -Variables that have other than a single word as their -value print as a parenthesized word list. -The second form sets -.Ar name -to the null string. -The third form sets -.Ar name -to the single -.Ar word . -The fourth form sets -the -.Ar index Ns 'th -component of -.Ar name -to -.Ar word ; -this component must already exist. -The final form sets -.Ar name -to the list of words in -.Ar wordlist . -The value is always command and filename expanded. -.Pp -These arguments may be repeated to set multiple values in a single set command. -Note however, that variable expansion happens for all arguments before any -setting occurs. -.Pp -.It Ic setenv -.It Ic setenv Ar name -.It Ic setenv Ar name value -The first form lists all current environment variables. -It is equivalent to -.Xr printenv 1 . -The last form sets the value of environment variable -.Ar name -to be -.Ar value , -a single string. -The second form sets -.Ar name -to an empty string. -The most commonly used environment variables -.Ev USER , -.Ev TERM , -and -.Ev PATH -are automatically imported to and exported from the -.Nm -variables -.Ar user , -.Ar term , -and -.Ar path ; -there is no need to use -.Ic setenv -for these. -.Pp -.It Ic shift -.It Ic shift Ar variable -The members of -.Ic argv -are shifted to the left, discarding -.Ic argv Ns Bq 1 . -It is an error for -.Ic argv -not to be set or to have less than one word as value. -The second form performs the same function on the specified variable. -.Pp -.It Ic source Ar name -.It Ic source Fl h Ar name -The shell reads commands from -.Ar name . -.Ic Source -commands may be nested; if they are nested too deeply the shell may -run out of file descriptors. -An error in a -.Ic source -at any level terminates all nested -.Ic source -commands. -Normally input during -.Ic source -commands is not placed on the history list; -the \-h option causes the commands to be placed on the -history list without being executed. -.Pp -.It Ic stop -.It Ic stop % Ns Ar job ... -Stops the current or specified jobs that are executing in the background. -.Pp -.It Ic suspend -Causes the shell to stop in its tracks, much as if it had been sent a stop -signal with -.Ic ^Z . -This is most often used to stop shells started by -.Xr su 1 . -.Pp -.It Ic switch Ar ( string ) -.It Ic case Ar str1 : -.It \ \ \ \ \&... -.It Ic \ \ \ \ breaksw -.It \ \ \ \ \&... -.It Ic default : -.It \ \ \ \ \&... -.It Ic \ \ \ \ breaksw -.It Ic endsw -Each case label is successively matched against the specified -.Ar string -which is first command and filename expanded. -The file metacharacters `*', `?' and `[...]' -may be used in the case labels, -which are variable expanded. -If none of the labels match before the `default' label is found, then -the execution begins after the default label. -Each case label and the default label must appear at the beginning of a line. -The command -.Ic breaksw -causes execution to continue after the -.Ic endsw . -Otherwise control may fall through case labels and the default label as in C. -If no label matches and there is no default, execution continues after -the -.Ic endsw . -.Pp -.It Ic time -.It Ic time Ar command -With no argument, a summary of time used by this shell and its children -is printed. -If arguments are given -the specified simple command is timed and a time summary -as described under the -.Ic time -variable is printed. -If necessary, an extra shell is created to print the time -statistic when the command completes. -.Pp -.It Ic umask -.It Ic umask Ar value -The file creation mask is displayed (first form) or set to the specified -value (second form). -The mask is given in octal. -Common values for -the mask are 002 giving all access to the group and read and execute -access to others or 022 giving all access except write access for -users in the group or others. -.Pp -.It Ic unalias Ar pattern -All aliases whose names match the specified pattern are discarded. -Thus all aliases are removed by `unalias *'. -It is not an error for nothing to be -.Ic unaliased . -.Pp -.It Ic unhash -Use of the internal hash table to speed location of executed programs -is disabled. -.Pp -.It Ic unlimit -.It Ic unlimit Ar resource -.It Ic unlimit Fl h -.It Ic unlimit Fl h Ar resource -Removes the limitation on -.Ar resource . -If no -.Ar resource -is specified, then all -.Ar resource -limitations are removed. -If -.Fl h -is given, the corresponding hard limits are removed. -Only the -super-user may do this. -.Pp -.It Ic unset Ar pattern -All variables whose names match the specified pattern are removed. -Thus all variables are removed by `unset *'; this has noticeably -distasteful side-effects. -It is not an error for nothing to be -.Ic unset . -.Pp -.It Ic unsetenv Ar pattern -Removes all variables whose name match the specified pattern from the -environment. -See also the -.Ic setenv -command above and -.Xr printenv 1 . -.Pp -.It Ic wait -Wait for all background jobs. -If the shell is interactive, then an interrupt can disrupt the wait. -After the interrupt, the shell prints names and job numbers of all jobs -known to be outstanding. -.Pp -.It Ic which Ar command -Displays the resolved command that will be executed by the shell. -.Pp -.It Ic while Ar ( expr ) -.It \&... -.It Ic end -While the specified expression evaluates non-zero, the commands between -the -.Ic while -and the matching -.Ic end -are evaluated. -.Ic Break -and -.Ic continue -may be used to terminate or continue the loop prematurely. -(The -.Ic while -and -.Ic end -must appear alone on their input lines.) -Prompting occurs here the first time through the loop as for the -.Ic foreach -statement if the input is a terminal. -.Pp -.It Ic % Ns Ar job -Brings the specified job into the foreground. -.Pp -.It Ic % Ns Ar job Ic \*[Am] -Continues the specified job in the background. -.Pp -.It Ic @ -.It Ic @ Ar name Ns = expr -.It Ic @ Ar name[index] Ns = expr -The first form prints the values of all the shell variables. -The second form sets the specified -.Ar name -to the value of -.Ar expr . -If the expression contains `\*[Lt]', `\*[Gt]', `\*[Am]' or `|' then at least -this part of the expression must be placed within `(' `)'. -The third form assigns the value of -.Ar expr -to the -.Ar index Ns 'th -argument of -.Ar name . -Both -.Ar name -and its -.Ar index Ns 'th -component must already exist. -.El -.Pp -The operators `*=', `+=', etc are available as in C. -The space separating the name from the assignment operator is optional. -Spaces are, however, mandatory in separating components of -.Ar expr -which would otherwise be single words. -.Pp -Special postfix `+\|+' and `\-\|\-' operators increment and decrement -.Ar name -respectively, i.e., `@ i++'. -.Ss Pre-defined and environment variables -The following variables have special meaning to the shell. -Of these, -.Ar argv , -.Ar cwd , -.Ar home , -.Ar path , -.Ar prompt , -.Ar shell -and -.Ar status -are always set by the shell. -Except for -.Ar cwd -and -.Ar status , -this setting occurs only at initialization; -these variables will not then be modified unless done -explicitly by the user. -.Pp -The shell copies the environment variable -.Ev USER -into the variable -.Ar user , -.Ev TERM -into -.Ar term , -and -.Ev HOME -into -.Ar home , -and copies these back into the environment whenever the normal -shell variables are reset. -The environment variable -.Ev PATH -is likewise handled; it is not -necessary to worry about its setting other than in the file -.Ar \&.cshrc -as inferior -.Nm -processes will import the definition of -.Ar path -from the environment, and re-export it if you then change it. -.Bl -tag -width histchars -.It Ic argv -Set to the arguments to the shell, it is from this variable that -positional parameters are substituted, i.e., `$1' is replaced by -`$argv[1]', -etc. -.It Ic cdpath -Gives a list of alternative directories searched to find subdirectories -in -.Ar chdir -commands. -.It Ic cwd -The full pathname of the current directory. -.It Ic echo -Set when the -.Fl x -command line option is given. -Causes each command and its arguments -to be echoed just before it is executed. -For non-builtin commands all expansions occur before echoing. -Builtin commands are echoed before command and filename substitution, -since these substitutions are then done selectively. -.It Ic filec -Enable file name completion. -.It Ic histchars -Can be given a string value to change the characters used in history -substitution. -The first character of its value is used as the -history substitution character, replacing the default character `!'. -The second character of its value replaces the character `^' in -quick substitutions. -.It Ic histfile -Can be set to the pathname where history is going to be saved/restored. -.It Ic history -Can be given a numeric value to control the size of the history list. -Any command that has been referenced in this many events will not be -discarded. -Too large values of -.Ar history -may run the shell out of memory. -The last executed command is always saved on the history list. -.It Ic home -The home directory of the invoker, initialized from the environment. -The filename expansion of -.Sq Pa ~ -refers to this variable. -.It Ic ignoreeof -If set the shell ignores -end-of-file from input devices which are terminals. -This prevents shells from accidentally being killed by control-D's. -.It Ic mail -The files where the shell checks for mail. -This checking is done after each command completion that will -result in a prompt, -if a specified interval has elapsed. -The shell says `You have new mail.' -if the file exists with an access time not greater than its modify time. -.Pp -If the first word of the value of -.Ar mail -is numeric it specifies a different mail checking interval, in seconds, -than the default, which is 10 minutes. -.Pp -If multiple mail files are specified, then the shell says -`New mail in -.Ar name Ns ' -when there is mail in the file -.Ar name . -.It Ic noclobber -As described in the section on -.Sx Input/output , -restrictions are placed on output redirection to ensure that -files are not accidentally destroyed, and that `\*[Gt]\*[Gt]' redirections -refer to existing files. -.It Ic noglob -If set, filename expansion is inhibited. -This inhibition is most useful in shell scripts that - are not dealing with filenames, -or after a list of filenames has been obtained and further expansions -are not desirable. -.It Ic nonomatch -If set, it is not an error for a filename expansion to not match any -existing files; instead the primitive pattern is returned. -It is still an error for the primitive pattern to be malformed, i.e., -`echo [' -still gives an error. -.It Ic notify -If set, the shell notifies asynchronously of job completions; -the default is to present job completions just before printing -a prompt. -.It Ic path -Each word of the path variable specifies a directory in which -commands are to be sought for execution. -A null word specifies the current directory. -If there is no -.Ar path -variable then only full path names will execute. -The usual search path is `.', `/bin' and `/usr/bin', but this -may vary from system to system. -For the super-user the default search path is `/etc', `/bin' and `/usr/bin'. -A shell that is given neither the -.Fl c -nor the -.Fl t -option will normally hash the contents of the directories in the -.Ar path -variable after reading -.Ar \&.cshrc , -and each time the -.Ar path -variable is reset. -If new commands are added to these directories -while the shell is active, it may be necessary to do a -.Ic rehash -or the commands may not be found. -.It Ic prompt -The string that is printed before each command is read from -an interactive terminal input. -If a `!' appears in the string it will be replaced by the current event number -unless a preceding `\e' is given. -Default is `% ', or `# ' for the super-user. -.It Ic savehist -Is given a numeric value to control the number of entries of the -history list that are saved in ~/.history when the user logs out. -Any command that has been referenced in this many events will be saved. -During start up the shell sources ~/.history into the history list -enabling history to be saved across logins. -Too large values of -.Ar savehist -will slow down the shell during start up. -If -.Ar savehist -is just set, the shell will use the value of -.Ar history . -.It Ic shell -The file in which the shell resides. -This variable is used in forking shells to interpret files that have execute -bits set, but which are not executable by the system. -(See the description of -.Sx Non-builtin command execution -below.) -Initialized to the (system-dependent) home of the shell. -.It Ic status -The status returned by the last command. -If it terminated abnormally, then 0200 is added to the status. -Builtin commands that fail return exit status `1', -all other builtin commands set status to `0'. -.It Ic time -Controls automatic timing of commands. -This setting allows two parameters. -The first specifies the CPU time threshold at which reporting should be done -for a process, and the optional second specifies the output format. -The following format strings are available: -.Pp -.Bl -tag -width Ds -compact -offset indent -.It Li \&%c -Number of involuntary context switches. -.It Li \&%D -Average unshared data size. -.It Li \&%E -Elapsed (wall\-clock) time. -.It Li \&%F -Page faults. -.It Li \&%I -Filesystem blocks in. -.It Li \&%K -Average total data memory used. -.It Li \&%k -Number of signals received. -.It Li \&%M -Maximum Resident Set Size. -.It Li \&%O -Filesystem blocks out. -.It Li \&%P -Total percent time spent running. -.It Li \&%R -Page reclaims. -.It Li \&%r -Socket messages received. -.It Li \&%S -Total system CPU time used. -.It Li \&%s -Socket messages sent. -.It Li \&%U -Total user CPU time used. -.It Li \&%W -Number of swaps. -.It Li \&%w -Number of voluntary context switches (waits). -.It Li \&%X -Average shared text size. -.El -.Pp -The default summary is "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww" -.It Ic verbose -Set by the -.Fl v -command line option, causes the words of each command to be printed -after history substitution. -.El -.Ss Non-builtin command execution -When a command to be executed is found to not be a builtin command -the shell attempts to execute the command via -.Xr execve 2 . -Each word in the variable -.Ar path -names a directory from which the shell will attempt to execute the command. -If it is given neither a -.Fl c -nor a -.Fl t -option, the shell will hash the names in these directories into an internal -table so that it will only try an -.Ic exec -in a directory if there is a possibility that the command resides there. -This shortcut greatly speeds command location when many directories -are present in the search path. -If this mechanism has been turned off (via -.Ic unhash ) , -or if the shell was given a -.Fl c -or -.Fl t -argument, and in any case for each directory component of -.Ar path -that does not begin with a `/', -the shell concatenates with the given command name to form a path name -of a file which it then attempts to execute. -.Pp -Parenthesized commands are always executed in a subshell. -Thus -.Pp -.Dl (cd ; pwd) ; pwd -.Pp -prints the -.Ar home -directory; leaving you where you were (printing this after the home directory), -while -.Pp -.Dl cd ; pwd -.Pp -leaves you in the -.Ar home -directory. -Parenthesized commands are most often used to prevent -.Ic chdir -from affecting the current shell. -.Pp -If the file has execute permissions but is not an -executable binary to the system, then it is assumed to be a -file containing shell commands and a new shell is spawned to read it. -.Pp -If there is an -.Ic alias -for -.Ic shell -then the words of the alias will be prepended to the argument list to form -the shell command. -The first word of the -.Ic alias -should be the full path name of the shell -(e.g., `$shell'). -Note that this is a special, late occurring, case of -.Ic alias -substitution, -and only allows words to be prepended to the argument list without change. -.Ss Signal handling -The shell normally ignores -.Ar quit -signals. -Jobs running detached (either by -.Ic \&\*[Am] -or the -.Ic bg -or -.Ic %... \*[Am] -commands) are immune to signals generated from the keyboard, including -hangups. -Other signals have the values which the shell inherited from its parent. -The shell's handling of interrupts and terminate signals -in shell scripts can be controlled by -.Ic onintr . -Login shells catch the -.Ar terminate -signal; otherwise this signal is passed on to children from the state in the -shell's parent. -Interrupts are not allowed when a login shell is reading the file -.Pa \&.logout . -.Sh FILES -.Bl -tag -width /etc/passwd -compact -.It Pa ~/.cshrc -Read at beginning of execution by each shell. -.It Pa ~/.login -Read by login shell, after `.cshrc' at login. -.It Pa ~/.logout -Read by login shell, at logout. -.It Pa /bin/sh -Standard shell, for shell scripts not starting with a `#'. -.It Pa /tmp/sh* -Temporary file for `\*[Lt]\*[Lt]'. -.It Pa /etc/passwd -Source of home directories for `~name'. -.El -.Sh LIMITATIONS -Word lengths \- -Words can be no longer than 1024 characters. -The system limits argument lists to 10240 characters. -The number of arguments to a command that involves filename expansion -is limited to 1/6'th the number of characters allowed in an argument list. -Command substitutions may substitute no more characters than are -allowed in an argument list. -To detect looping, the shell restricts the number of -.Ic alias -substitutions on a single line to 20. -.Sh SEE ALSO -.Xr sh 1 , -.Xr access 2 , -.Xr execve 2 , -.Xr fork 2 , -.Xr pipe 2 , -.Xr setrlimit 2 , -.Xr sigaction 2 , -.Xr umask 2 , -.Xr wait 2 , -.Xr killpg 3 , -.Xr tty 4 , -.Xr a.out 5 , -.Xr environ 7 , -.Xr sysctl 8 -.Rs -.%T "An introduction to the C shell" -.Re -.Sh HISTORY -.Nm -appeared in -.Bx 2 . -It was a first implementation of a command language interpreter -incorporating a history mechanism (see -.Sx History substitutions ) , -job control facilities (see -.Sx Jobs ) , -interactive file name -and user name completion (see -.Sx File Name Completion ) , -and a C-like syntax. -There are now many shells that also have these mechanisms, plus -a few more (and maybe some bugs too), which are available through the -usenet. -.Sh AUTHORS -William Joy. -Job control and directory stack features first implemented by J.E. Kulp of -IIASA, Laxenburg, Austria, -with different syntax than that used now. -File name completion code written by Ken Greer, HP Labs. -Eight-bit implementation Christos S. Zoulas, Cornell University. -.Sh BUGS -When a command is restarted from a stop, -the shell prints the directory it started in if this is different -from the current directory; this can be misleading (i.e., wrong) -as the job may have changed directories internally. -.Pp -Shell builtin functions are not stoppable/restartable. -Command sequences of the form `a ; b ; c' are also not handled gracefully -when stopping is attempted. -If you suspend `b', the shell will immediately execute `c'. -This is especially noticeable if this expansion results from an -.Ar alias . -It suffices to place the sequence of commands in ()'s to force it to -a subshell, i.e., `( a ; b ; c )'. -.Pp -Control over tty output after processes are started is primitive; -perhaps this will inspire someone to work on a good virtual -terminal interface. -In a virtual terminal interface much more -interesting things could be done with output control. -.Pp -Alias substitution is most often used to clumsily simulate shell procedures; -shell procedures should be provided instead of aliases. -.Pp -Commands within loops, prompted for by `?', are not placed on the -.Ic history -list. -Control structure should be parsed instead of being recognized as built-in -commands. -This would allow control commands to be placed anywhere, -to be combined with `\&|', and to be used with `\*[Am]' and `;' metasyntax. -.Pp -It should be possible to use the `:' modifiers on the output of command -substitutions. -.Pp -The way the -.Ic filec -facility is implemented is ugly and expensive. diff --git a/bin/csh/csh.c b/bin/csh/csh.c deleted file mode 100644 index f03f78a93..000000000 --- a/bin/csh/csh.c +++ /dev/null @@ -1,1401 +0,0 @@ -/* $NetBSD: csh.c,v 1.46 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1980, 1991, 1993\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)csh.c 8.2 (Berkeley) 10/12/93"; -#else -__RCSID("$NetBSD: csh.c,v 1.46 2013/07/16 17:47:43 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include - -#include -#include -#include -#include /* should this be included in pathnames.h instead? */ -#include -#include -#include -#include -#include -#include -#include - -#include "csh.h" -#include "extern.h" -#include "pathnames.h" -#include "proc.h" - -/* - * C Shell - * - * Bill Joy, UC Berkeley, California, USA - * October 1978, May 1980 - * - * Jim Kulp, IIASA, Laxenburg, Austria - * April 1980 - * - * Christos Zoulas, Cornell University - * June, 1991 - */ - -Char *dumphist[] = {STRhistory, STRmh, 0, 0}; -Char *tildehist[] = {STRsource, STRmh, STRtildothist, 0}; - -int nofile = 0; -int batch = 0; -int enterhist = 0; -int fast = 0; -int mflag = 0; -int nexececho = 0; -int nverbose = 0; -int prompt = 1; -int quitit = 0; -int reenter = 0; - -extern char **environ; - -static ssize_t readf(void *, void *, size_t); -static off_t seekf(void *, off_t, int); -static ssize_t writef(void *, const void *, size_t); -static int closef(void *); -static int srccat(Char *, Char *); -static int srcfile(const char *, int, int); -__dead static void phup(int); -static void srcunit(int, int, int); -static void mailchk(void); -#ifndef _PATH_DEFPATH -static Char **defaultpath(void); -#endif -#ifdef EDITING -int editing = 0; -#endif - -int -main(int argc, char *argv[]) -{ - struct sigaction oact; - Char *cp; - char *tcp, **tempv; - const char *ecp; - sigset_t nsigset; - int f; - - cshin = stdin; - cshout = stdout; - csherr = stderr; - - setprogname(argv[0]); - settimes(); /* Immed. estab. timing base */ - - /* - * Initialize non constant strings - */ -#ifdef _PATH_BSHELL - STR_BSHELL = SAVE(_PATH_BSHELL); -#endif -#ifdef _PATH_CSHELL - STR_SHELLPATH = SAVE(_PATH_CSHELL); -#endif - STR_environ = blk2short(environ); - environ = short2blk(STR_environ); /* So that we can free it */ - STR_WORD_CHARS = SAVE(WORD_CHARS); - - HIST = '!'; - HISTSUB = '^'; - word_chars = STR_WORD_CHARS; - - tempv = argv; - if (eq(str2short(tempv[0]), STRaout)) /* A.out's are quittable */ - quitit = 1; - uid = getuid(); - gid = getgid(); - euid = geteuid(); - egid = getegid(); - /* - * We are a login shell if: 1. we were invoked as - and we had - * no arguments 2. or we were invoked only with the -l flag - */ - loginsh = (**tempv == '-' && argc == 1) || - (argc == 2 && tempv[1][0] == '-' && tempv[1][1] == 'l' && - tempv[1][2] == '\0'); - - if (loginsh && **tempv != '-') { - /* - * Mangle the argv space - */ - tempv[1][0] = '\0'; - tempv[1][1] = '\0'; - tempv[1] = NULL; - for (tcp = *tempv; *tcp++;) - continue; - for (tcp--; tcp >= *tempv; tcp--) - tcp[1] = tcp[0]; - *++tcp = '-'; - argc--; - } - if (loginsh) - (void)time(&chktim); - - AsciiOnly = 1; -#ifdef NLS - (void)setlocale(LC_ALL, ""); - { - int k; - - for (k = 0200; k <= 0377 && !Isprint(k); k++) - continue; - AsciiOnly = k > 0377; - } -#else - AsciiOnly = getenv("LANG") == NULL && getenv("LC_CTYPE") == NULL; -#endif /* NLS */ - - /* - * Move the descriptors to safe places. The variable didfds is 0 while we - * have only FSH* to work with. When didfds is true, we have 0,1,2 and - * prefer to use these. - */ - initdesc(); - /* - * XXX: This is to keep programs that use stdio happy. - * what we really want is freunopen() .... - * Closing cshin cshout and csherr (which are really stdin stdout - * and stderr at this point and then reopening them in the same order - * gives us again stdin == cshin stdout == cshout and stderr == csherr. - * If that was not the case builtins like printf that use stdio - * would break. But in any case we could fix that with memcpy and - * a bit of pointer manipulation... - * Fortunately this is not needed under the current implementation - * of stdio. - */ - (void)fclose(cshin); - (void)fclose(cshout); - (void)fclose(csherr); - if (!(cshin = funopen2((void *) &SHIN, readf, writef, seekf, NULL, - closef))) - exit(1); - if (!(cshout = funopen2((void *) &SHOUT, readf, writef, seekf, NULL, - closef))) - exit(1); - if (!(csherr = funopen2((void *) &SHERR, readf, writef, seekf, NULL, - closef))) - exit(1); - (void)setvbuf(cshin, NULL, _IOLBF, 0); - (void)setvbuf(cshout, NULL, _IOLBF, 0); - (void)setvbuf(csherr, NULL, _IOLBF, 0); - - /* - * Initialize the shell variables. ARGV and PROMPT are initialized later. - * STATUS is also munged in several places. CHILD is munged when - * forking/waiting - */ - set(STRstatus, Strsave(STR0)); - - if ((ecp = getenv("HOME")) != NULL) - cp = quote(SAVE(ecp)); - else - cp = NULL; - - if (cp == NULL) - fast = 1; /* No home -> can't read scripts */ - else - set(STRhome, cp); - dinit(cp); /* dinit thinks that HOME == cwd in a login - * shell */ - /* - * Grab other useful things from the environment. Should we grab - * everything?? - */ - if ((ecp = getenv("LOGNAME")) != NULL || - (ecp = getenv("USER")) != NULL) - set(STRuser, quote(SAVE(ecp))); - if ((ecp = getenv("TERM")) != NULL) - set(STRterm, quote(SAVE(ecp))); - - /* - * Re-initialize path if set in environment - */ - if ((ecp = getenv("PATH")) == NULL) { -#ifdef _PATH_DEFPATH - importpath(str2short(_PATH_DEFPATH)); -#else - setq(STRpath, defaultpath(), &shvhed); -#endif - } else { - importpath(str2short(ecp)); - } - - set(STRshell, Strsave(STR_SHELLPATH)); - - doldol = putn((int) getpid()); /* For $$ */ - shtemp = Strspl(STRtmpsh, doldol); /* For << */ - - /* - * Record the interrupt states from the parent process. If the parent is - * non-interruptible our hand must be forced or we (and our children) won't - * be either. Our children inherit termination from our parent. We catch it - * only if we are the login shell. - */ - /* parents interruptibility */ - (void)sigaction(SIGINT, NULL, &oact); - parintr = oact.sa_handler; - (void)sigaction(SIGTERM, NULL, &oact); - parterm = oact.sa_handler; - - /* catch these all, login shell or not */ - (void)signal(SIGHUP, phup); /* exit processing on HUP */ - (void)signal(SIGXCPU, phup); /* ...and on XCPU */ - (void)signal(SIGXFSZ, phup); /* ...and on XFSZ */ - - /* - * Process the arguments. - * - * Note that processing of -v/-x is actually delayed till after script - * processing. - * - * We set the first character of our name to be '-' if we are a shell - * running interruptible commands. Many programs which examine ps'es - * use this to filter such shells out. - */ - argc--, tempv++; - while (argc > 0 && (tcp = tempv[0])[0] == '-' && *++tcp != '\0' && !batch) { - do - switch (*tcp++) { - case 0: /* - Interruptible, no prompt */ - prompt = 0; - setintr = 1; - nofile = 1; - break; - case 'b': /* -b Next arg is input file */ - batch = 1; - break; - case 'c': /* -c Command input from arg */ - if (argc == 1) - xexit(0); - argc--, tempv++; - arginp = SAVE(tempv[0]); - prompt = 0; - nofile = 1; - break; - case 'e': /* -e Exit on any error */ - exiterr = 1; - break; - case 'f': /* -f Fast start */ - fast = 1; - break; - case 'i': /* -i Interactive, even if !intty */ - intact = 1; - nofile = 1; - break; - case 'm': /* -m read .cshrc (from su) */ - mflag = 1; - break; - case 'n': /* -n Don't execute */ - noexec = 1; - break; - case 'q': /* -q (Undoc'd) ... die on quit */ - quitit = 1; - break; - case 's': /* -s Read from std input */ - nofile = 1; - break; - case 't': /* -t Read one line from input */ - onelflg = 2; - prompt = 0; - nofile = 1; - break; - case 'v': /* -v Echo hist expanded input */ - nverbose = 1; /* ... later */ - break; - case 'x': /* -x Echo just before execution */ - nexececho = 1; /* ... later */ - break; - case 'V': /* -V Echo hist expanded input */ - setNS(STRverbose); /* NOW! */ - break; - case 'X': /* -X Echo just before execution */ - setNS(STRecho); /* NOW! */ - break; - - } while (*tcp); - tempv++, argc--; - } - - if (quitit) /* With all due haste, for debugging */ - (void)signal(SIGQUIT, SIG_DFL); - - /* - * Unless prevented by -, -c, -i, -s, or -t, if there are remaining - * arguments the first of them is the name of a shell file from which to - * read commands. - */ - if (nofile == 0 && argc > 0) { - nofile = open(tempv[0], O_RDONLY); - if (nofile < 0) { - child = 1; /* So this doesn't return */ - stderror(ERR_SYSTEM, tempv[0], strerror(errno)); - } - ffile = SAVE(tempv[0]); - /* - * Replace FSHIN. Handle /dev/std{in,out,err} specially - * since once they are closed we cannot open them again. - * In that case we use our own saved descriptors - */ - if ((SHIN = dmove(nofile, FSHIN)) < 0) - switch(nofile) { - case 0: - SHIN = FSHIN; - break; - case 1: - SHIN = FSHOUT; - break; - case 2: - SHIN = FSHERR; - break; - default: - stderror(ERR_SYSTEM, tempv[0], strerror(errno)); - /* NOTREACHED */ - } - (void)ioctl(SHIN, FIOCLEX, NULL); - prompt = 0; - /* argc not used any more */ tempv++; - } - - intty = isatty(SHIN); - intty |= intact; - if (intty || (intact && isatty(SHOUT))) { - if (!batch && (uid != euid || gid != egid)) { - errno = EACCES; - child = 1; /* So this doesn't return */ - stderror(ERR_SYSTEM, "csh", strerror(errno)); - } - } - /* - * Decide whether we should play with signals or not. If we are explicitly - * told (via -i, or -) or we are a login shell (arg0 starts with -) or the - * input and output are both the ttys("csh", or "csh/dev/ttyx") - * Note that in only the login shell is it likely that parent may have set - * signals to be ignored - */ - if (loginsh || intact || (intty && isatty(SHOUT))) - setintr = 1; - settell(); - /* - * Save the remaining arguments in argv. - */ - setq(STRargv, blk2short(tempv), &shvhed); - - /* - * Set up the prompt. - */ - if (prompt) { - set(STRprompt, Strsave(uid == 0 ? STRsymhash : STRsymcent)); - /* that's a meta-questionmark */ - set(STRprompt2, Strsave(STRmquestion)); - } - - /* - * If we are an interactive shell, then start fiddling with the signals; - * this is a tricky game. - */ - shpgrp = getpgrp(); - opgrp = tpgrp = -1; - if (setintr) { - **argv = '-'; - if (!quitit) /* Wary! */ - (void)signal(SIGQUIT, SIG_IGN); - (void)signal(SIGINT, pintr); - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGINT); - (void)sigprocmask(SIG_BLOCK, &nsigset, NULL); - (void)signal(SIGTERM, SIG_IGN); - if (quitit == 0 && arginp == 0) { - (void)signal(SIGTSTP, SIG_IGN); - (void)signal(SIGTTIN, SIG_IGN); - (void)signal(SIGTTOU, SIG_IGN); - /* - * Wait till in foreground, in case someone stupidly runs csh & - * dont want to try to grab away the tty. - */ - if (isatty(FSHERR)) - f = FSHERR; - else if (isatty(FSHOUT)) - f = FSHOUT; - else if (isatty(OLDSTD)) - f = OLDSTD; - else - f = -1; - retry: - if ((tpgrp = tcgetpgrp(f)) != -1) { - if (tpgrp != shpgrp) { - sig_t old = signal(SIGTTIN, SIG_DFL); - (void)kill(0, SIGTTIN); - (void)signal(SIGTTIN, old); - goto retry; - } - opgrp = shpgrp; - shpgrp = getpid(); - tpgrp = shpgrp; - /* - * Setpgid will fail if we are a session leader and - * mypid == mypgrp (POSIX 4.3.3) - */ - if (opgrp != shpgrp) - if (setpgid(0, shpgrp) == -1) - goto notty; - /* - * We do that after we set our process group, to make sure - * that the process group belongs to a process in the same - * session as the tty (our process and our group) (POSIX 7.2.4) - */ - if (tcsetpgrp(f, shpgrp) == -1) - goto notty; - (void)ioctl(dcopy(f, FSHTTY), FIOCLEX, NULL); - } - if (tpgrp == -1) { -notty: -#ifndef __minix /* MINIX3 has no job control. No need to report this. */ - (void)fprintf(csherr, "Warning: no access to tty (%s).\n", - strerror(errno)); - (void)fprintf(csherr, "Thus no job control in this shell.\n"); -#else /* __minix */ - /* nothing */; -#endif /* __minix */ - } - } - } - if ((setintr == 0) && (parintr == SIG_DFL)) - setintr = 1; - (void)signal(SIGCHLD, pchild); /* while signals not ready */ - - /* - * Set an exit here in case of an interrupt or error reading the shell - * start-up scripts. - */ - reenter = setexit(); /* PWP */ - haderr = 0; /* In case second time through */ - if (!fast && reenter == 0) { - /* Will have value(STRhome) here because set fast if don't */ - { - sig_t oparintr; - sigset_t osigset; - int osetintr; - - oparintr = parintr; - osetintr = setintr; - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGINT); - (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); - - setintr = 0; - parintr = SIG_IGN; /* Disable onintr */ -#ifdef _PATH_DOTCSHRC - (void)srcfile(_PATH_DOTCSHRC, 0, 0); -#endif - if (!fast && !arginp && !onelflg) - dohash(NULL, NULL); -#ifdef _PATH_DOTLOGIN - if (loginsh) - (void)srcfile(_PATH_DOTLOGIN, 0, 0); -#endif - (void)sigprocmask(SIG_SETMASK, &osigset, NULL); - setintr = osetintr; - parintr = oparintr; - } - (void)srccat(value(STRhome), STRsldotcshrc); - - if (!fast && !arginp && !onelflg && !havhash) - dohash(NULL, NULL); - /* - * Source history before .login so that it is available in .login - */ - if ((cp = value(STRhistfile)) != STRNULL) - tildehist[2] = cp; - dosource(tildehist, NULL); - if (loginsh) - (void)srccat(value(STRhome), STRsldotlogin); - } - - /* - * Now are ready for the -v and -x flags - */ - if (nverbose) - setNS(STRverbose); - if (nexececho) - setNS(STRecho); - - /* - * All the rest of the world is inside this call. The argument to process - * indicates whether it should catch "error unwinds". Thus if we are a - * interactive shell our call here will never return by being blown past on - * an error. - */ - process(setintr); - - /* - * Mop-up. - */ - if (intty) { - if (loginsh) { - (void)fprintf(cshout, "logout\n"); - (void)close(SHIN); - child = 1; - goodbye(); - } - else { - (void)fprintf(cshout, "exit\n"); - } - } - rechist(); - exitstat(); - /* NOTREACHED */ -} - -void -untty(void) -{ - if (tpgrp > 0) { - (void)setpgid(0, opgrp); - (void)tcsetpgrp(FSHTTY, opgrp); - } -} - -void -importpath(Char *cp) -{ - Char *dp, **pv; - int c, i; - - i = 0; - for (dp = cp; *dp; dp++) - if (*dp == ':') - i++; - /* - * i+2 where i is the number of colons in the path. There are i+1 - * directories in the path plus we need room for a zero terminator. - */ - pv = (Char **)xcalloc((size_t) (i + 2), sizeof(Char **)); - dp = cp; - i = 0; - if (*dp) - for (;;) { - if ((c = *dp) == ':' || c == 0) { - *dp = 0; - pv[i++] = Strsave(*cp ? cp : STRdot); - if (c) { - cp = dp + 1; - *dp = ':'; - } - else - break; - } - dp++; - } - pv[i] = 0; - setq(STRpath, pv, &shvhed); -} - -/* - * Source to the file which is the catenation of the argument names. - */ -static int -srccat(Char *cp, Char *dp) -{ - Char *ep; - char *ptr; - - ep = Strspl(cp, dp); - ptr = short2str(ep); - xfree((ptr_t) ep); - return srcfile(ptr, mflag ? 0 : 1, 0); -} - -/* - * Source to a file putting the file descriptor in a safe place (> 2). - */ -static int -srcfile(const char *f, int onlyown, int flag) -{ - int unit; - - if ((unit = open(f, O_RDONLY)) == -1) - return 0; - unit = dmove(unit, -1); - - (void) ioctl(unit, FIOCLEX, NULL); - srcunit(unit, onlyown, flag); - return 1; -} - -/* - * Source to a unit. If onlyown it must be our file or our group or - * we don't chance it. This occurs on ".cshrc"s and the like. - */ -int insource; - -static void -srcunit(int unit, int onlyown, int hflg) -{ - /* We have to push down a lot of state here */ - /* All this could go into a structure */ - struct whyle *oldwhyl; - struct Bin saveB; - sigset_t nsigset, osigset; - jmp_buf oldexit; - Char *oarginp, *oevalp, **oevalvec, *ogointr; - Char OHIST; - int oSHIN, oinsource, oldintty, oonelflg; - int oenterhist, otell; - /* The (few) real local variables */ - int my_reenter; - - oSHIN = -1; - oldintty = intty; - oinsource = insource; - oldwhyl = whyles; - ogointr = gointr; - oarginp = arginp; - oevalp = evalp; - oevalvec = evalvec; - oonelflg = onelflg; - oenterhist = enterhist; - OHIST = HIST; - otell = cantell; - - if (unit < 0) - return; - if (didfds) - donefds(); - if (onlyown) { - struct stat stb; - - if (fstat(unit, &stb) < 0) { - (void)close(unit); - return; - } - } - - /* - * There is a critical section here while we are pushing down the input - * stream since we have stuff in different structures. If we weren't - * careful an interrupt could corrupt SHIN's Bin structure and kill the - * shell. - * - * We could avoid the critical region by grouping all the stuff in a single - * structure and pointing at it to move it all at once. This is less - * efficient globally on many variable references however. - */ - insource = 1; - getexit(oldexit); - - if (setintr) { - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGINT); - (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); - } - /* Setup the new values of the state stuff saved above */ - (void)memcpy(&saveB, &B, sizeof(B)); - fbuf = NULL; - fseekp = feobp = fblocks = 0; - oSHIN = SHIN, SHIN = unit, arginp = 0, onelflg = 0; - intty = isatty(SHIN), whyles = 0, gointr = 0; - evalvec = 0; - evalp = 0; - enterhist = hflg; - if (enterhist) - HIST = '\0'; - - /* - * Now if we are allowing commands to be interrupted, we let ourselves be - * interrupted. - */ - if (setintr) - (void)sigprocmask(SIG_SETMASK, &osigset, NULL); - settell(); - - if ((my_reenter = setexit()) == 0) - process(0); /* 0 -> blow away on errors */ - - if (setintr) - (void)sigprocmask(SIG_SETMASK, &osigset, NULL); - if (oSHIN >= 0) { - int i; - - /* We made it to the new state... free up its storage */ - /* This code could get run twice but xfree doesn't care */ - for (i = 0; i < fblocks; i++) - xfree((ptr_t) fbuf[i]); - xfree((ptr_t) fbuf); - - /* Reset input arena */ - (void)memcpy(&B, &saveB, sizeof(B)); - - (void)close(SHIN), SHIN = oSHIN; - arginp = oarginp, onelflg = oonelflg; - evalp = oevalp, evalvec = oevalvec; - intty = oldintty, whyles = oldwhyl, gointr = ogointr; - if (enterhist) - HIST = OHIST; - enterhist = oenterhist; - cantell = otell; - } - - resexit(oldexit); - /* - * If process reset() (effectively an unwind) then we must also unwind. - */ - if (my_reenter) - stderror(ERR_SILENT); - insource = oinsource; -} - -void -rechist(void) -{ - Char buf[BUFSIZE], hbuf[BUFSIZE], *hfile; - int fp, ftmp, oldidfds; - struct varent *shist; - - if (!fast) { - /* - * If $savehist is just set, we use the value of $history - * else we use the value in $savehist - */ - if ((shist = adrof(STRsavehist)) != NULL) { - if (shist->vec[0][0] != '\0') - (void)Strcpy(hbuf, shist->vec[0]); - else if ((shist = adrof(STRhistory)) && shist->vec[0][0] != '\0') - (void)Strcpy(hbuf, shist->vec[0]); - else - return; - } - else - return; - - if ((hfile = value(STRhistfile)) == STRNULL) { - hfile = Strcpy(buf, value(STRhome)); - (void) Strcat(buf, STRsldthist); - } - - if ((fp = open(short2str(hfile), O_WRONLY | O_CREAT | O_TRUNC, - 0600)) == -1) - return; - - oldidfds = didfds; - didfds = 0; - ftmp = SHOUT; - SHOUT = fp; - dumphist[2] = hbuf; - dohist(dumphist, NULL); - SHOUT = ftmp; - (void)close(fp); - didfds = oldidfds; - } -} - -void -goodbye(void) -{ - rechist(); - - if (loginsh) { - (void)signal(SIGQUIT, SIG_IGN); - (void)signal(SIGINT, SIG_IGN); - (void)signal(SIGTERM, SIG_IGN); - setintr = 0; /* No interrupts after "logout" */ - if (!(adrof(STRlogout))) - set(STRlogout, STRnormal); -#ifdef _PATH_DOTLOGOUT - (void)srcfile(_PATH_DOTLOGOUT, 0, 0); -#endif - if (adrof(STRhome)) - (void)srccat(value(STRhome), STRsldtlogout); - } - exitstat(); - /* NOTREACHED */ -} - -__dead void -exitstat(void) -{ - Char *s; -#ifdef PROF - monitor(0); -#endif - /* - * Note that if STATUS is corrupted (i.e. getn bombs) then error will exit - * directly because we poke child here. Otherwise we might continue - * unwarrantedly (sic). - */ - child = 1; - s = value(STRstatus); - xexit(s ? getn(s) : 0); - /* NOTREACHED */ -} - -/* - * in the event of a HUP we want to save the history - */ -static void -phup(int sig) -{ - rechist(); - - /* - * We kill the last foreground process group. It then becomes - * responsible to propagate the SIGHUP to its progeny. - */ - { - struct process *pp, *np; - - for (pp = proclist.p_next; pp; pp = pp->p_next) { - np = pp; - /* - * Find if this job is in the foreground. It could be that - * the process leader has exited and the foreground flag - * is cleared for it. - */ - do - /* - * If a process is in the foreground; we try to kill - * its process group. If we succeed, then the - * whole job is gone. Otherwise we keep going... - * But avoid sending HUP to the shell again. - */ - if ((np->p_flags & PFOREGND) != 0 && np->p_jobid != shpgrp && - kill(-np->p_jobid, SIGHUP) != -1) { - /* In case the job was suspended... */ - (void)kill(-np->p_jobid, SIGCONT); - break; - } - while ((np = np->p_friends) != pp); - } - } - xexit(sig); - /* NOTREACHED */ -} - -Char *jobargv[2] = {STRjobs, 0}; - -/* - * Catch an interrupt, e.g. during lexical input. - * If we are an interactive shell, we reset the interrupt catch - * immediately. In any case we drain the shell output, - * and finally go through the normal error mechanism, which - * gets a chance to make the shell go away. - */ -/* ARGSUSED */ -void -pintr(int notused) -{ - pintr1(1); - /* NOTREACHED */ -} - -void -pintr1(int wantnl) -{ - Char **v; - sigset_t nsigset, osigset; - - sigemptyset(&nsigset); - (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); - if (setintr) { - nsigset = osigset; - (void)sigdelset(&nsigset, SIGINT); - (void)sigprocmask(SIG_SETMASK, &nsigset, NULL); - if (pjobs) { - pjobs = 0; - (void)fprintf(cshout, "\n"); - dojobs(jobargv, NULL); - stderror(ERR_NAME | ERR_INTR); - } - } - (void)sigdelset(&osigset, SIGCHLD); - (void)sigprocmask(SIG_SETMASK, &osigset, NULL); - (void)fpurge(cshout); - (void)endpwent(); - - /* - * If we have an active "onintr" then we search for the label. Note that if - * one does "onintr -" then we shan't be interruptible so we needn't worry - * about that here. - */ - if (gointr) { - gotolab(gointr); - timflg = 0; - if ((v = pargv) != NULL) - pargv = 0, blkfree(v); - if ((v = gargv) != NULL) - gargv = 0, blkfree(v); - reset(); - } - else if (intty && wantnl) { - (void)fputc('\r', cshout); - (void)fputc('\n', cshout); - } - stderror(ERR_SILENT); - /* NOTREACHED */ -} - -/* - * Process is the main driving routine for the shell. - * It runs all command processing, except for those within { ... } - * in expressions (which is run by a routine evalav in sh.exp.c which - * is a stripped down process), and `...` evaluation which is run - * also by a subset of this code in sh.glob.c in the routine backeval. - * - * The code here is a little strange because part of it is interruptible - * and hence freeing of structures appears to occur when none is necessary - * if this is ignored. - * - * Note that if catch is not set then we will unwind on any error. - * If an end-of-file occurs, we return. - */ -static struct command *savet = NULL; - -void -process(int catch) -{ - struct command *t; - jmp_buf osetexit; - sigset_t nsigset; - - t = savet; - savet = NULL; - getexit(osetexit); - for (;;) { - pendjob(); - paraml.next = paraml.prev = ¶ml; - paraml.word = STRNULL; - (void)setexit(); - justpr = enterhist; /* execute if not entering history */ - - /* - * Interruptible during interactive reads - */ - if (setintr) { - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGINT); - (void)sigprocmask(SIG_UNBLOCK, &nsigset, NULL); - } - - /* - * For the sake of reset() - */ - freelex(¶ml); - if (savet) - freesyn(savet), savet = NULL; - - if (haderr) { - if (!catch) { - /* unwind */ - doneinp = 0; - resexit(osetexit); - savet = t; - reset(); - } - haderr = 0; - /* - * Every error is eventually caught here or the shell dies. It is - * at this point that we clean up any left-over open files, by - * closing all but a fixed number of pre-defined files. Thus - * routines don't have to worry about leaving files open due to - * deeper errors... they will get closed here. - */ - closem(); - continue; - } - if (doneinp) { - doneinp = 0; - break; - } - if (chkstop) - chkstop--; - if (neednote) - pnote(); - if (intty && prompt && evalvec == 0) { - mailchk(); - /* - * If we are at the end of the input buffer then we are going to - * read fresh stuff. Otherwise, we are rereading input and don't - * need or want to prompt. - */ - if (aret == F_SEEK && fseekp == feobp) - printprompt(); - (void)fflush(cshout); - } - if (seterr) { - xfree((ptr_t) seterr); - seterr = NULL; - } - - /* - * Echo not only on VERBOSE, but also with history expansion. If there - * is a lexical error then we forego history echo. - */ - if ((lex(¶ml) && !seterr && intty) || adrof(STRverbose)) { - int odidfds = didfds; - fflush(csherr); - didfds = 0; - prlex(csherr, ¶ml); - fflush(csherr); - didfds = odidfds; - } - - /* - * The parser may lose space if interrupted. - */ - if (setintr) - (void)sigprocmask(SIG_BLOCK, &nsigset, NULL); - - /* - * Save input text on the history list if reading in old history, or it - * is from the terminal at the top level and not in a loop. - * - * PWP: entry of items in the history list while in a while loop is done - * elsewhere... - */ - if (enterhist || (catch && intty && !whyles)) - savehist(¶ml); - - /* - * Print lexical error messages, except when sourcing history lists. - */ - if (!enterhist && seterr) - stderror(ERR_OLD); - - /* - * If had a history command :p modifier then this is as far as we - * should go - */ - if (justpr) - reset(); - - alias(¶ml); - - /* - * Parse the words of the input into a parse tree. - */ - savet = syntax(paraml.next, ¶ml, 0); - if (seterr) - stderror(ERR_OLD); - - execute(savet, (tpgrp > 0 ? tpgrp : -1), NULL, NULL); - - /* - * Made it! - */ - freelex(¶ml); - freesyn((struct command *) savet), savet = NULL; - } - resexit(osetexit); - savet = t; -} - -void -/*ARGSUSED*/ -dosource(Char **v, struct command *t) -{ - Char buf[BUFSIZE], *f; - int hflg; - - hflg = 0; - v++; - if (*v && eq(*v, STRmh)) { - if (*++v == NULL) - stderror(ERR_NAME | ERR_HFLAG); - hflg++; - } - (void)Strcpy(buf, *v); - f = globone(buf, G_ERROR); - (void)strcpy((char *)buf, short2str(f)); - xfree((ptr_t) f); - if (!srcfile((char *)buf, 0, hflg) && !hflg) - stderror(ERR_SYSTEM, (char *)buf, strerror(errno)); -} - -/* - * Check for mail. - * If we are a login shell, then we don't want to tell - * about any mail file unless its been modified - * after the time we started. - * This prevents us from telling the user things he already - * knows, since the login program insists on saying - * "You have mail." - */ -static void -mailchk(void) -{ - struct stat stb; - struct varent *v; - Char **vp; - time_t t; - int cnt, intvl; - int new; - - v = adrof(STRmail); - if (v == 0) - return; - (void)time(&t); - vp = v->vec; - cnt = blklen(vp); - intvl = (cnt && number(*vp)) ? (--cnt, getn(*vp++)) : MAILINTVL; - if (intvl < 1) - intvl = 1; - if (chktim + intvl > t) - return; - for (; *vp; vp++) { - if (stat(short2str(*vp), &stb) < 0) - continue; - new = stb.st_mtime > time0.tv_sec; - if (stb.st_size == 0 || stb.st_atime > stb.st_mtime || - (stb.st_atime < chktim && stb.st_mtime < chktim) || - (loginsh && !new)) - continue; - if (cnt == 1) - (void)fprintf(cshout, "You have %smail.\n", new ? "new " : ""); - else - (void)fprintf(cshout, "%s in %s.\n", new ? "New mail" : "Mail", - vis_str(*vp)); - } - chktim = t; -} - -/* - * Extract a home directory from the password file - * The argument points to a buffer where the name of the - * user whose home directory is sought is currently. - * We write the home directory of the user back there. - */ -int -gethdir(Char *home) -{ - struct passwd *pw; - Char *h; - - /* - * Is it us? - */ - if (*home == '\0') { - if ((h = value(STRhome)) != NULL) { - (void)Strcpy(home, h); - return 0; - } - else - return 1; - } - - if ((pw = getpwnam(short2str(home))) != NULL) { - (void)Strcpy(home, str2short(pw->pw_dir)); - return 0; - } - else - return 1; -} - -/* - * When didfds is set, we do I/O from 0, 1, 2 otherwise from 15, 16, 17 - * We also check if the shell has already changed the descriptor to point to - * 0, 1, 2 when didfds is set. - */ -#define DESC(a) (*((int *) (a)) - (didfds && *((int *) a) >= FSHIN ? FSHIN : 0)) - -static ssize_t -readf(void *oreo, void *buf, size_t siz) -{ - return read(DESC(oreo), buf, siz); -} - - -static ssize_t -writef(void *oreo, const void *buf, size_t siz) -{ - return write(DESC(oreo), buf, siz); -} - -static off_t -seekf(void *oreo, off_t off, int whence) -{ - return lseek(DESC(oreo), off, whence); -} - - -static int -closef(void *oreo) -{ - return close(DESC(oreo)); -} - - -/* - * Print the visible version of a string. - */ -int -vis_fputc(int ch, FILE *fp) -{ - char uenc[5]; /* 4 + NULL */ - - if (ch & QUOTE) - return fputc(ch & TRIM, fp); - /* - * XXX: When we are in AsciiOnly we want all characters >= 0200 to - * be encoded, but currently there is no way in vis to do that. - */ - (void)vis(uenc, ch & TRIM, VIS_NOSLASH, 0); - return (fputs(uenc, fp)); -} - -/* - * Move the initial descriptors to their eventual - * resting places, closing all other units. - */ -void -initdesc(void) -{ - didfds = 0; /* 0, 1, 2 aren't set up */ - (void)ioctl(SHIN = dcopy(0, FSHIN), FIOCLEX, NULL); - (void)ioctl(SHOUT = dcopy(1, FSHOUT), FIOCLEX, NULL); - (void)ioctl(SHERR = dcopy(2, FSHERR), FIOCLEX, NULL); - (void)ioctl(OLDSTD = dcopy(SHIN, FOLDSTD), FIOCLEX, NULL); - closem(); -} - - -__dead void -#ifdef PROF -done(int i) -#else -xexit(int i) -#endif -{ - untty(); - _exit(i); - /* NOTREACHED */ -} - -#ifndef _PATH_DEFPATH -static Char ** -defaultpath(void) -{ - struct stat stb; - Char **blk, **blkp; - char *ptr; - - blkp = blk = xmalloc((size_t) sizeof(Char *) * 10); - -#define DIRAPPEND(a) \ - if (stat(ptr = a, &stb) == 0 && S_ISDIR(stb.st_mode)) \ - *blkp++ = SAVE(ptr) -#ifdef RESCUEDIR - DIRAPPEND(RESCUEDIR); -#endif - DIRAPPEND(_PATH_BIN); - DIRAPPEND(_PATH_USRBIN); - -#undef DIRAPPEND - -#if 0 - if (euid != 0 && uid != 0) - *blkp++ = Strsave(STRdot); -#endif - - *blkp = NULL; - return (blk); -} -#endif /* _PATH_DEFPATH */ - -void -printprompt(void) -{ - Char *cp; - - if (editing) - return; - - if (!whyles) { - for (cp = value(STRprompt); *cp; cp++) - if (*cp == HIST) - (void)fprintf(cshout, "%d", eventno + 1); - else { - if (*cp == '\\' && cp[1] == HIST) - cp++; - (void)vis_fputc(*cp | QUOTE, cshout); - } - } - else - /* - * Prompt for forward reading loop body content. - */ - (void)fprintf(cshout, "? "); - (void)fflush(cshout); -} - -#ifdef EDIT -char * -printpromptstr(EditLine *elx) { - static char pbuf[1024]; - static char qspace[] = "? "; - Char *cp; - size_t i; - - if (whyles) - return qspace; - - i = 0; - for (cp = value(STRprompt); *cp; cp++) { - if (i >= sizeof(pbuf)) - break; - if (*cp == HIST) { - int r; - r = snprintf(pbuf + i, sizeof(pbuf) - i, "%d", eventno + 1); - if (r > 0) - i += (size_t)r; - } else - pbuf[i++] = (char)*cp; - } - if (i >= sizeof(pbuf)) - i = sizeof(pbuf) - 1; - pbuf[i] = '\0'; - return pbuf; -} -#endif diff --git a/bin/csh/csh.h b/bin/csh/csh.h deleted file mode 100644 index 6a186d7ec..000000000 --- a/bin/csh/csh.h +++ /dev/null @@ -1,559 +0,0 @@ -/* $NetBSD: csh.h,v 1.26 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)csh.h 8.1 (Berkeley) 5/31/93 - */ - -#ifndef _CSH_H_ -#define _CSH_H_ - -/* - * Fundamental definitions which may vary from system to system. - * - * BUFSIZE The i/o buffering size; also limits word size - * MAILINTVL How often to mailcheck; more often is more expensive - */ -#ifndef BUFSIZE -#define BUFSIZE 4096 /* default buffer size */ -#endif /* BUFSIZE */ - -#define FORKSLEEP 10 /* delay loop on non-interactive fork failure */ -#define MAILINTVL 600 /* 10 minutes */ - -/* - * The shell moves std in/out/diag and the old std input away from units - * 0, 1, and 2 so that it is easy to set up these standards for invoked - * commands. - */ -#define FSHTTY 15 /* /dev/tty when manip pgrps */ -#define FSHIN 16 /* Preferred desc for shell input */ -#define FSHOUT 17 /* ... shell output */ -#define FSHERR 18 /* ... shell diagnostics */ -#define FOLDSTD 19 /* ... old std input */ - -#ifdef PROF -#define xexit(n) done(n) -#endif - -#ifdef SHORT_STRINGS -typedef short Char; - -#define SAVE(a) (Strsave(str2short(a))) -#else -typedef char Char; - -#define SAVE(a) (strsave(a)) -#endif - -/* - * Make sure a variable is not stored in a register by taking its address - * This is used where variables might be clobbered by longjmp. - */ -#define UNREGISTER(a) (void) &a - -typedef void *ioctl_t; /* Third arg of ioctl */ - -typedef void *ptr_t; - -#include "const.h" -#include "char.h" -#include "errnum.h" - -#define xmalloc(i) Malloc(i) -#define xrealloc(p, i) Realloc(p, i) -#define xcalloc(n, s) Calloc(n, s) -#define xfree(p) Free(p) - -#include -FILE *cshin, *cshout, *csherr; - -#define isdir(d) (S_ISDIR(d.st_mode)) - -#define eq(a, b) (Strcmp(a, b) == 0) - -/* globone() flags */ -#define G_ERROR 0 /* default action: error if multiple words */ -#define G_IGNORE 1 /* ignore the rest of the words */ -#define G_APPEND 2 /* make a sentence by cat'ing the words */ - -/* - * Global flags - */ -int child; /* Child shell ... errors cause exit */ -int chkstop; /* Warned of stopped jobs... allow exit */ -int didfds; /* Have setup i/o fd's for child */ -int doneinp; /* EOF indicator after reset from readc */ -int exiterr; /* Exit if error or non-zero exit status */ -int haderr; /* Reset was because of an error */ -int havhash; /* path hashing is available */ -int intact; /* We are interactive... therefore prompt */ -int intty; /* Input is a tty */ -int justpr; /* Just print because of :p hist mod */ -int loginsh; /* We are a loginsh -> .login/.logout */ -int neednote; /* Need to pnotify() */ -int noexec; /* Don't execute, just syntax check */ -int pjobs; /* want to print jobs if interrupted */ -int setintr; /* Set interrupts on/off -> Wait intr... */ -int timflg; /* Time the next waited for command */ - -#ifdef FILEC -extern int filec; /* doing filename expansion */ -#endif - -/* - * Global i/o info - */ -Char *arginp; /* Argument input for sh -c and internal `xx` */ -Char *ffile; /* Name of shell file for $0 */ -int onelflg; /* 2 -> need line for -t, 1 -> exit on read */ - -extern char *seterr; /* Error message from scanner/parser */ -Char *shtemp; /* Temp name for << shell files in /tmp */ - -#include -#include -#include - -struct timespec time0; /* Time at which the shell started */ -struct rusage ru0; - -/* - * Miscellany - */ -time_t chktim; /* Time mail last checked */ -Char *doldol; /* Character pid for $$ */ -pid_t backpid; /* Pid of the last background process */ -gid_t egid, gid; /* Invokers gid */ -uid_t euid, uid; /* Invokers uid */ -int shpgrp; /* Pgrp of shell */ -int tpgrp; /* Terminal process group */ - -/* If tpgrp is -1, leave tty alone! */ -int opgrp; /* Initial pgrp and tty pgrp */ - - -/* - * To be able to redirect i/o for builtins easily, the shell moves the i/o - * descriptors it uses away from 0,1,2. - * Ideally these should be in units which are closed across exec's - * (this saves work) but for version 6, this is not usually possible. - * The desired initial values for these descriptors are F{SHIN,...}. - */ -int SHIN; /* Current shell input (script) */ -int SHOUT; /* Shell output */ -int SHERR; /* Diagnostic output... shell errs go here */ -int OLDSTD; /* Old standard input (def for cmds) */ - -/* - * Error control - * - * Errors in scanning and parsing set up an error message to be printed - * at the end and complete. Other errors always cause a reset. - * Because of source commands and .cshrc we need nested error catches. - */ - -#include -jmp_buf reslab; - -#define setexit() (setjmp(reslab)) -#define reset() longjmp(reslab, 1) - /* Should use structure assignment here */ -#define getexit(a) (void)memcpy((a), reslab, sizeof reslab) -#define resexit(a) (void)memcpy(reslab, (a), sizeof reslab) - -Char *gointr; /* Label for an onintr transfer */ - -#include -sig_t parintr; /* Parents interrupt catch */ -sig_t parterm; /* Parents terminate catch */ - -/* - * Lexical definitions. - * - * All lexical space is allocated dynamically. - * The eighth/sixteenth bit of characters is used to prevent recognition, - * and eventually stripped. - */ -#define META 0x80 -#define ASCII 0x7f -#ifdef SHORT_STRINGS -#define CHAR ((Char)0xff) -#define QUOTE ((Char)0x8000) /* 16nth char bit used for 'ing */ -#define TRIM ((Char)0x7fff) /* Mask to strip quote bit */ -#else -#define CHAR ((Char)0x7f) -#define QUOTE ((Char)0x80) /* Eighth char bit used for 'ing */ -#define TRIM ((Char)0x7f) /* Mask to strip quote bit */ -#endif - -int AsciiOnly; /* If set only 7 bits is expected in characters */ - -/* - * Each level of input has a buffered input structure. - * There are one or more blocks of buffered input for each level, - * exactly one if the input is seekable and tell is available. - * In other cases, the shell buffers enough blocks to keep all loops - * in the buffer. - */ -struct Bin { - off_t Bfseekp; /* Seek pointer */ - off_t Bfbobp; /* Seekp of beginning of buffers */ - off_t Bfeobp; /* Seekp of end of buffers */ - int Bfblocks; /* Number of buffer blocks */ - Char **Bfbuf; /* The array of buffer blocks */ -} B; - -/* - * This structure allows us to seek inside aliases - */ -struct Ain { - int type; -#define I_SEEK -1 /* Invalid seek */ -#define A_SEEK 0 /* Alias seek */ -#define F_SEEK 1 /* File seek */ -#define E_SEEK 2 /* Eval seek */ - union { - off_t _f_seek; - Char* _c_seek; - } fc; -#define f_seek fc._f_seek -#define c_seek fc._c_seek - Char **a_seek; -} ; -extern int aret; /* What was the last character returned */ -#define SEEKEQ(a, b) ((a)->type == (b)->type && \ - (a)->f_seek == (b)->f_seek && \ - (a)->a_seek == (b)->a_seek) - -#define fseekp B.Bfseekp -#define fbobp B.Bfbobp -#define feobp B.Bfeobp -#define fblocks B.Bfblocks -#define fbuf B.Bfbuf - -/* - * The shell finds commands in loops by reseeking the input - * For whiles, in particular, it reseeks to the beginning of the - * line the while was on; hence the while placement restrictions. - */ -struct Ain lineloc; - -int cantell; /* Is current source tellable ? */ - -/* - * Input lines are parsed into doubly linked circular - * lists of words of the following form. - */ -struct wordent { - Char *word; - struct wordent *prev; - struct wordent *next; -}; - -/* - * During word building, both in the initial lexical phase and - * when expanding $ variable substitutions, expansion by `!' and `$' - * must be inhibited when reading ahead in routines which are themselves - * processing `!' and `$' expansion or after characters such as `\' or in - * quotations. The following flags are passed to the getC routines - * telling them which of these substitutions are appropriate for the - * next character to be returned. - */ -#define DODOL 1 -#define DOEXCL 2 -#define DOALL DODOL|DOEXCL - -/* - * Labuf implements a general buffer for lookahead during lexical operations. - * Text which is to be placed in the input stream can be stuck here. - * We stick parsed ahead $ constructs during initial input, - * process id's from `$$', and modified variable values (from qualifiers - * during expansion in sh.dol.c) here. - */ -Char *lap; - -/* - * Parser structure - * - * Each command is parsed to a tree of command structures and - * flags are set bottom up during this process, to be propagated down - * as needed during the semantics/execution pass (sh.sem.c). - */ -struct command { - int t_dtyp; /* Type of node */ -#define NODE_COMMAND 1 /* t_dcom t_drit */ -#define NODE_PAREN 2 /* ( t_dspr ) t_drit */ -#define NODE_PIPE 3 /* t_dlef | t_drit */ -#define NODE_LIST 4 /* t_dlef ; t_drit */ -#define NODE_OR 5 /* t_dlef || t_drit */ -#define NODE_AND 6 /* t_dlef && t_drit */ - int t_dflg; /* Flags, e.g. F_AMPERSAND|... */ -#define F_SAVE (F_NICE|F_TIME|F_NOHUP) /* save these when re-doing */ - -#define F_AMPERSAND (1<<0) /* executes in background */ -#define F_APPEND (1<<1) /* output is redirected >> */ -#define F_PIPEIN (1<<2) /* input is a pipe */ -#define F_PIPEOUT (1<<3) /* output is a pipe */ -#define F_NOFORK (1<<4) /* don't fork, last ()ized cmd */ -#define F_NOINTERRUPT (1<<5) /* should be immune from intr's */ -/* spare */ -#define F_STDERR (1<<7) /* redirect unit 2 with unit 1 */ -#define F_OVERWRITE (1<<8) /* output was ! */ -#define F_READ (1<<9) /* input redirection is << */ -#define F_REPEAT (1<<10) /* reexec aft if, repeat,... */ -#define F_NICE (1<<11) /* t_nice is meaningful */ -#define F_NOHUP (1<<12) /* nohup this command */ -#define F_TIME (1<<13) /* time this command */ - union { - Char *T_dlef; /* Input redirect word */ - struct command *T_dcar; /* Left part of list/pipe */ - } L; - union { - Char *T_drit; /* Output redirect word */ - struct command *T_dcdr; /* Right part of list/pipe */ - } R; -#define t_dlef L.T_dlef -#define t_dcar L.T_dcar -#define t_drit R.T_drit -#define t_dcdr R.T_dcdr - Char **t_dcom; /* Command/argument vector */ - struct command *t_dspr; /* Pointer to ()'d subtree */ - int t_nice; -}; - - -/* - * These are declared here because they want to be - * initialized in sh.init.c (to allow them to be made readonly) - */ - -extern struct biltins { - const char *bname; - void (*bfunct)(Char **, struct command *); - short minargs, maxargs; -} bfunc[]; - -extern int nbfunc; -extern int nsrchn; - -extern struct srch { - const char *s_name; - short s_value; -} srchn[]; - -/* - * The keywords for the parser - */ -#define T_BREAK 0 -#define T_BRKSW 1 -#define T_CASE 2 -#define T_DEFAULT 3 -#define T_ELSE 4 -#define T_END 5 -#define T_ENDIF 6 -#define T_ENDSW 7 -#define T_EXIT 8 -#define T_FOREACH 9 -#define T_GOTO 10 -#define T_IF 11 -#define T_LABEL 12 -#define T_LET 13 -#define T_SET 14 -#define T_SWITCH 15 -#define T_TEST 16 -#define T_THEN 17 -#define T_WHILE 18 - -/* - * Structure defining the existing while/foreach loops at this - * source level. Loops are implemented by seeking back in the - * input. For foreach (fe), the word list is attached here. - */ -struct whyle { - struct Ain w_start; /* Point to restart loop */ - struct Ain w_end; /* End of loop (0 if unknown) */ - Char **w_fe, **w_fe0; /* Current/initial wordlist for fe */ - Char *w_fename; /* Name for fe */ - struct whyle *w_next; /* Next (more outer) loop */ -} *whyles; - -/* - * Variable structure - * - * Aliases and variables are stored in AVL balanced binary trees. - */ -struct varent { - Char **vec; /* Array of words which is the value */ - Char *v_name; /* Name of variable/alias */ - struct varent *v_link[3]; /* The links, see below */ - int v_bal; /* Balance factor */ -} shvhed, aliases; - -#define v_left v_link[0] -#define v_right v_link[1] -#define v_parent v_link[2] - -#define adrof(v) adrof1(v, &shvhed) -#define value(v) value1(v, &shvhed) - -/* - * The following are for interfacing redo substitution in - * aliases to the lexical routines. - */ -struct wordent *alhistp; /* Argument list (first) */ -struct wordent *alhistt; /* Node after last in arg list */ -extern Char **alvec, *alvecp; /* The (remnants of) alias vector */ - -/* - * Filename/command name expansion variables - */ -int gflag; /* After tglob -> is globbing needed? */ - -#define MAXVARLEN 30 /* Maximum number of char in a variable name */ - -/* - * Variables for filename expansion - */ -extern long gargc; /* Number args in gargv */ -extern Char **gargv; /* Pointer to the (stack) arglist */ - -/* - * Variables for command expansion. - */ -extern Char **pargv; /* Pointer to the argv list space */ -extern long pargc; /* Count of arguments in pargv */ -long pnleft; /* Number of chars left in pargs */ -Char *pargs; /* Pointer to start current word */ -Char *pargcp; /* Current index into pargs */ - -/* - * History list - * - * Each history list entry contains an embedded wordlist - * from the scanner, a number for the event, and a reference count - * to aid in discarding old entries. - * - * Essentially "invisible" entries are put on the history list - * when history substitution includes modifiers, and thrown away - * at the next discarding since their event numbers are very negative. - */ -struct Hist { - struct wordent Hlex; - int Hnum; - int Href; - struct Hist *Hnext; -} Histlist; - -struct wordent paraml; /* Current lexical word list */ -int eventno; /* Next events number */ -int lastev; /* Last event reference (default) */ - -Char HIST; /* history invocation character */ -Char HISTSUB; /* auto-substitute character */ - -/* - * strings.h: - */ -#ifndef SHORT_STRINGS -#define Strchr(a, b) strchr(a, b) -#define Strrchr(a, b) strrchr(a, b) -#define Strcat(a, b) strcat(a, b) -#define Strncat(a, b, c) strncat(a, b, c) -#define Strcpy(a, b) strcpy(a, b) -#define Strncpy(a, b, c) strncpy(a, b, c) -#define Strlen(a) strlen(a) -#define Strcmp(a, b) strcmp(a, b) -#define Strncmp(a, b, c) strncmp(a, b, c) - -#define Strspl(a, b) strspl(a, b) -#define Strsave(a) strsave(a) -#define Strend(a) strend(a) -#define Strstr(a, b) strstr(a, b) - -#define str2short(a) (a) -#define blk2short(a) saveblk(a) -#define short2blk(a) saveblk(a) -#define short2str(a) strip(a) -#else -#define Strchr(a, b) s_strchr(a, b) -#define Strrchr(a, b) s_strrchr(a, b) -#define Strcat(a, b) s_strcat(a, b) -#define Strncat(a, b, c) s_strncat(a, b, c) -#define Strcpy(a, b) s_strcpy(a, b) -#define Strncpy(a, b, c) s_strncpy(a, b, c) -#define Strlen(a) s_strlen(a) -#define Strcmp(a, b) s_strcmp(a, b) -#define Strncmp(a, b, c) s_strncmp(a, b, c) - -#define Strspl(a, b) s_strspl(a, b) -#define Strsave(a) s_strsave(a) -#define Strend(a) s_strend(a) -#define Strstr(a, b) s_strstr(a, b) -#endif - -/* - * setname is a macro to save space (see sh.err.c) - */ -const char *bname; - -#define setname(a) (bname = (a)) - -Char *Vsav; -Char *Vdp; -Char *Vexpath; -char **Vt; - -Char **evalvec; -Char *evalp; - -/* word_chars is set by default to WORD_CHARS but can be overridden by - the worchars variable--if unset, reverts to WORD_CHARS */ - -Char *word_chars; - -#define WORD_CHARS "*?_-.[]~=" /* default chars besides alnums in words */ - -Char *STR_SHELLPATH; - -#include -#ifdef _PATH_BSHELL -Char *STR_BSHELL; -#endif -Char *STR_WORD_CHARS; -Char **STR_environ; - -#ifdef EDIT -#include -EditLine *el; -History *hi; -#endif -int editing; - -#endif /* !_CSH_H_ */ diff --git a/bin/csh/dir.c b/bin/csh/dir.c deleted file mode 100644 index 418d30236..000000000 --- a/bin/csh/dir.c +++ /dev/null @@ -1,901 +0,0 @@ -/* $NetBSD: dir.c,v 1.30 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)dir.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: dir.c,v 1.30 2013/07/16 17:47:43 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include - -#include -#include -#include -#include -#include - -#include "csh.h" -#include "dir.h" -#include "extern.h" - -/* Directory management. */ - -static struct directory *dfind(Char *); -static Char *dfollow(Char *); -static void printdirs(void); -static Char *dgoto(Char *); -static void skipargs(Char ***, const char *); -static void dnewcwd(struct directory *); -static void dset(Char *); - -struct directory dhead; /* "head" of loop */ -int printd; /* force name to be printed */ - -static int dirflag = 0; - -/* - * dinit - initialize current working directory - */ -void -dinit(Char *hp) -{ - static const char emsg[] = "csh: Trying to start from \"%s\"\n"; - char path[MAXPATHLEN]; - struct directory *dp; - const char *ecp; - Char *cp; - - /* Don't believe the login shell home, because it may be a symlink */ - ecp = getcwd(path, MAXPATHLEN); - if (ecp == NULL || *ecp == '\0') { - (void)fprintf(csherr, "csh: %s\n", strerror(errno)); - if (hp && *hp) { - ecp = short2str(hp); - if (chdir(ecp) == -1) - cp = NULL; - else - cp = Strsave(hp); - (void)fprintf(csherr, emsg, vis_str(hp)); - } - else - cp = NULL; - if (cp == NULL) { - (void)fprintf(csherr, emsg, "/"); - if (chdir("/") == -1) { - /* I am not even try to print an error message! */ - xexit(1); - } - cp = SAVE("/"); - } - } - else { - struct stat swd, shp; - - /* - * See if $HOME is the working directory we got and use that - */ - if (hp && *hp && - stat(ecp, &swd) != -1 && stat(short2str(hp), &shp) != -1 && - swd.st_dev == shp.st_dev && swd.st_ino == shp.st_ino) - cp = Strsave(hp); - else { - const char *cwd; - - /* - * use PWD if we have it (for subshells) - */ - if ((cwd = getenv("PWD")) != NULL) { - if (stat(cwd, &shp) != -1 && swd.st_dev == shp.st_dev && - swd.st_ino == shp.st_ino) - ecp = cwd; - } - cp = dcanon(SAVE(ecp), STRNULL); - } - } - - dp = (struct directory *)xcalloc(1, sizeof(struct directory)); - dp->di_name = cp; - dp->di_count = 0; - dhead.di_next = dhead.di_prev = dp; - dp->di_next = dp->di_prev = &dhead; - printd = 0; - dnewcwd(dp); -} - -static void -dset(Char *dp) -{ - Char **vec; - - /* - * Don't call set() directly cause if the directory contains ` or - * other junk characters glob will fail. - */ - - vec = xmalloc((size_t)(2 * sizeof(Char **))); - vec[0] = Strsave(dp); - vec[1] = 0; - setq(STRcwd, vec, &shvhed); - Setenv(STRPWD, dp); -} - -#define DIR_LONG 1 -#define DIR_VERT 2 -#define DIR_LINE 4 - -static void -skipargs(Char ***v, const char *str) -{ - Char **n, *s; - - n = *v; - dirflag = 0; - for (n++; *n != NULL && (*n)[0] == '-'; n++) - for (s = &((*n)[1]); *s; s++) - switch (*s) { - case 'l': - dirflag |= DIR_LONG; - break; - case 'n': - dirflag |= DIR_LINE; - break; - case 'v': - dirflag |= DIR_VERT; - break; - default: - stderror(ERR_DIRUS, vis_str(**v), str); - /* NOTREACHED */ - } - *v = n; -} - -/* - * dodirs - list all directories in directory loop - */ -void -/*ARGSUSED*/ -dodirs(Char **v, struct command *t) -{ - skipargs(&v, ""); - - if (*v != NULL) - stderror(ERR_DIRUS, "dirs", ""); - printdirs(); -} - -static void -printdirs(void) -{ - struct directory *dp; - Char *hp, *s; - size_t cur, idx, len; - - hp = value(STRhome); - if (*hp == '\0') - hp = NULL; - dp = dcwd; - idx = 0; - cur = 0; - do { - if (dp == &dhead) - continue; - if (dirflag & DIR_VERT) { - (void)fprintf(cshout, "%zu\t", idx++); - cur = 0; - } - if (!(dirflag & DIR_LONG) && hp != NULL && !eq(hp, STRslash) && - (len = Strlen(hp), Strncmp(hp, dp->di_name, len) == 0) && - (dp->di_name[len] == '\0' || dp->di_name[len] == '/')) - len = Strlen(s = (dp->di_name + len)) + 2; - else - len = Strlen(s = dp->di_name) + 1; - - cur += len; - if ((dirflag & DIR_LINE) && cur >= 80 - 1 && len < 80) { - (void)fprintf(cshout, "\n"); - cur = len; - } - (void) fprintf(cshout, "%s%s%c", (s != dp->di_name)? "~" : "", - vis_str(s), (dirflag & DIR_VERT) ? '\n' : ' '); - } while ((dp = dp->di_prev) != dcwd); - if (!(dirflag & DIR_VERT)) - (void)fprintf(cshout, "\n"); -} - -void -dtildepr(Char *home, Char *dir) -{ - if (!eq(home, STRslash) && prefix(home, dir)) - (void)fprintf(cshout, "~%s", vis_str(dir + Strlen(home))); - else - (void)fprintf(cshout, "%s", vis_str(dir)); -} - -void -dtilde(void) -{ - struct directory *d; - - d = dcwd; - do { - if (d == &dhead) - continue; - d->di_name = dcanon(d->di_name, STRNULL); - } while ((d = d->di_prev) != dcwd); - - dset(dcwd->di_name); -} - - -/* dnormalize(): - * If the name starts with . or .. then we might need to normalize - * it depending on the symbolic link flags - */ -Char * -dnormalize(Char *cp) -{ -#define UC (unsigned char) -#define ISDOT(c) (UC(c)[0] == '.' && ((UC(c)[1] == '\0') || (UC(c)[1] == '/'))) -#define ISDOTDOT(c) (UC(c)[0] == '.' && ISDOT(&((c)[1]))) - if ((unsigned char) cp[0] == '/') - return (Strsave(cp)); - - if (adrof(STRignore_symlinks)) { - size_t dotdot = 0; - Char *dp, *cwd; - - cwd = xmalloc((size_t)((Strlen(dcwd->di_name) + 3) * - sizeof(Char))); - (void)Strcpy(cwd, dcwd->di_name); - - /* - * Ignore . and count ..'s - */ - while (*cp) { - if (ISDOT(cp)) { - if (*++cp) - cp++; - } - else if (ISDOTDOT(cp)) { - dotdot++; - cp += 2; - if (*cp) - cp++; - } - else - break; - } - while (dotdot > 0) { - dp = Strrchr(cwd, '/'); - if (dp) { - *dp = '\0'; - dotdot--; - } - else - break; - } - - if (*cp) { - cwd[dotdot = Strlen(cwd)] = '/'; - cwd[dotdot + 1] = '\0'; - dp = Strspl(cwd, cp); - xfree((ptr_t) cwd); - return dp; - } - else { - if (!*cwd) { - cwd[0] = '/'; - cwd[1] = '\0'; - } - return cwd; - } - } - return Strsave(cp); -} - -/* - * dochngd - implement chdir command. - */ -void -/*ARGSUSED*/ -dochngd(Char **v, struct command *t) -{ - struct directory *dp; - Char *cp; - - skipargs(&v, " []"); - printd = 0; - if (*v == NULL) { - if ((cp = value(STRhome)) == NULL || *cp == 0) - stderror(ERR_NAME | ERR_NOHOMEDIR); - if (chdir(short2str(cp)) < 0) - stderror(ERR_NAME | ERR_CANTCHANGE); - cp = Strsave(cp); - } - else if (v[1] != NULL) - stderror(ERR_NAME | ERR_TOOMANY); - else if ((dp = dfind(*v)) != 0) { - char *tmp; - - printd = 1; - if (chdir(tmp = short2str(dp->di_name)) < 0) - stderror(ERR_SYSTEM, tmp, strerror(errno)); - dcwd->di_prev->di_next = dcwd->di_next; - dcwd->di_next->di_prev = dcwd->di_prev; - dfree(dcwd); - dnewcwd(dp); - return; - } - else - cp = dfollow(*v); - dp = (struct directory *)xcalloc(1, sizeof(struct directory)); - dp->di_name = cp; - dp->di_count = 0; - dp->di_next = dcwd->di_next; - dp->di_prev = dcwd->di_prev; - dp->di_prev->di_next = dp; - dp->di_next->di_prev = dp; - dfree(dcwd); - dnewcwd(dp); -} - -static Char * -dgoto(Char *cp) -{ - Char *dp; - - if (*cp != '/') { - Char *p, *q; - size_t cwdlen; - - for (p = dcwd->di_name; *p++;) - continue; - if ((cwdlen = (size_t)(p - dcwd->di_name - 1)) == 1) /* root */ - cwdlen = 0; - for (p = cp; *p++;) - continue; - dp = xmalloc((size_t)(cwdlen + (size_t)(p - cp) + 1) * sizeof(Char)); - for (p = dp, q = dcwd->di_name; (*p++ = *q++) != '\0';) - continue; - if (cwdlen) - p[-1] = '/'; - else - p--; /* don't add a / after root */ - for (q = cp; (*p++ = *q++) != '\0';) - continue; - xfree((ptr_t) cp); - cp = dp; - dp += cwdlen; - } - else - dp = cp; - - cp = dcanon(cp, dp); - return cp; -} - -/* - * dfollow - change to arg directory; fall back on cdpath if not valid - */ -static Char * -dfollow(Char *cp) -{ - char ebuf[MAXPATHLEN]; - struct varent *c; - Char *dp; - int serrno; - - cp = globone(cp, G_ERROR); - /* - * if we are ignoring symlinks, try to fix relatives now. - */ - dp = dnormalize(cp); - if (chdir(short2str(dp)) >= 0) { - xfree((ptr_t) cp); - return dgoto(dp); - } - else { - xfree((ptr_t) dp); - if (chdir(short2str(cp)) >= 0) - return dgoto(cp); - serrno = errno; - } - - if (cp[0] != '/' && !prefix(STRdotsl, cp) && !prefix(STRdotdotsl, cp) - && (c = adrof(STRcdpath))) { - Char **cdp; - Char *p; - Char buf[MAXPATHLEN]; - - for (cdp = c->vec; *cdp; cdp++) { - for (dp = buf, p = *cdp; (*dp++ = *p++) != '\0';) - continue; - dp[-1] = '/'; - for (p = cp; (*dp++ = *p++) != '\0';) - continue; - if (chdir(short2str(buf)) >= 0) { - printd = 1; - xfree((ptr_t) cp); - cp = Strsave(buf); - return dgoto(cp); - } - } - } - dp = value(cp); - if ((dp[0] == '/' || dp[0] == '.') && chdir(short2str(dp)) >= 0) { - xfree((ptr_t) cp); - cp = Strsave(dp); - printd = 1; - return dgoto(cp); - } - (void)strcpy(ebuf, short2str(cp)); - xfree((ptr_t) cp); - stderror(ERR_SYSTEM, ebuf, strerror(serrno)); - /* NOTREACHED */ -} - -/* - * dopushd - push new directory onto directory stack. - * with no arguments exchange top and second. - * with numeric argument (+n) bring it to top. - */ -void -/*ARGSUSED*/ -dopushd(Char **v, struct command *t) -{ - struct directory *dp; - - skipargs(&v, " [|+]"); - printd = 1; - if (*v == NULL) { - char *tmp; - - if ((dp = dcwd->di_prev) == &dhead) - dp = dhead.di_prev; - if (dp == dcwd) - stderror(ERR_NAME | ERR_NODIR); - if (chdir(tmp = short2str(dp->di_name)) < 0) - stderror(ERR_SYSTEM, tmp, strerror(errno)); - dp->di_prev->di_next = dp->di_next; - dp->di_next->di_prev = dp->di_prev; - dp->di_next = dcwd->di_next; - dp->di_prev = dcwd; - dcwd->di_next->di_prev = dp; - dcwd->di_next = dp; - } - else if (v[1] != NULL) - stderror(ERR_NAME | ERR_TOOMANY); - else if ((dp = dfind(*v)) != NULL) { - char *tmp; - - if (chdir(tmp = short2str(dp->di_name)) < 0) - stderror(ERR_SYSTEM, tmp, strerror(errno)); - } - else { - Char *ccp; - - ccp = dfollow(*v); - dp = (struct directory *)xcalloc(1, sizeof(struct directory)); - dp->di_name = ccp; - dp->di_count = 0; - dp->di_prev = dcwd; - dp->di_next = dcwd->di_next; - dcwd->di_next = dp; - dp->di_next->di_prev = dp; - } - dnewcwd(dp); -} - -/* - * dfind - find a directory if specified by numeric (+n) argument - */ -static struct directory * -dfind(Char *cp) -{ - struct directory *dp; - Char *ep; - int i; - - if (*cp++ != '+') - return (0); - for (ep = cp; Isdigit(*ep); ep++) - continue; - if (*ep) - return (0); - i = getn(cp); - if (i <= 0) - return (0); - for (dp = dcwd; i != 0; i--) { - if ((dp = dp->di_prev) == &dhead) - dp = dp->di_prev; - if (dp == dcwd) - stderror(ERR_NAME | ERR_DEEP); - } - return (dp); -} - -/* - * dopopd - pop a directory out of the directory stack - * with a numeric argument just discard it. - */ -void -/*ARGSUSED*/ -dopopd(Char **v, struct command *t) -{ - struct directory *dp, *p = NULL; - - skipargs(&v, " [+]"); - printd = 1; - if (*v == NULL) - dp = dcwd; - else if (v[1] != NULL) - stderror(ERR_NAME | ERR_TOOMANY); - else if ((dp = dfind(*v)) == 0) - stderror(ERR_NAME | ERR_BADDIR); - if (dp->di_prev == &dhead && dp->di_next == &dhead) - stderror(ERR_NAME | ERR_EMPTY); - if (dp == dcwd) { - char *tmp; - - if ((p = dp->di_prev) == &dhead) - p = dhead.di_prev; - if (chdir(tmp = short2str(p->di_name)) < 0) - stderror(ERR_SYSTEM, tmp, strerror(errno)); - } - dp->di_prev->di_next = dp->di_next; - dp->di_next->di_prev = dp->di_prev; - if (dp == dcwd) - dnewcwd(p); - else { - printdirs(); - } - dfree(dp); -} - -/* - * dfree - free the directory (or keep it if it still has ref count) - */ -void -dfree(struct directory *dp) -{ - - if (dp->di_count != 0) { - dp->di_next = dp->di_prev = 0; - } - else { - xfree((char *) dp->di_name); - xfree((ptr_t) dp); - } -} - -/* - * dcanon - canonicalize the pathname, removing excess ./ and ../ etc. - * we are of course assuming that the file system is standardly - * constructed (always have ..'s, directories have links) - */ -Char * -dcanon(Char *cp, Char *p) -{ - Char slink[MAXPATHLEN]; - char tlink[MAXPATHLEN]; - Char *newcp, *sp; - Char *p1, *p2; /* general purpose */ - ssize_t cc; - size_t len; - int slash; - - /* - * christos: if the path given does not start with a slash prepend cwd. If - * cwd does not start with a path or the result would be too long abort(). - */ - if (*cp != '/') { - Char tmpdir[MAXPATHLEN]; - - p1 = value(STRcwd); - if (p1 == NULL || *p1 != '/') - abort(); - if (Strlen(p1) + Strlen(cp) + 1 >= MAXPATHLEN) - abort(); - (void)Strcpy(tmpdir, p1); - (void)Strcat(tmpdir, STRslash); - (void)Strcat(tmpdir, cp); - xfree((ptr_t) cp); - cp = p = Strsave(tmpdir); - } - - while (*p) { /* for each component */ - sp = p; /* save slash address */ - while (*++p == '/') /* flush extra slashes */ - continue; - if (p != ++sp) - for (p1 = sp, p2 = p; (*p1++ = *p2++) != '\0';) - continue; - p = sp; /* save start of component */ - slash = 0; - while (*++p) /* find next slash or end of path */ - if (*p == '/') { - slash = 1; - *p = 0; - break; - } - - if (*sp == '\0') { /* if component is null */ - if (--sp == cp) /* if path is one char (i.e. /) */ - break; - else - *sp = '\0'; - } else if (sp[0] == '.' && sp[1] == 0) { - if (slash) { - for (p1 = sp, p2 = p + 1; (*p1++ = *p2++) != '\0';) - continue; - p = --sp; - } - else if (--sp != cp) - *sp = '\0'; - } - else if (sp[0] == '.' && sp[1] == '.' && sp[2] == 0) { - /* - * We have something like "yyy/xxx/..", where "yyy" can be null or - * a path starting at /, and "xxx" is a single component. Before - * compressing "xxx/..", we want to expand "yyy/xxx", if it is a - * symbolic link. - */ - *--sp = 0; /* form the pathname for readlink */ - if (sp != cp && !adrof(STRignore_symlinks) && - (cc = readlink(short2str(cp), tlink, - sizeof(tlink) - 1)) >= 0) { - tlink[cc] = '\0'; - (void)Strcpy(slink, str2short(tlink)); - - if (slash) - *p = '/'; - /* - * Point p to the '/' in "/..", and restore the '/'. - */ - *(p = sp) = '/'; - /* - * find length of p - */ - for (p1 = p; *p1++;) - continue; - if (*slink != '/') { - /* - * Relative path, expand it between the "yyy/" and the - * "/..". First, back sp up to the character past "yyy/". - */ - while (*--sp != '/') - continue; - sp++; - *sp = 0; - /* - * New length is "yyy/" + slink + "/.." and rest - */ - p1 = newcp = xmalloc( - (size_t)((sp - cp) + cc + (p1 - p)) * sizeof(Char)); - /* - * Copy new path into newcp - */ - for (p2 = cp; (*p1++ = *p2++) != '\0';) - continue; - for (p1--, p2 = slink; (*p1++ = *p2++) != '\0';) - continue; - for (p1--, p2 = p; (*p1++ = *p2++) != '\0';) - continue; - /* - * Restart canonicalization at expanded "/xxx". - */ - p = sp - cp - 1 + newcp; - } - else { - /* - * New length is slink + "/.." and rest - */ - p1 = newcp = xmalloc( - (size_t)(cc + (p1 - p)) * sizeof(Char)); - /* - * Copy new path into newcp - */ - for (p2 = slink; (*p1++ = *p2++) != '\0';) - continue; - for (p1--, p2 = p; (*p1++ = *p2++) != '\0';) - continue; - /* - * Restart canonicalization at beginning - */ - p = newcp; - } - xfree((ptr_t) cp); - cp = newcp; - continue; /* canonicalize the link */ - } - *sp = '/'; - if (sp != cp) - while (*--sp != '/') - continue; - if (slash) { - for (p1 = sp + 1, p2 = p + 1; (*p1++ = *p2++) != '\0';) - continue; - p = sp; - } - else if (cp == sp) - *++sp = '\0'; - else - *sp = '\0'; - } - else { /* normal dir name (not . or .. or nothing) */ - - if (sp != cp && adrof(STRchase_symlinks) && - !adrof(STRignore_symlinks) && - (cc = readlink(short2str(cp), tlink, sizeof(tlink)-1)) >= 0) { - tlink[cc] = '\0'; - (void)Strcpy(slink, str2short(tlink)); - - /* - * restore the '/'. - */ - if (slash) - *p = '/'; - - /* - * point sp to p (rather than backing up). - */ - sp = p; - - /* - * find length of p - */ - for (p1 = p; *p1++;) - continue; - if (*slink != '/') { - /* - * Relative path, expand it between the "yyy/" and the - * remainder. First, back sp up to the character past - * "yyy/". - */ - while (*--sp != '/') - continue; - sp++; - *sp = 0; - /* - * New length is "yyy/" + slink + "/.." and rest - */ - p1 = newcp = xmalloc( - (size_t)((sp - cp) + cc + (p1 - p)) * sizeof(Char)); - /* - * Copy new path into newcp - */ - for (p2 = cp; (*p1++ = *p2++) != '\0';) - continue; - for (p1--, p2 = slink; (*p1++ = *p2++) != '\0';) - continue; - for (p1--, p2 = p; (*p1++ = *p2++) != '\0';) - continue; - /* - * Restart canonicalization at expanded "/xxx". - */ - p = sp - cp - 1 + newcp; - } - else { - /* - * New length is slink + the rest - */ - p1 = newcp = xmalloc( - (size_t)(cc + (p1 - p)) * sizeof(Char)); - /* - * Copy new path into newcp - */ - for (p2 = slink; (*p1++ = *p2++) != '\0';) - continue; - for (p1--, p2 = p; (*p1++ = *p2++) != '\0';) - continue; - /* - * Restart canonicalization at beginning - */ - p = newcp; - } - xfree((ptr_t) cp); - cp = newcp; - continue; /* canonicalize the link */ - } - if (slash) - *p = '/'; - } - } - - /* - * fix home... - */ - p1 = value(STRhome); - len = Strlen(p1); - /* - * See if we're not in a subdir of STRhome - */ - if (p1 && *p1 == '/' && - (Strncmp(p1, cp, len) != 0 || (cp[len] != '/' && cp[len] != '\0'))) { - static ino_t home_ino; - static dev_t home_dev = NODEV; - static Char *home_ptr = NULL; - struct stat statbuf; - - /* - * Get dev and ino of STRhome - */ - if (home_ptr != p1 && - stat(short2str(p1), &statbuf) != -1) { - home_dev = statbuf.st_dev; - home_ino = statbuf.st_ino; - home_ptr = p1; - } - /* - * Start comparing dev & ino backwards - */ - p2 = Strcpy(slink, cp); - for (sp = NULL; *p2 && stat(short2str(p2), &statbuf) != -1;) { - if (statbuf.st_dev == home_dev && - statbuf.st_ino == home_ino) { - sp = (Char *) - 1; - break; - } - if ((sp = Strrchr(p2, '/')) != NULL) - *sp = '\0'; - } - /* - * See if we found it - */ - if (*p2 && sp == (Char *) -1) { - /* - * Use STRhome to make '~' work - */ - newcp = Strspl(p1, cp + Strlen(p2)); - xfree((ptr_t) cp); - cp = newcp; - } - } - return cp; -} - - -/* - * dnewcwd - make a new directory in the loop the current one - */ -static void -dnewcwd(struct directory *dp) -{ - dcwd = dp; - dset(dcwd->di_name); - if (printd && !(adrof(STRpushdsilent))) - printdirs(); -} diff --git a/bin/csh/dir.h b/bin/csh/dir.h deleted file mode 100644 index 16b9babff..000000000 --- a/bin/csh/dir.h +++ /dev/null @@ -1,48 +0,0 @@ -/* $NetBSD: dir.h,v 1.8 2003/08/07 09:05:04 agc Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)dir.h 8.1 (Berkeley) 5/31/93 - */ - -#ifndef _DIR_H_ -#define _DIR_H_ - -/* - * Structure for entries in directory stack. - */ -struct directory { - struct directory *di_next; /* next in loop */ - struct directory *di_prev; /* prev in loop */ - unsigned short *di_count; /* refcount of processes */ - Char *di_name; /* actual name */ -}; -struct directory *dcwd; /* the one we are in now */ - -#endif /* !_DIR_H_ */ diff --git a/bin/csh/dol.c b/bin/csh/dol.c deleted file mode 100644 index 308203ee3..000000000 --- a/bin/csh/dol.c +++ /dev/null @@ -1,968 +0,0 @@ -/* $NetBSD: dol.c,v 1.29 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)dol.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: dol.c,v 1.29 2013/07/16 17:47:43 christos Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "csh.h" -#include "extern.h" - -/* - * These routines perform variable substitution and quoting via ' and ". - * To this point these constructs have been preserved in the divided - * input words. Here we expand variables and turn quoting via ' and " into - * QUOTE bits on characters (which prevent further interpretation). - * If the `:q' modifier was applied during history expansion, then - * some QUOTEing may have occurred already, so we dont "trim()" here. - */ - -static int Dpeekc, Dpeekrd; /* Peeks for DgetC and Dreadc */ -static Char *Dcp, **Dvp; /* Input vector for Dreadc */ - -#define DEOF -1 -#define unDgetC(c) Dpeekc = c -#define QUOTES (_QF|_QB|_ESC) /* \ ' " ` */ - -/* - * The following variables give the information about the current - * $ expansion, recording the current word position, the remaining - * words within this expansion, the count of remaining words, and the - * information about any : modifier which is being applied. - */ -#define MAXWLEN (BUFSIZE - 4) -#define MAXMOD MAXWLEN /* This cannot overflow */ -static Char dolmod[MAXMOD]; /* : modifier character */ -static Char *dolp; /* Remaining chars from this word */ -static Char **dolnxt; /* Further words */ -static int dolcnt; /* Count of further words */ -static int dolnmod; /* Number of modifiers */ -static int dolmcnt; /* :gx -> 10000, else 1 */ -static int dolwcnt; /* :wx -> 10000, else 1 */ - -static void Dfix2(Char **); -static Char *Dpack(Char *, Char *); -static int Dword(void); -__dead static void dolerror(Char *); -static int DgetC(int); -static void Dgetdol(void); -static void fixDolMod(void); -static void setDolp(Char *); -static void unDredc(int); -static int Dredc(void); -static void Dtestq(int); - - -/* - * Fix up the $ expansions and quotations in the - * argument list to command t. - */ -void -Dfix(struct command *t) -{ - Char *p, **pp; - - if (noexec) - return; - /* Note that t_dcom isn't trimmed thus !...:q's aren't lost */ - for (pp = t->t_dcom; (p = *pp++) != NULL;) - for (; *p; p++) { - if (cmap(*p, _DOL | QUOTES)) { /* $, \, ', ", ` */ - Dfix2(t->t_dcom); /* found one */ - blkfree(t->t_dcom); - t->t_dcom = gargv; - gargv = 0; - return; - } - } -} - -/* - * $ substitute one word, for i/o redirection - */ -Char * -Dfix1(Char *cp) -{ - Char *Dv[2]; - - if (noexec) - return (0); - Dv[0] = cp; - Dv[1] = NULL; - Dfix2(Dv); - if (gargc != 1) { - setname(vis_str(cp)); - stderror(ERR_NAME | ERR_AMBIG); - } - cp = Strsave(gargv[0]); - blkfree(gargv), gargv = 0; - return (cp); -} - -/* - * Subroutine to do actual fixing after state initialization. - */ -static void -Dfix2(Char **v) -{ - ginit(); /* Initialize glob's area pointers */ - Dvp = v; - Dcp = STRNULL; /* Setup input vector for Dreadc */ - unDgetC(0); - unDredc(0); /* Clear out any old peeks (at error) */ - dolp = 0; - dolcnt = 0; /* Clear out residual $ expands (...) */ - while (Dword()) - continue; -} - -/* - * Pack up more characters in this word - */ -static Char * -Dpack(Char *wbuf, Char *wp) -{ - int c; - ptrdiff_t i; - - i = MAXWLEN - (wp - wbuf); - for (;;) { - c = DgetC(DODOL); - if (c == '\\') { - c = DgetC(0); - if (c == DEOF) { - unDredc(c); - *wp = 0; - Gcat(STRNULL, wbuf); - return (NULL); - } - if (c == '\n') - c = ' '; - else - c |= QUOTE; - } - if (c == DEOF) { - unDredc(c); - *wp = 0; - Gcat(STRNULL, wbuf); - return (NULL); - } - if (cmap(c, _SP | _NL | _QF | _QB)) { /* sp \t\n'"` */ - unDgetC(c); - if (cmap(c, QUOTES)) - return (wp); - *wp++ = 0; - Gcat(STRNULL, wbuf); - return (NULL); - } - if (--i <= 0) - stderror(ERR_WTOOLONG); - *wp++ = (Char)c; - } -} - -/* - * Get a word. This routine is analogous to the routine - * word() in sh.lex.c for the main lexical input. One difference - * here is that we don't get a newline to terminate our expansion. - * Rather, DgetC will return a DEOF when we hit the end-of-input. - */ -static int -Dword(void) -{ - Char wbuf[BUFSIZE], *wp; - int c, c1; - ptrdiff_t i; - int dolflg, done, sofar; - - done = 0; - i = MAXWLEN; - sofar = 0; - wp = wbuf; - - while (!done) { - done = 1; - c = DgetC(DODOL); - switch (c) { - case DEOF: - if (sofar == 0) - return (0); - /* finish this word and catch the code above the next time */ - unDredc(c); - /* FALLTHROUGH */ - case '\n': - *wp = 0; - Gcat(STRNULL, wbuf); - return (1); - case ' ': - case '\t': - done = 0; - break; - case '`': - /* We preserve ` quotations which are done yet later */ - *wp++ = (Char)c, --i; - /* FALLTHROUGH */ - case '\'': - case '"': - /* - * Note that DgetC never returns a QUOTES character from an - * expansion, so only true input quotes will get us here or out. - */ - c1 = c; - dolflg = c1 == '"' ? DODOL : 0; - for (;;) { - c = DgetC(dolflg); - if (c == c1) - break; - if (c == '\n' || c == DEOF) - stderror(ERR_UNMATCHED, c1); - if ((c & (QUOTE | TRIM)) == ('\n' | QUOTE)) - --wp, ++i; - if (--i <= 0) - stderror(ERR_WTOOLONG); - switch (c1) { - case '"': - /* - * Leave any `s alone for later. Other chars are all - * quoted, thus `...` can tell it was within "...". - */ - *wp++ = (Char)(c == '`' ? '`' : (c | QUOTE)); - break; - case '\'': - /* Prevent all further interpretation */ - *wp++ = (Char)(c | QUOTE); - break; - case '`': - /* Leave all text alone for later */ - *wp++ = (Char)c; - break; - default: - break; - } - } - if (c1 == '`') - *wp++ = '`' /* i--; eliminated */; - sofar = 1; - if ((wp = Dpack(wbuf, wp)) == NULL) - return (1); - else { - i = MAXWLEN - (wp - wbuf); - done = 0; - } - break; - case '\\': - c = DgetC(0); /* No $ subst! */ - if (c == '\n' || c == DEOF) { - done = 0; - break; - } - c |= QUOTE; - break; - default: - break; - } - if (done) { - unDgetC(c); - sofar = 1; - if ((wp = Dpack(wbuf, wp)) == NULL) - return (1); - else { - i = MAXWLEN - (wp - wbuf); - done = 0; - } - } - } - /* Really NOTREACHED */ - return (0); -} - - -/* - * Get a character, performing $ substitution unless flag is 0. - * Any QUOTES character which is returned from a $ expansion is - * QUOTEd so that it will not be recognized above. - */ -static int -DgetC(int flag) -{ - int c; -top: - if ((c = Dpeekc) != '\0') { - Dpeekc = 0; - return (c); - } - if (lap) { - c = *lap++ & (QUOTE | TRIM); - if (c == 0) { - lap = 0; - goto top; - } -quotspec: - if (cmap(c, QUOTES)) - return (c | QUOTE); - return (c); - } - if (dolp) { - if ((c = *dolp++ & (QUOTE | TRIM)) != '\0') - goto quotspec; - if (dolcnt > 0) { - setDolp(*dolnxt++); - --dolcnt; - return (' '); - } - dolp = 0; - } - if (dolcnt > 0) { - setDolp(*dolnxt++); - --dolcnt; - goto top; - } - c = Dredc(); - if (c == '$' && flag) { - Dgetdol(); - goto top; - } - return (c); -} - -static Char *nulvec[] = {0}; -static struct varent nulargv = {nulvec, STRargv, { NULL, NULL, NULL }, 0}; - -static void -dolerror(Char *s) -{ - setname(vis_str(s)); - stderror(ERR_NAME | ERR_RANGE); - /* NOTREACHED */ -} - -/* - * Handle the multitudinous $ expansion forms. - * Ugh. - */ -static void -Dgetdol(void) -{ - static Char *dolbang = NULL; - Char name[4*MAXVARLEN+1]; - Char wbuf[BUFSIZE]; - struct varent *vp; - Char *np; - int c, lwb, sc, subscr, upb; - int dimen, bitset; - char tnp; - - bitset = 0; - dimen = 0; - lwb = 1; - upb = 0; - subscr = 0; - vp = NULL; - - dolnmod = dolmcnt = dolwcnt = 0; - c = sc = DgetC(0); - if (c == '{') - c = DgetC(0); /* sc is { to take } later */ - if ((c & TRIM) == '#') - dimen++, c = DgetC(0); /* $# takes dimension */ - else if (c == '?') - bitset++, c = DgetC(0); /* $? tests existence */ - switch (c) { - case '!': - if (dimen || bitset) - stderror(ERR_SYNTAX); - if (backpid != 0) { - if (dolbang) - xfree((ptr_t)dolbang); - setDolp(dolbang = putn(backpid)); - } - goto eatbrac; - case '$': - if (dimen || bitset) - stderror(ERR_SYNTAX); - setDolp(doldol); - goto eatbrac; - case '<' | QUOTE: - if (bitset) - stderror(ERR_NOTALLOWED, "$?<"); - if (dimen) - stderror(ERR_NOTALLOWED, "$?#"); - for (np = wbuf; read(OLDSTD, &tnp, 1) == 1; np++) { - *np = (unsigned char)tnp; - if (np >= &wbuf[BUFSIZE - 1]) - stderror(ERR_LTOOLONG); - if (tnp == '\n') - break; - } - *np = 0; - /* - * KLUDGE: dolmod is set here because it will cause setDolp to call - * domod and thus to copy wbuf. Otherwise setDolp would use it - * directly. If we saved it ourselves, no one would know when to free - * it. The actual function of the 'q' causes filename expansion not to - * be done on the interpolated value. - */ - dolmod[dolnmod++] = 'q'; - dolmcnt = 10000; - setDolp(wbuf); - goto eatbrac; - case DEOF: - case '\n': - stderror(ERR_SYNTAX); - /* NOTREACHED */ - case '*': - (void) Strcpy(name, STRargv); - vp = adrof(STRargv); - subscr = -1; /* Prevent eating [...] */ - break; - default: - np = name; - if (Isdigit(c)) { - if (dimen) - stderror(ERR_NOTALLOWED, "$#"); - subscr = 0; - do { - subscr = subscr * 10 + c - '0'; - c = DgetC(0); - } while (Isdigit(c)); - unDredc(c); - if (subscr < 0) - stderror(ERR_RANGE); - if (subscr == 0) { - if (bitset) { - dolp = ffile ? STR1 : STR0; - goto eatbrac; - } - if (ffile == 0) - stderror(ERR_DOLZERO); - fixDolMod(); - setDolp(ffile); - goto eatbrac; - } - if (bitset) - stderror(ERR_DOLQUEST); - vp = adrof(STRargv); - if (vp == 0) { - vp = &nulargv; - goto eatmod; - } - break; - } - if (!alnum(c)) - stderror(ERR_VARALNUM); - for (;;) { - *np++ = (Char)c; - c = DgetC(0); - if (!alnum(c)) - break; - if (np >= &name[MAXVARLEN]) - stderror(ERR_VARTOOLONG); - } - *np++ = 0; - unDredc(c); - vp = adrof(name); - } - if (bitset) { - dolp = (vp || getenv(short2str(name))) ? STR1 : STR0; - goto eatbrac; - } - if (vp == 0) { - np = str2short(getenv(short2str(name))); - if (np) { - fixDolMod(); - setDolp(np); - goto eatbrac; - } - udvar(name); - } - c = DgetC(0); - upb = blklen(vp->vec); - if (dimen == 0 && subscr == 0 && c == '[') { - np = name; - for (;;) { - c = DgetC(DODOL); /* Allow $ expand within [ ] */ - if (c == ']') - break; - if (c == '\n' || c == DEOF) - stderror(ERR_INCBR); - if (np >= &name[sizeof(name) / sizeof(Char) - 2]) - stderror(ERR_VARTOOLONG); - *np++ = (Char)c; - } - *np = 0, np = name; - if (dolp || dolcnt) /* $ exp must end before ] */ - stderror(ERR_EXPORD); - if (!*np) - stderror(ERR_SYNTAX); - if (Isdigit(*np)) { - int i; - - for (i = 0; Isdigit(*np); i = i * 10 + *np++ - '0') - continue; - if ((i < 0 || i > upb) && !any("-*", *np)) { - dolerror(vp->v_name); - return; - } - lwb = i; - if (!*np) - upb = lwb, np = STRstar; - } - if (*np == '*') - np++; - else if (*np != '-') - stderror(ERR_MISSING, '-'); - else { - int i = upb; - - np++; - if (Isdigit(*np)) { - i = 0; - while (Isdigit(*np)) - i = i * 10 + *np++ - '0'; - if (i < 0 || i > upb) { - dolerror(vp->v_name); - return; - } - } - if (i < lwb) - upb = lwb - 1; - else - upb = i; - } - if (lwb == 0) { - if (upb != 0) { - dolerror(vp->v_name); - return; - } - upb = -1; - } - if (*np) - stderror(ERR_SYNTAX); - } - else { - if (subscr > 0) { - if (subscr > upb) - lwb = 1, upb = 0; - else - lwb = upb = subscr; - } - unDredc(c); - } - if (dimen) { - Char *cp = putn(upb - lwb + 1); - - addla(cp); - xfree((ptr_t) cp); - } - else { -eatmod: - fixDolMod(); - dolnxt = &vp->vec[lwb - 1]; - dolcnt = upb - lwb + 1; - } -eatbrac: - if (sc == '{') { - c = Dredc(); - if (c != '}') - stderror(ERR_MISSING, '}'); - } -} - -static void -fixDolMod(void) -{ - int c; - - c = DgetC(0); - if (c == ':') { - do { - c = DgetC(0), dolmcnt = 1, dolwcnt = 1; - if (c == 'g' || c == 'a') { - if (c == 'g') - dolmcnt = 10000; - else - dolwcnt = 10000; - c = DgetC(0); - } - if ((c == 'g' && dolmcnt != 10000) || - (c == 'a' && dolwcnt != 10000)) { - if (c == 'g') - dolmcnt = 10000; - else - dolwcnt = 10000; - c = DgetC(0); - } - - if (c == 's') { /* [eichin:19910926.0755EST] */ - int delimcnt = 2; - int delim = DgetC(0); - dolmod[dolnmod++] = (Char)c; - dolmod[dolnmod++] = (Char)delim; - - if (!delim || letter(delim) - || Isdigit(delim) || any(" \t\n", delim)) { - seterror(ERR_BADSUBST); - break; - } - while ((c = DgetC(0)) != (-1)) { - dolmod[dolnmod++] = (Char)c; - if(c == delim) delimcnt--; - if(!delimcnt) break; - } - if(delimcnt) { - seterror(ERR_BADSUBST); - break; - } - continue; - } - if (!any("htrqxes", c)) - stderror(ERR_BADMOD, c); - dolmod[dolnmod++] = (Char)c; - if (c == 'q') - dolmcnt = 10000; - } - while ((c = DgetC(0)) == ':'); - unDredc(c); - } - else - unDredc(c); -} - -static void -setDolp(Char *cp) -{ - Char *dp; - int i; - - if (dolnmod == 0 || dolmcnt == 0) { - dolp = cp; - return; - } - dp = cp = Strsave(cp); - for (i = 0; i < dolnmod; i++) { - /* handle s// [eichin:19910926.0510EST] */ - if(dolmod[i] == 's') { - int delim; - Char *lhsub, *rhsub, *np; - size_t lhlen = 0, rhlen = 0; - int didmod = 0; - - delim = dolmod[++i]; - if (!delim || letter(delim) - || Isdigit(delim) || any(" \t\n", delim)) { - seterror(ERR_BADSUBST); - break; - } - lhsub = &dolmod[++i]; - while(dolmod[i] != delim && dolmod[++i]) { - lhlen++; - } - dolmod[i] = 0; - rhsub = &dolmod[++i]; - while(dolmod[i] != delim && dolmod[++i]) { - rhlen++; - } - dolmod[i] = 0; - - do { - dp = Strstr(cp, lhsub); - if (dp) { - np = xmalloc( - (size_t)((Strlen(cp) + 1 - lhlen + rhlen) * - sizeof(*np))); - (void)Strncpy(np, cp, (size_t)(dp - cp)); - (void)Strcpy(np + (dp - cp), rhsub); - (void)Strcpy(np + (dp - cp) + rhlen, dp + lhlen); - - xfree((ptr_t) cp); - dp = cp = np; - didmod = 1; - } else { - /* should this do a seterror? */ - break; - } - } - while (dolwcnt == 10000); - /* - * restore dolmod for additional words - */ - dolmod[i] = rhsub[-1] = (Char)delim; - if (didmod) - dolmcnt--; - else - break; - } else { - int didmod = 0; - - do { - if ((dp = domod(cp, dolmod[i]))) { - didmod = 1; - if (Strcmp(cp, dp) == 0) { - xfree((ptr_t) cp); - cp = dp; - break; - } - else { - xfree((ptr_t) cp); - cp = dp; - } - } - else - break; - } - while (dolwcnt == 10000); - dp = cp; - if (didmod) - dolmcnt--; - else - break; - } - } - - if (dp) { - addla(dp); - xfree((ptr_t) dp); - } - else { - addla(cp); - xfree((ptr_t) cp); - } - - dolp = STRNULL; - if (seterr) - stderror(ERR_OLD); -} - -static void -unDredc(int c) -{ - Dpeekrd = c; -} - -static int -Dredc(void) -{ - int c; - - if ((c = Dpeekrd) != '\0') { - Dpeekrd = 0; - return (c); - } - if (Dcp && (c = *Dcp++)) - return (c & (QUOTE | TRIM)); - if (*Dvp == 0) { - Dcp = 0; - return (DEOF); - } - Dcp = *Dvp++; - return (' '); -} - -static void -Dtestq(int c) -{ - if (cmap(c, QUOTES)) - gflag = 1; -} - -/* - * Form a shell temporary file (in unit 0) from the words - * of the shell input up to EOF or a line the same as "term". - * Unit 0 should have been closed before this call. - */ -void -/*ARGSUSED*/ -heredoc(Char *term) -{ - Char obuf[BUFSIZE], lbuf[BUFSIZE], mbuf[BUFSIZE]; - struct timespec tv; - Char *Dv[2], *lbp, *obp, *mbp, **vp; - char *tmp; - int c, ocnt, lcnt, mcnt; - int quoted; - -again: - tmp = short2str(shtemp); - if (open(tmp, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, 0600) < 0) { - if (errno == EEXIST) { - if (unlink(tmp) == -1) { - (void)clock_gettime(CLOCK_MONOTONIC, &tv); - mbp = putn((((int)tv.tv_sec) ^ - ((int)tv.tv_nsec) ^ ((int)getpid())) & 0x00ffffff); - shtemp = Strspl(STRtmpsh, mbp); - xfree((ptr_t)mbp); - } - goto again; - } - stderror(ERR_SYSTEM, tmp, strerror(errno)); - } - (void)unlink(tmp); /* 0 0 inode! */ - Dv[0] = term; - Dv[1] = NULL; - gflag = 0; - trim(Dv); - rscan(Dv, Dtestq); - quoted = gflag; - ocnt = BUFSIZE; - obp = obuf; - for (;;) { - /* - * Read up a line - */ - lbp = lbuf; - lcnt = BUFSIZE - 4; - for (;;) { - c = readc(1); /* 1 -> Want EOF returns */ - if (c < 0 || c == '\n') - break; - if ((c &= TRIM) != '\0') { - *lbp++ = (Char)c; - if (--lcnt < 0) { - setname("<<"); - stderror(ERR_NAME | ERR_OVERFLOW); - } - } - } - *lbp = 0; - - /* - * Check for EOF or compare to terminator -- before expansion - */ - if (c < 0 || eq(lbuf, term)) { - (void)write(0, short2str(obuf), (size_t)(BUFSIZE - ocnt)); - (void)lseek(0, (off_t)0, SEEK_SET); - return; - } - - /* - * If term was quoted or -n just pass it on - */ - if (quoted || noexec) { - *lbp++ = '\n'; - *lbp = 0; - for (lbp = lbuf; (c = *lbp++) != '\0';) { - *obp++ = (Char)c; - if (--ocnt == 0) { - (void) write(0, short2str(obuf), BUFSIZE); - obp = obuf; - ocnt = BUFSIZE; - } - } - continue; - } - - /* - * Term wasn't quoted so variable and then command expand the input - * line - */ - Dcp = lbuf; - Dvp = Dv + 1; - mbp = mbuf; - mcnt = BUFSIZE - 4; - for (;;) { - c = DgetC(DODOL); - if (c == DEOF) - break; - if ((c &= TRIM) == 0) - continue; - /* \ quotes \ $ ` here */ - if (c == '\\') { - c = DgetC(0); - if (!any("$\\`", c)) - unDgetC(c | QUOTE), c = '\\'; - else - c |= QUOTE; - } - *mbp++ = (Char)c; - if (--mcnt == 0) { - setname("<<"); - stderror(ERR_NAME | ERR_OVERFLOW); - } - } - *mbp++ = 0; - - /* - * If any ` in line do command substitution - */ - mbp = mbuf; - if (any(short2str(mbp), '`')) { - /* - * 1 arg to dobackp causes substitution to be literal. Words are - * broken only at newlines so that all blanks and tabs are - * preserved. Blank lines (null words) are not discarded. - */ - vp = dobackp(mbuf, 1); - } - else - /* Setup trivial vector similar to return of dobackp */ - Dv[0] = mbp, Dv[1] = NULL, vp = Dv; - - /* - * Resurrect the words from the command substitution each separated by - * a newline. Note that the last newline of a command substitution - * will have been discarded, but we put a newline after the last word - * because this represents the newline after the last input line! - */ - for (; *vp; vp++) { - for (mbp = *vp; *mbp; mbp++) { - *obp++ = *mbp & TRIM; - if (--ocnt == 0) { - (void)write(0, short2str(obuf), BUFSIZE); - obp = obuf; - ocnt = BUFSIZE; - } - } - *obp++ = '\n'; - if (--ocnt == 0) { - (void)write(0, short2str(obuf), BUFSIZE); - obp = obuf; - ocnt = BUFSIZE; - } - } - if (pargv) - blkfree(pargv), pargv = 0; - } -} diff --git a/bin/csh/err.c b/bin/csh/err.c deleted file mode 100644 index 030aaf724..000000000 --- a/bin/csh/err.c +++ /dev/null @@ -1,388 +0,0 @@ -/* $NetBSD: err.c,v 1.21 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: err.c,v 1.21 2013/07/16 17:47:43 christos Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include -#include - -#include "csh.h" -#include "extern.h" - -char *seterr = NULL; /* Holds last error if there was one */ - -#define ERR_FLAGS ((int)0xf0000000) -#define ERR_NAME 0x10000000 -#define ERR_SILENT 0x20000000 -#define ERR_OLD 0x40000000 - -static const char *errorlist[] = -{ -#define ERR_SYNTAX 0 - "Syntax Error", -#define ERR_NOTALLOWED 1 - "%s is not allowed", -#define ERR_WTOOLONG 2 - "Word too long", -#define ERR_LTOOLONG 3 - "$< line too long", -#define ERR_DOLZERO 4 - "No file for $0", -#define ERR_DOLQUEST 5 - "$? not allowed here", -#define ERR_INCBR 6 - "Incomplete [] modifier", -#define ERR_EXPORD 7 - "$ expansion must end before ]", -#define ERR_BADMOD 8 - "Bad : modifier in $ (%c)", -#define ERR_SUBSCRIPT 9 - "Subscript error", -#define ERR_BADNUM 10 - "Badly formed number", -#define ERR_NOMORE 11 - "No more words", -#define ERR_FILENAME 12 - "Missing file name", -#define ERR_GLOB 13 - "Internal glob error", -#define ERR_COMMAND 14 - "Command not found", -#define ERR_TOOFEW 15 - "Too few arguments", -#define ERR_TOOMANY 16 - "Too many arguments", -#define ERR_DANGER 17 - "Too dangerous to alias that", -#define ERR_EMPTYIF 18 - "Empty if", -#define ERR_IMPRTHEN 19 - "Improper then", -#define ERR_NOPAREN 20 - "Words not parenthesized", -#define ERR_NOTFOUND 21 - "%s not found", -#define ERR_MASK 22 - "Improper mask", -#define ERR_LIMIT 23 - "No such limit", -#define ERR_TOOLARGE 24 - "Argument too large", -#define ERR_SCALEF 25 - "Improper or unknown scale factor", -#define ERR_UNDVAR 26 - "Undefined variable", -#define ERR_DEEP 27 - "Directory stack not that deep", -#define ERR_BADSIG 28 - "Bad signal number", -#define ERR_UNKSIG 29 - "Unknown signal; kill -l lists signals", -#define ERR_VARBEGIN 30 - "Variable name must begin with a letter", -#define ERR_VARTOOLONG 31 - "Variable name too long", -#define ERR_VARALNUM 32 - "Variable name must contain alphanumeric characters", -#define ERR_JOBCONTROL 33 - "No job control in this shell", -#define ERR_EXPRESSION 34 - "Expression Syntax", -#define ERR_NOHOMEDIR 35 - "No home directory", -#define ERR_CANTCHANGE 36 - "Can't change to home directory", -#define ERR_NULLCOM 37 - "Invalid null command", -#define ERR_ASSIGN 38 - "Assignment missing expression", -#define ERR_UNKNOWNOP 39 - "Unknown operator", -#define ERR_AMBIG 40 - "Ambiguous", -#define ERR_EXISTS 41 - "%s: File exists", -#define ERR_INTR 42 - "Interrupted", -#define ERR_RANGE 43 - "Subscript out of range", -#define ERR_OVERFLOW 44 - "Line overflow", -#define ERR_VARMOD 45 - "Unknown variable modifier", -#define ERR_NOSUCHJOB 46 - "No such job", -#define ERR_TERMINAL 47 - "Can't from terminal", -#define ERR_NOTWHILE 48 - "Not in while/foreach", -#define ERR_NOPROC 49 - "No more processes", -#define ERR_NOMATCH 50 - "No match", -#define ERR_MISSING 51 - "Missing %c", -#define ERR_UNMATCHED 52 - "Unmatched %c", -#define ERR_NOMEM 53 - "Out of memory", -#define ERR_PIPE 54 - "Can't make pipe", -#define ERR_SYSTEM 55 - "%s: %s", -#define ERR_STRING 56 - "%s", -#define ERR_JOBS 57 - "usage: jobs [ -l ]", -#define ERR_JOBARGS 58 - "Arguments should be jobs or process id's", -#define ERR_JOBCUR 59 - "No current job", -#define ERR_JOBPREV 60 - "No previous job", -#define ERR_JOBPAT 61 - "No job matches pattern", -#define ERR_NESTING 62 - "Fork nesting > %d; maybe `...` loop", -#define ERR_JOBCTRLSUB 63 - "No job control in subshells", -#define ERR_BADPLPS 64 - "Badly placed ()'s", -#define ERR_STOPPED 65 - "%sThere are suspended jobs", -#define ERR_NODIR 66 - "No other directory", -#define ERR_EMPTY 67 - "Directory stack empty", -#define ERR_BADDIR 68 - "Bad directory", -#define ERR_DIRUS 69 - "usage: %s [-lvn]%s", -#define ERR_HFLAG 70 - "No operand for -h flag", -#define ERR_NOTLOGIN 71 - "Not a login shell", -#define ERR_DIV0 72 - "Division by 0", -#define ERR_MOD0 73 - "Mod by 0", -#define ERR_BADSCALE 74 - "Bad scaling; did you mean \"%s\"?", -#define ERR_SUSPLOG 75 - "Can't suspend a login shell (yet)", -#define ERR_UNKUSER 76 - "Unknown user: %s", -#define ERR_NOHOME 77 - "No $home variable set", -#define ERR_HISTUS 78 - "usage: history [-rh] [# number of events]", -#define ERR_SPDOLLT 79 - "$, ! or < not allowed with $# or $?", -#define ERR_NEWLINE 80 - "Newline in variable name", -#define ERR_SPSTAR 81 - "* not allowed with $# or $?", -#define ERR_DIGIT 82 - "$? or $# not allowed", -#define ERR_VARILL 83 - "Illegal variable name", -#define ERR_NLINDEX 84 - "Newline in variable index", -#define ERR_EXPOVFL 85 - "Expansion buffer overflow", -#define ERR_VARSYN 86 - "Variable syntax", -#define ERR_BADBANG 87 - "Bad ! form", -#define ERR_NOSUBST 88 - "No previous substitute", -#define ERR_BADSUBST 89 - "Bad substitute", -#define ERR_LHS 90 - "No previous left hand side", -#define ERR_RHSLONG 91 - "Right hand side too long", -#define ERR_BADBANGMOD 92 - "Bad ! modifier: %c", -#define ERR_MODFAIL 93 - "Modifier failed", -#define ERR_SUBOVFL 94 - "Substitution buffer overflow", -#define ERR_BADBANGARG 95 - "Bad ! arg selector", -#define ERR_NOSEARCH 96 - "No prev search", -#define ERR_NOEVENT 97 - "%s: Event not found", -#define ERR_TOOMANYRP 98 - "Too many )'s", -#define ERR_TOOMANYLP 99 - "Too many ('s", -#define ERR_BADPLP 100 - "Badly placed (", -#define ERR_MISRED 101 - "Missing name for redirect", -#define ERR_OUTRED 102 - "Ambiguous output redirect", -#define ERR_REDPAR 103 - "Can't << within ()'s", -#define ERR_INRED 104 - "Ambiguous input redirect", -#define ERR_ALIASLOOP 105 - "Alias loop", -#define ERR_HISTLOOP 106 - "!# History loop", -#define ERR_ARCH 107 - "%s: %s. Wrong Architecture", -#define ERR_FILEINQ 108 - "Malformed file inquiry", -#define ERR_SELOVFL 109 - "Selector overflow", -#define ERR_INVALID 110 - "Invalid Error" -}; - -/* - * The parser and scanner set up errors for later by calling seterr, - * which sets the variable err as a side effect; later to be tested, - * e.g. in process. - */ -void -seterror(int id, ...) -{ - if (seterr == 0) { - char berr[BUFSIZE]; - va_list va; - - va_start(va, id); - if (id < 0 || id >= (int)(sizeof(errorlist) / sizeof(errorlist[0])) - 1) - id = ERR_INVALID; - (void)vsnprintf(berr, sizeof(berr), errorlist[id], va); - va_end(va); - - seterr = strsave(berr); - } -} - -/* - * Print the error with the given id. - * - * Special ids: - * ERR_SILENT: Print nothing. - * ERR_OLD: Print the previously set error if one was there. - * otherwise return. - * ERR_NAME: If this bit is set, print the name of the function - * in bname - * - * This routine always resets or exits. The flag haderr - * is set so the routine who catches the unwind can propogate - * it if they want. - * - * Note that any open files at the point of error will eventually - * be closed in the routine process in sh.c which is the only - * place error unwinds are ever caught. - */ -void -stderror(int id, ...) -{ - va_list va; - Char **v; - int flags; - - flags = id & ERR_FLAGS; - id &= ~ERR_FLAGS; - - if ((flags & ERR_OLD) && seterr == NULL) - abort(); - - if (id < 0 || id > (int)(sizeof(errorlist) / sizeof(errorlist[0]))) - id = ERR_INVALID; - - (void)fflush(cshout); - (void)fflush(csherr); - haderr = 1; /* Now to diagnostic output */ - timflg = 0; /* This isn't otherwise reset */ - - - if (!(flags & ERR_SILENT)) { - if (flags & ERR_NAME) - (void)fprintf(csherr, "%s: ", bname); - if ((flags & ERR_OLD)) - /* Old error. */ - (void)fprintf(csherr, "%s.\n", seterr); - else { - va_start(va, id); - (void)vfprintf(csherr, errorlist[id], va); - va_end(va); - (void)fprintf(csherr, ".\n"); - } - } - - if (seterr) { - xfree((ptr_t) seterr); - seterr = NULL; - } - - if ((v = pargv) != NULL) - pargv = 0, blkfree(v); - if ((v = gargv) != NULL) - gargv = 0, blkfree(v); - - (void)fflush(cshout); - (void)fflush(csherr); - didfds = 0; /* Forget about 0,1,2 */ - /* - * Go away if -e or we are a child shell - */ - if (exiterr || child) - xexit(1); - - /* - * Reset the state of the input. This buffered seek to end of file will - * also clear the while/foreach stack. - */ - btoeof(); - - set(STRstatus, Strsave(STR1)); - if (tpgrp > 0) - (void)tcsetpgrp(FSHTTY, tpgrp); - reset(); /* Unwind */ -} diff --git a/bin/csh/exec.c b/bin/csh/exec.c deleted file mode 100644 index bd2b343b4..000000000 --- a/bin/csh/exec.c +++ /dev/null @@ -1,746 +0,0 @@ -/* $NetBSD: exec.c,v 1.29 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)exec.c 8.3 (Berkeley) 5/23/95"; -#else -__RCSID("$NetBSD: exec.c,v 1.29 2013/07/16 17:47:43 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "csh.h" -#include "extern.h" - -/* - * System level search and execute of a command. We look in each directory - * for the specified command name. If the name contains a '/' then we - * execute only the full path name. If there is no search path then we - * execute only full path names. - */ -extern char **environ; - -/* - * As we search for the command we note the first non-trivial error - * message for presentation to the user. This allows us often - * to show that a file has the wrong mode/no access when the file - * is not in the last component of the search path, so we must - * go on after first detecting the error. - */ -static const char *exerr; /* Execution error message */ -static Char *expath; /* Path for exerr */ - -/* - * Xhash is an array of HSHSIZ bits (HSHSIZ / 8 chars), which are used - * to hash execs. If it is allocated (havhash true), then to tell - * whether ``name'' is (possibly) present in the i'th component - * of the variable path, you look at the bit in xhash indexed by - * hash(hashname("name"), i). This is setup automatically - * after .login is executed, and recomputed whenever ``path'' is - * changed. - * The two part hash function is designed to let texec() call the - * more expensive hashname() only once and the simple hash() several - * times (once for each path component checked). - * Byte size is assumed to be 8. - */ -#define HSHSIZ 8192 /* 1k bytes */ -#define HSHMASK (HSHSIZ - 1) -#define HSHMUL 243 -static unsigned char xhash[HSHSIZ / 8]; - -#define hash(a, b) (((a) * HSHMUL + (b)) & HSHMASK) -#define bit(h, b) ((h)[(b) >> 3] & 1 << ((b) & 7)) /* bit test */ -#define bis(h, b) ((h)[(b) >> 3] |= (unsigned char)(1 << ((b) & 7))) /* bit set */ -static int hits, misses; - -/* Dummy search path for just absolute search when no path */ -static Char *justabs[] = {STRNULL, 0}; - -static void pexerr(void) __dead; -static void texec(Char *, Char **); -static int hashname(Char *); -static int tellmewhat(struct wordent *, Char *); -static int executable(Char *, Char *, int); -static int iscommand(Char *); - -void -/*ARGSUSED*/ -doexec(Char **v, struct command *t) -{ - struct varent *pathv; - Char *blk[2], **av, *dp, **pv, *sav; - int i, hashval, hashval1; - sigset_t nsigset; - int slash; - - hashval = 0; - /* - * Glob the command name. We will search $path even if this does something, - * as in sh but not in csh. One special case: if there is no PATH, then we - * execute only commands which start with '/'. - */ - blk[0] = t->t_dcom[0]; - blk[1] = 0; - gflag = 0, tglob(blk); - if (gflag) { - pv = globall(blk); - if (pv == 0) { - setname(vis_str(blk[0])); - stderror(ERR_NAME | ERR_NOMATCH); - } - gargv = 0; - } - else - pv = saveblk(blk); - - trim(pv); - - exerr = 0; - expath = Strsave(pv[0]); - Vexpath = expath; - - pathv = adrof(STRpath); - if (pathv == 0 && expath[0] != '/') { - blkfree(pv); - pexerr(); - } - slash = any(short2str(expath), '/'); - - /* - * Glob the argument list, if necessary. Otherwise trim off the quote bits. - */ - gflag = 0; - av = &t->t_dcom[1]; - tglob(av); - if (gflag) { - av = globall(av); - if (av == 0) { - blkfree(pv); - setname(vis_str(expath)); - stderror(ERR_NAME | ERR_NOMATCH); - } - gargv = 0; - } - else - av = saveblk(av); - - blkfree(t->t_dcom); - t->t_dcom = blkspl(pv, av); - xfree((ptr_t) pv); - xfree((ptr_t) av); - av = t->t_dcom; - trim(av); - - if (*av == NULL || **av == '\0') - pexerr(); - - xechoit(av); /* Echo command if -x */ - /* - * Since all internal file descriptors are set to close on exec, we don't - * need to close them explicitly here. Just reorient ourselves for error - * messages. - */ - SHIN = 0; - SHOUT = 1; - SHERR = 2; - OLDSTD = 0; - /* - * We must do this AFTER any possible forking (like `foo` in glob) so that - * this shell can still do subprocesses. - */ - sigemptyset(&nsigset); - (void)sigprocmask(SIG_SETMASK, &nsigset, NULL); - /* - * If no path, no words in path, or a / in the filename then restrict the - * command search. - */ - if (pathv == 0 || pathv->vec[0] == 0 || slash) - pv = justabs; - else - pv = pathv->vec; - sav = Strspl(STRslash, *av); /* / command name for postpending */ - Vsav = sav; - if (havhash) - hashval = hashname(*av); - i = 0; - hits++; - do { - /* - * Try to save time by looking at the hash table for where this command - * could be. If we are doing delayed hashing, then we put the names in - * one at a time, as the user enters them. This is kinda like Korn - * Shell's "tracked aliases". - */ - if (!slash && pv[0][0] == '/' && havhash) { - hashval1 = hash(hashval, i); - if (!bit(xhash, hashval1)) - goto cont; - } - if (pv[0][0] == 0 || eq(pv[0], STRdot)) /* don't make ./xxx */ - texec(*av, av); - else { - dp = Strspl(*pv, sav); - Vdp = dp; - texec(dp, av); - Vdp = 0; - xfree((ptr_t)dp); - } - misses++; -cont: - pv++; - i++; - } while (*pv); - hits--; - Vsav = 0; - xfree((ptr_t)sav); - pexerr(); - /* NOTREACHED */ -} - -static void -pexerr(void) -{ - /* Couldn't find the damn thing */ - if (expath) { - setname(vis_str(expath)); - Vexpath = 0; - xfree((ptr_t)expath); - expath = 0; - } - else - setname(""); - if (exerr) - stderror(ERR_NAME | ERR_STRING, exerr); - else - stderror(ERR_NAME | ERR_COMMAND); - /* NOTREACHED */ -} - -/* - * Execute command f, arg list t. - * Record error message if not found. - * Also do shell scripts here. - */ -static void -texec(Char *sf, Char **st) -{ - struct varent *v; - Char *lastsh[2], **vp, *st0, **ost; - char *f, **t; - int fd; - unsigned char c = '\0'; - - /* The order for the conversions is significant */ - t = short2blk(st); - f = short2str(sf); - Vt = t; - errno = 0; /* don't use a previous error */ - (void)execve(f, t, environ); - Vt = 0; - blkfree((Char **)t); - switch (errno) { - - case ENOEXEC: - /* - * From: casper@fwi.uva.nl (Casper H.S. Dik) If we could not execute - * it, don't feed it to the shell if it looks like a binary! - */ - if ((fd = open(f, O_RDONLY)) != -1) { - if (read(fd, (char *)&c, 1) == 1) { - if (!Isprint(c) && (c != '\n' && c != '\t')) { - (void)close(fd); - /* - * We *know* what ENOEXEC means. - */ - stderror(ERR_ARCH, f, strerror(errno)); - } - } -#ifdef _PATH_BSHELL - else - c = '#'; -#endif - (void)close(fd); - } - /* - * If there is an alias for shell, then put the words of the alias in - * front of the argument list replacing the command name. Note no - * interpretation of the words at this point. - */ - v = adrof1(STRshell, &aliases); - if (v == 0) { - vp = lastsh; - vp[0] = adrof(STRshell) ? value(STRshell) : STR_SHELLPATH; - vp[1] = NULL; -#ifdef _PATH_BSHELL - if (fd != -1 && c != '#') - vp[0] = STR_BSHELL; -#endif - } - else - vp = v->vec; - st0 = st[0]; - st[0] = sf; - ost = st; - st = blkspl(vp, st); /* Splice up the new arglst */ - ost[0] = st0; - sf = *st; - /* The order for the conversions is significant */ - t = short2blk(st); - f = short2str(sf); - xfree((ptr_t) st); - Vt = t; - (void)execve(f, t, environ); - Vt = 0; - blkfree((Char **) t); - /* FALLTHROUGH */ - - case ENOMEM: - stderror(ERR_SYSTEM, f, strerror(errno)); - /* NOTREACHED */ - - case ENOENT: - break; - - default: - if (exerr == 0) { - exerr = strerror(errno); - if (expath) - xfree((ptr_t) expath); - expath = Strsave(sf); - Vexpath = expath; - } - } -} - -/*ARGSUSED*/ -void -execash(Char **t, struct command *kp) -{ - jmp_buf osetexit; - sig_t osigint, osigquit, osigterm; - int my_reenter, odidfds, oOLDSTD, oSHERR, oSHIN, oSHOUT; - int saveDIAG, saveIN, saveOUT, saveSTD; - - if (chkstop == 0 && setintr) - panystop(0); - /* - * Hmm, we don't really want to do that now because we might - * fail, but what is the choice - */ - rechist(); - - osigint = signal(SIGINT, parintr); - osigquit = signal(SIGQUIT, parintr); - osigterm = signal(SIGTERM, parterm); - - odidfds = didfds; - oSHIN = SHIN; - oSHOUT = SHOUT; - oSHERR = SHERR; - oOLDSTD = OLDSTD; - - saveIN = dcopy(SHIN, -1); - saveOUT = dcopy(SHOUT, -1); - saveDIAG = dcopy(SHERR, -1); - saveSTD = dcopy(OLDSTD, -1); - - lshift(kp->t_dcom, 1); - - getexit(osetexit); - - if ((my_reenter = setexit()) == 0) { - SHIN = dcopy(0, -1); - SHOUT = dcopy(1, -1); - SHERR = dcopy(2, -1); - didfds = 0; - doexec(t, kp); - } - - (void)signal(SIGINT, osigint); - (void)signal(SIGQUIT, osigquit); - (void)signal(SIGTERM, osigterm); - - doneinp = 0; - didfds = odidfds; - (void)close(SHIN); - (void)close(SHOUT); - (void)close(SHERR); - (void)close(OLDSTD); - SHIN = dmove(saveIN, oSHIN); - SHOUT = dmove(saveOUT, oSHOUT); - SHERR = dmove(saveDIAG, oSHERR); - OLDSTD = dmove(saveSTD, oOLDSTD); - - resexit(osetexit); - if (my_reenter) - stderror(ERR_SILENT); -} - -void -xechoit(Char **t) -{ - if (adrof(STRecho)) { - int odidfds = didfds; - (void)fflush(csherr); - odidfds = didfds; - didfds = 0; - blkpr(csherr, t); - (void)fputc('\n', csherr); - (void)fflush(csherr); - didfds = odidfds; - } -} - -void -/*ARGSUSED*/ -dohash(Char **v, struct command *t) -{ - struct dirent *dp; - struct varent *pathv; - DIR *dirp; - Char **pv; - size_t cnt; - int hashval, i; - - i = 0; - havhash = 1; - pathv = adrof(STRpath); - - for (cnt = 0; cnt < sizeof xhash; cnt++) - xhash[cnt] = 0; - if (pathv == 0) - return; - for (pv = pathv->vec; *pv; pv++, i++) { - if (pv[0][0] != '/') - continue; - dirp = opendir(short2str(*pv)); - if (dirp == NULL) - continue; - while ((dp = readdir(dirp)) != NULL) { - if (dp->d_ino == 0) - continue; - if (dp->d_name[0] == '.' && - (dp->d_name[1] == '\0' || - (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) - continue; - hashval = hash(hashname(str2short(dp->d_name)), i); - bis(xhash, hashval); - /* tw_add_comm_name (dp->d_name); */ - } - (void) closedir(dirp); - } -} - -void -/*ARGSUSED*/ -dounhash(Char **v, struct command *t) -{ - havhash = 0; -} - -void -/*ARGSUSED*/ -hashstat(Char **v, struct command *t) -{ - if (hits + misses) - (void)fprintf(cshout, "%d hits, %d misses, %d%%\n", - hits, misses, 100 * hits / (hits + misses)); -} - -/* - * Hash a command name. - */ -static int -hashname(Char *cp) -{ - long h = 0; - - while (*cp) - h = hash(h, *cp++); - return ((int) h); -} - -static int -iscommand(Char *name) -{ - struct varent *v; - Char **pv, *sav; - int hashval, hashval1, i; - int slash; - - hashval = 0; - slash = any(short2str(name), '/'); - v = adrof(STRpath); - - if (v == 0 || v->vec[0] == 0 || slash) - pv = justabs; - else - pv = v->vec; - sav = Strspl(STRslash, name); /* / command name for postpending */ - if (havhash) - hashval = hashname(name); - i = 0; - do { - if (!slash && pv[0][0] == '/' && havhash) { - hashval1 = hash(hashval, i); - if (!bit(xhash, hashval1)) - goto cont; - } - if (pv[0][0] == 0 || eq(pv[0], STRdot)) { /* don't make ./xxx */ - if (executable(NULL, name, 0)) { - xfree((ptr_t) sav); - return i + 1; - } - } - else { - if (executable(*pv, sav, 0)) { - xfree((ptr_t) sav); - return i + 1; - } - } -cont: - pv++; - i++; - } while (*pv); - xfree((ptr_t) sav); - return 0; -} - -/* Also by: - * Andreas Luik - * I S A GmbH - Informationssysteme fuer computerintegrierte Automatisierung - * Azenberstr. 35 - * D-7000 Stuttgart 1 - * West-Germany - * is the executable() routine below and changes to iscommand(). - * Thanks again!! - */ - -/* - * executable() examines the pathname obtained by concatenating dir and name - * (dir may be NULL), and returns 1 either if it is executable by us, or - * if dir_ok is set and the pathname refers to a directory. - * This is a bit kludgy, but in the name of optimization... - */ -static int -executable(Char *dir, Char *name, int dir_ok) -{ - struct stat stbuf; - Char path[MAXPATHLEN + 1], *dp, *sp; - char *strname; - - if (dir && *dir) { - for (dp = path, sp = dir; *sp; *dp++ = *sp++) - if (dp == &path[MAXPATHLEN + 1]) { - *--dp = '\0'; - break; - } - for (sp = name; *sp; *dp++ = *sp++) - if (dp == &path[MAXPATHLEN + 1]) { - *--dp = '\0'; - break; - } - *dp = '\0'; - strname = short2str(path); - } - else - strname = short2str(name); - return (stat(strname, &stbuf) != -1 && ((S_ISREG(stbuf.st_mode) && - /* save time by not calling access() in the hopeless case */ - (stbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) && - access(strname, X_OK) == 0) || (dir_ok && S_ISDIR(stbuf.st_mode)))); -} - -/* The dowhich() is by: - * Andreas Luik - * I S A GmbH - Informationssysteme fuer computerintegrierte Automatisierung - * Azenberstr. 35 - * D-7000 Stuttgart 1 - * West-Germany - * Thanks!! - */ -/*ARGSUSED*/ -void -dowhich(Char **v, struct command *c) -{ - struct wordent lexw[3]; - struct varent *vp; - - lexw[0].next = &lexw[1]; - lexw[1].next = &lexw[2]; - lexw[2].next = &lexw[0]; - - lexw[0].prev = &lexw[2]; - lexw[1].prev = &lexw[0]; - lexw[2].prev = &lexw[1]; - - lexw[0].word = STRNULL; - lexw[2].word = STRret; - - while (*++v) { - if ((vp = adrof1(*v, &aliases)) != NULL) { - (void)fprintf(cshout, "%s: \t aliased to ", vis_str(*v)); - blkpr(cshout, vp->vec); - (void)fputc('\n', cshout); - set(STRstatus, Strsave(STR0)); - } - else { - lexw[1].word = *v; - set(STRstatus, Strsave(tellmewhat(lexw, NULL) ? STR0 : STR1)); - } - } -} - -static int -tellmewhat(struct wordent *lexp, Char *str) -{ - struct biltins *bptr; - struct wordent *sp; - Char *cmd, *s0, *s1, *s2; - int i; - int aliased, found; - Char qc; - - aliased = 0; - sp = lexp->next; - - if (adrof1(sp->word, &aliases)) { - alias(lexp); - sp = lexp->next; - aliased = 1; - } - - s0 = sp->word; /* to get the memory freeing right... */ - - /* handle quoted alias hack */ - if ((*(sp->word) & (QUOTE | TRIM)) == QUOTE) - (sp->word)++; - - /* do quoting, if it hasn't been done */ - s1 = s2 = sp->word; - while (*s2) - switch (*s2) { - case '\'': - case '"': - qc = *s2++; - while (*s2 && *s2 != qc) - *s1++ = (Char)(*s2++ | QUOTE); - if (*s2) - s2++; - break; - case '\\': - if (*++s2) - *s1++ = (Char)(*s2++ | QUOTE); - break; - default: - *s1++ = *s2++; - } - *s1 = '\0'; - - for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++) { - if (eq(sp->word, str2short(bptr->bname))) { - if (str == NULL) { - if (aliased) - prlex(cshout, lexp); - (void)fprintf(cshout, "%s: shell built-in command.\n", - vis_str(sp->word)); - } - else - (void)Strcpy(str, sp->word); - sp->word = s0; /* we save and then restore this */ - return 1; - } - } - - sp->word = cmd = globone(sp->word, G_IGNORE); - - if ((i = iscommand(sp->word)) != 0) { - Char **pv; - struct varent *v; - int slash = any(short2str(sp->word), '/'); - - v = adrof(STRpath); - if (v == 0 || v->vec[0] == 0 || slash) - pv = justabs; - else - pv = v->vec; - - while (--i) - pv++; - if (pv[0][0] == 0 || eq(pv[0], STRdot)) { - if (!slash) { - sp->word = Strspl(STRdotsl, sp->word); - prlex(cshout, lexp); - xfree((ptr_t) sp->word); - } - else - prlex(cshout, lexp); - } - else { - s1 = Strspl(*pv, STRslash); - sp->word = Strspl(s1, sp->word); - xfree((ptr_t) s1); - if (str == NULL) - prlex(cshout, lexp); - else - (void)Strcpy(str, sp->word); - xfree((ptr_t) sp->word); - } - found = 1; - } - else { - if (str == NULL) { - if (aliased) - prlex(cshout, lexp); - (void)fprintf(csherr, - "%s: Command not found.\n", vis_str(sp->word)); - } - else - (void)Strcpy(str, sp->word); - found = 0; - } - sp->word = s0; /* we save and then restore this */ - xfree((ptr_t) cmd); - return found; -} diff --git a/bin/csh/exp.c b/bin/csh/exp.c deleted file mode 100644 index a4be1fc14..000000000 --- a/bin/csh/exp.c +++ /dev/null @@ -1,661 +0,0 @@ -/* $NetBSD: exp.c,v 1.20 2009/02/14 07:12:29 lukem Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)exp.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: exp.c,v 1.20 2009/02/14 07:12:29 lukem Exp $"); -#endif -#endif /* not lint */ - -#include -#include - -#include -#include -#include - -#ifndef SHORT_STRINGS -#include -#endif /* SHORT_STRINGS */ - -#include "csh.h" -#include "extern.h" - -#define IGNORE 1 /* in ignore, it means to ignore value, just parse */ -#define NOGLOB 2 /* in ignore, it means not to globone */ - -#define ADDOP 1 -#define MULOP 2 -#define EQOP 4 -#define RELOP 8 -#define RESTOP 16 -#define ANYOP 31 - -#define EQEQ 1 -#define GTR 2 -#define LSS 4 -#define NOTEQ 6 -#define EQMATCH 7 -#define NOTEQMATCH 8 - -static int exp1(Char ***, int); -static int csh_exp2(Char ***, int); -static int exp2a(Char ***, int); -static int exp2b(Char ***, int); -static int exp2c(Char ***, int); -static Char *exp3(Char ***, int); -static Char *exp3a(Char ***, int); -static Char *exp4(Char ***, int); -static Char *exp5(Char ***, int); -static Char *exp6(Char ***, int); -static void evalav(Char **); -static int isa(Char *, int); -static int egetn(Char *); - -#ifdef EDEBUG -static void etracc(char *, Char *, Char ***); -static void etraci(char *, int, Char ***); -#endif - -int -expr(Char ***vp) -{ - return (exp0(vp, 0)); -} - -int -exp0(Char ***vp, int ignore) -{ - int p1; - - p1 = exp1(vp, ignore); -#ifdef EDEBUG - etraci("exp0 p1", p1, vp); -#endif - if (**vp && eq(**vp, STRor2)) { - int p2; - - (*vp)++; - p2 = exp0(vp, (ignore & IGNORE) || p1); -#ifdef EDEBUG - etraci("exp0 p2", p2, vp); -#endif - return (p1 || p2); - } - return (p1); -} - -static int -exp1(Char ***vp, int ignore) -{ - int p1; - - p1 = csh_exp2(vp, ignore); -#ifdef EDEBUG - etraci("exp1 p1", p1, vp); -#endif - if (**vp && eq(**vp, STRand2)) { - int p2; - - (*vp)++; - p2 = exp1(vp, (ignore & IGNORE) || !p1); -#ifdef EDEBUG - etraci("exp1 p2", p2, vp); -#endif - return (p1 && p2); - } - return (p1); -} - -static int -csh_exp2(Char ***vp, int ignore) -{ - int p1; - - p1 = exp2a(vp, ignore); -#ifdef EDEBUG - etraci("exp3 p1", p1, vp); -#endif - if (**vp && eq(**vp, STRor)) { - int p2; - - (*vp)++; - p2 = csh_exp2(vp, ignore); -#ifdef EDEBUG - etraci("exp3 p2", p2, vp); -#endif - return (p1 | p2); - } - return (p1); -} - -static int -exp2a(Char ***vp, int ignore) -{ - int p1; - - p1 = exp2b(vp, ignore); -#ifdef EDEBUG - etraci("exp2a p1", p1, vp); -#endif - if (**vp && eq(**vp, STRcaret)) { - int p2; - - (*vp)++; - p2 = exp2a(vp, ignore); -#ifdef EDEBUG - etraci("exp2a p2", p2, vp); -#endif - return (p1 ^ p2); - } - return (p1); -} - -static int -exp2b(Char ***vp, int ignore) -{ - int p1; - - p1 = exp2c(vp, ignore); -#ifdef EDEBUG - etraci("exp2b p1", p1, vp); -#endif - if (**vp && eq(**vp, STRand)) { - int p2; - - (*vp)++; - p2 = exp2b(vp, ignore); -#ifdef EDEBUG - etraci("exp2b p2", p2, vp); -#endif - return (p1 & p2); - } - return (p1); -} - -static int -exp2c(Char ***vp, int ignore) -{ - Char *p1, *p2; - int i; - - p1 = exp3(vp, ignore); -#ifdef EDEBUG - etracc("exp2c p1", p1, vp); -#endif - if ((i = isa(**vp, EQOP)) != 0) { - (*vp)++; - if (i == EQMATCH || i == NOTEQMATCH) - ignore |= NOGLOB; - p2 = exp3(vp, ignore); -#ifdef EDEBUG - etracc("exp2c p2", p2, vp); -#endif - if (!(ignore & IGNORE)) - switch (i) { - case EQEQ: - i = eq(p1, p2); - break; - case EQMATCH: - i = Gmatch(p1, p2); - break; - case NOTEQ: - i = !eq(p1, p2); - break; - case NOTEQMATCH: - i = !Gmatch(p1, p2); - break; - } - xfree((ptr_t) p1); - xfree((ptr_t) p2); - return (i); - } - i = egetn(p1); - xfree((ptr_t) p1); - return (i); -} - -static Char * -exp3(Char ***vp, int ignore) -{ - Char *p1, *p2; - int i; - - p1 = exp3a(vp, ignore); -#ifdef EDEBUG - etracc("exp3 p1", p1, vp); -#endif - if ((i = isa(**vp, RELOP)) != 0) { - (*vp)++; - if (**vp && eq(**vp, STRequal)) - i |= 1, (*vp)++; - p2 = exp3(vp, ignore); -#ifdef EDEBUG - etracc("exp3 p2", p2, vp); -#endif - if (!(ignore & IGNORE)) - switch (i) { - case GTR: - i = egetn(p1) > egetn(p2); - break; - case GTR | 1: - i = egetn(p1) >= egetn(p2); - break; - case LSS: - i = egetn(p1) < egetn(p2); - break; - case LSS | 1: - i = egetn(p1) <= egetn(p2); - break; - } - xfree((ptr_t) p1); - xfree((ptr_t) p2); - return (putn(i)); - } - return (p1); -} - -static Char * -exp3a(Char ***vp, int ignore) -{ - Char *op, *p1, *p2; - int i; - - p1 = exp4(vp, ignore); -#ifdef EDEBUG - etracc("exp3a p1", p1, vp); -#endif - op = **vp; - if (op && any("<>", op[0]) && op[0] == op[1]) { - (*vp)++; - p2 = exp3a(vp, ignore); -#ifdef EDEBUG - etracc("exp3a p2", p2, vp); -#endif - if (op[0] == '<') - i = egetn(p1) << egetn(p2); - else - i = egetn(p1) >> egetn(p2); - xfree((ptr_t) p1); - xfree((ptr_t) p2); - return (putn(i)); - } - return (p1); -} - -static Char * -exp4(Char ***vp, int ignore) -{ - Char *p1, *p2; - int i; - - i = 0; - p1 = exp5(vp, ignore); -#ifdef EDEBUG - etracc("exp4 p1", p1, vp); -#endif - if (isa(**vp, ADDOP)) { - Char *op; - - op = *(*vp)++; - p2 = exp4(vp, ignore); -#ifdef EDEBUG - etracc("exp4 p2", p2, vp); -#endif - if (!(ignore & IGNORE)) - switch (op[0]) { - case '+': - i = egetn(p1) + egetn(p2); - break; - case '-': - i = egetn(p1) - egetn(p2); - break; - } - xfree((ptr_t) p1); - xfree((ptr_t) p2); - return (putn(i)); - } - return (p1); -} - -static Char * -exp5(Char ***vp, int ignore) -{ - Char *p1, *p2; - int i; - - i = 0; - p1 = exp6(vp, ignore); -#ifdef EDEBUG - etracc("exp5 p1", p1, vp); -#endif - if (isa(**vp, MULOP)) { - Char *op; - - op = *(*vp)++; - p2 = exp5(vp, ignore); -#ifdef EDEBUG - etracc("exp5 p2", p2, vp); -#endif - if (!(ignore & IGNORE)) - switch (op[0]) { - case '*': - i = egetn(p1) * egetn(p2); - break; - case '/': - i = egetn(p2); - if (i == 0) - stderror(ERR_DIV0); - i = egetn(p1) / i; - break; - case '%': - i = egetn(p2); - if (i == 0) - stderror(ERR_MOD0); - i = egetn(p1) % i; - break; - } - xfree((ptr_t) p1); - xfree((ptr_t) p2); - return (putn(i)); - } - return (p1); -} - -static Char * -exp6(Char ***vp, int ignore) -{ - Char *cp, *dp, *ep; - int ccode, i; - - i = 0; - if (**vp == 0) - stderror(ERR_NAME | ERR_EXPRESSION); - if (eq(**vp, STRbang)) { - (*vp)++; - cp = exp6(vp, ignore); -#ifdef EDEBUG - etracc("exp6 ! cp", cp, vp); -#endif - i = egetn(cp); - xfree((ptr_t) cp); - return (putn(!i)); - } - if (eq(**vp, STRtilde)) { - (*vp)++; - cp = exp6(vp, ignore); -#ifdef EDEBUG - etracc("exp6 ~ cp", cp, vp); -#endif - i = egetn(cp); - xfree((ptr_t) cp); - return (putn(~i)); - } - if (eq(**vp, STRLparen)) { - (*vp)++; - ccode = exp0(vp, ignore); -#ifdef EDEBUG - etraci("exp6 () ccode", ccode, vp); -#endif - if (**vp == 0 || ***vp != ')') - stderror(ERR_NAME | ERR_EXPRESSION); - (*vp)++; - return (putn(ccode)); - } - if (eq(**vp, STRLbrace)) { - struct command faket; - Char *fakecom[2]; - Char **v; - - faket.t_dtyp = NODE_COMMAND; - faket.t_dflg = 0; - faket.t_dcar = faket.t_dcdr = faket.t_dspr = NULL; - faket.t_dcom = fakecom; - fakecom[0] = STRfakecom; - fakecom[1] = NULL; - (*vp)++; - v = *vp; - for (;;) { - if (!**vp) - stderror(ERR_NAME | ERR_MISSING, '}'); - if (eq(*(*vp)++, STRRbrace)) - break; - } - if (ignore & IGNORE) - return (Strsave(STRNULL)); - psavejob(); - if (pfork(&faket, -1) == 0) { - *--(*vp) = 0; - evalav(v); - exitstat(); - } - pwait(); - prestjob(); -#ifdef EDEBUG - etraci("exp6 {} status", egetn(value(STRstatus)), vp); -#endif - return (putn(egetn(value(STRstatus)) == 0)); - } - if (isa(**vp, ANYOP)) - return (Strsave(STRNULL)); - cp = *(*vp)++; - if (*cp == '-' && any("erwxfdzopls", cp[1])) { - struct stat stb; - - if (cp[2] != '\0') - stderror(ERR_NAME | ERR_FILEINQ); - /* - * Detect missing file names by checking for operator in the file name - * position. However, if an operator name appears there, we must make - * sure that there's no file by that name (e.g., "/") before announcing - * an error. Even this check isn't quite right, since it doesn't take - * globbing into account. - */ - if (isa(**vp, ANYOP) && stat(short2str(**vp), &stb)) - stderror(ERR_NAME | ERR_FILENAME); - - dp = *(*vp)++; - if (ignore & IGNORE) - return (Strsave(STRNULL)); - ep = globone(dp, G_ERROR); - switch (cp[1]) { - case 'r': - i = !access(short2str(ep), R_OK); - break; - case 'w': - i = !access(short2str(ep), W_OK); - break; - case 'x': - i = !access(short2str(ep), X_OK); - break; - default: - if (cp[1] == 'l' ? - lstat(short2str(ep), &stb) : stat(short2str(ep), &stb)) { - xfree((ptr_t) ep); - return (Strsave(STR0)); - } - switch (cp[1]) { - case 'd': - i = S_ISDIR(stb.st_mode); - break; - case 'e': - i = 1; - break; - case 'f': - i = S_ISREG(stb.st_mode); - break; - case 'l': -#ifdef S_ISLNK - i = S_ISLNK(stb.st_mode); -#else - i = 0; -#endif - break; - case 'o': - i = stb.st_uid == (uid_t)uid; - break; - case 'p': -#ifdef S_ISFIFO - i = S_ISFIFO(stb.st_mode); -#else - i = 0; -#endif - break; - case 's': -#ifdef S_ISSOCK - i = S_ISSOCK(stb.st_mode); -#else - i = 0; -#endif - break; - case 'z': - i = stb.st_size == 0; - break; - } - } -#ifdef EDEBUG - etraci("exp6 -? i", i, vp); -#endif - xfree((ptr_t) ep); - return (putn(i)); - } -#ifdef EDEBUG - etracc("exp6 default", cp, vp); -#endif - return (ignore & NOGLOB ? Strsave(cp) : globone(cp, G_ERROR)); -} - -static void -evalav(Char **v) -{ - struct wordent *hp, paraml1, *wdp; - struct command *t; - - hp = ¶ml1; - wdp = hp; - set(STRstatus, Strsave(STR0)); - hp->prev = hp->next = hp; - hp->word = STRNULL; - while (*v) { - struct wordent *new; - - new = (struct wordent *)xcalloc(1, sizeof *wdp); - new->prev = wdp; - new->next = hp; - wdp->next = new; - wdp = new; - wdp->word = Strsave(*v++); - } - hp->prev = wdp; - alias(¶ml1); - t = syntax(paraml1.next, ¶ml1, 0); - if (seterr) - stderror(ERR_OLD); - execute(t, -1, NULL, NULL); - freelex(¶ml1), freesyn(t); -} - -static int -isa(Char *cp, int what) -{ - if (cp == 0) - return ((what & RESTOP) != 0); - if (cp[1] == 0) { - if (what & ADDOP && (*cp == '+' || *cp == '-')) - return (1); - if (what & MULOP && (*cp == '*' || *cp == '/' || *cp == '%')) - return (1); - if (what & RESTOP && (*cp == '(' || *cp == ')' || *cp == '!' || - *cp == '~' || *cp == '^' || *cp == '"')) - return (1); - } - else if (cp[2] == 0) { - if (what & RESTOP) { - if (cp[0] == '|' && cp[1] == '&') - return (1); - if (cp[0] == '<' && cp[1] == '<') - return (1); - if (cp[0] == '>' && cp[1] == '>') - return (1); - } - if (what & EQOP) { - if (cp[0] == '=') { - if (cp[1] == '=') - return (EQEQ); - if (cp[1] == '~') - return (EQMATCH); - } - else if (cp[0] == '!') { - if (cp[1] == '=') - return (NOTEQ); - if (cp[1] == '~') - return (NOTEQMATCH); - } - } - } - if (what & RELOP) { - if (*cp == '<') - return (LSS); - if (*cp == '>') - return (GTR); - } - return (0); -} - -static int -egetn(Char *cp) -{ - if (*cp && *cp != '-' && !Isdigit(*cp)) - stderror(ERR_NAME | ERR_EXPRESSION); - return (getn(cp)); -} - -/* Phew! */ - -#ifdef EDEBUG -static void -etraci(char *str, int i, Char ***vp) -{ - (void)fprintf(csherr, "%s=%d\t", str, i); - blkpr(csherr, *vp); - (void)fprintf(csherr, "\n"); -} -static void -etracc(char *str, Char *cp, Char ***vp) -{ - (void)fprintf(csherr, "%s=%s\t", str, vis_str(cp)); - blkpr(csherr, *vp); - (void)fprintf(csherr, "\n"); -} -#endif diff --git a/bin/csh/extern.h b/bin/csh/extern.h deleted file mode 100644 index 0d882f93c..000000000 --- a/bin/csh/extern.h +++ /dev/null @@ -1,341 +0,0 @@ -/* $NetBSD: extern.h,v 1.29 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)extern.h 8.1 (Berkeley) 5/31/93 - */ - -#ifndef _EXTERN_H_ -#define _EXTERN_H_ - -#include - -/* - * csh.c - */ -int gethdir(Char *); -void dosource(Char **, struct command *); -__dead void exitstat(void); -__dead void goodbye(void); -void importpath(Char *); -void initdesc(void); -__dead void pintr(int); -__dead void pintr1(int); -void printprompt(void); -#ifdef EDIT -char *printpromptstr(EditLine *); -#endif -void process(int); -void rechist(void); -void untty(void); -int vis_fputc(int, FILE *); - -#ifdef PROF -__dead void done(int); -#else -__dead void xexit(int); -#endif - -/* - * dir.c - */ -void dinit(Char *); -void dodirs(Char **, struct command *); -Char *dcanon(Char *, Char *); -void dtildepr(Char *, Char *); -void dtilde(void); -void dochngd(Char **, struct command *); -Char *dnormalize(Char *); -void dopushd(Char **, struct command *); -void dopopd(Char **, struct command *); -struct directory; -void dfree(struct directory *); - -/* - * dol.c - */ -void Dfix(struct command *); -Char *Dfix1(Char *); -void heredoc(Char *); - -/* - * err.c - */ -void seterror(int, ...); -__dead void stderror(int, ...); - -/* - * exec.c - */ -__dead void doexec(Char **, struct command *); -void dohash(Char **, struct command *); -void dounhash(Char **, struct command *); -void dowhich(Char **, struct command *); -void execash(Char **, struct command *); -void hashstat(Char **, struct command *); -void xechoit(Char **); - -/* - * exp.c - */ -int expr(Char ***); -int exp0(Char ***, int); - -/* - * file.c - */ -#ifdef FILEC -ssize_t tenex(Char *, size_t); -#endif - -/* - * func.c - */ -void Setenv(Char *, Char *); -void doalias(Char **, struct command *); -void dobreak(Char **, struct command *); -void docontin(Char **, struct command *); -void doecho(Char **, struct command *); -void doelse(Char **, struct command *); -void doend(Char **, struct command *); -void doeval(Char **, struct command *); -void doexit(Char **, struct command *); -void doforeach(Char **, struct command *); -void doglob(Char **, struct command *); -void dogoto(Char **, struct command *); -void doif(Char **, struct command *); -void dolimit(Char **, struct command *); -__dead void dologin(Char **, struct command *); -__dead void dologout(Char **, struct command *); -void donohup(Char **, struct command *); -void doonintr(Char **, struct command *); -void doprintf(Char **, struct command *); -void dorepeat(Char **, struct command *); -void dosetenv(Char **, struct command *); -void dosuspend(Char **, struct command *); -void doswbrk(Char **, struct command *); -void doswitch(Char **, struct command *); -void doumask(Char **, struct command *); -void dounlimit(Char **, struct command *); -void dounsetenv(Char **, struct command *); -void dowhile(Char **, struct command *); -void dozip(Char **, struct command *); -void func(struct command *, struct biltins *); -struct biltins *isbfunc(struct command *); -void prvars(void); -void gotolab(Char *); -int srchx(Char *); -void unalias(Char **, struct command *); -void wfree(void); - -/* - * glob.c - */ -Char **dobackp(Char *, int); -void Gcat(Char *, Char *); -Char *globone(Char *, int); -int Gmatch(Char *, Char *); -void ginit(void); -Char **globall(Char **); -void rscan(Char **, void (*)(int)); -void tglob(Char **); -void trim(Char **); -#ifdef FILEC -int sortscmp(const ptr_t, const ptr_t); -#endif /* FILEC */ - -/* - * hist.c - */ -void dohist(Char **, struct command *); -struct Hist *enthist(int, struct wordent *, int); -#ifdef EDIT -void loadhist(struct Hist *); -#endif -void savehist(struct wordent *); - -/* - * lex.c - */ -void addla(Char *); -void bseek(struct Ain *); -void btell(struct Ain *); -void btoeof(void); -void copylex(struct wordent *, struct wordent *); -Char *domod(Char *, int); -void freelex(struct wordent *); -int lex(struct wordent *); -void prlex(FILE *, struct wordent *); -#ifdef EDIT -int sprlex(char **, struct wordent *); -#endif -int readc(int); -void settell(void); -void unreadc(int); - -/* - * misc.c - */ -int any(const char *, int); -Char **blkcat(Char **, Char **); -Char **blkcpy(Char **, Char **); -Char **blkend(Char **); -void blkfree(Char **); -int blklen(Char **); -void blkpr(FILE *, Char **); -Char **blkspl(Char **, Char **); -void closem(void); -Char **copyblk(Char **); -int dcopy(int, int); -int dmove(int, int); -void donefds(void); -Char lastchr(Char *); -void lshift(Char **, size_t); -int number(Char *); -int prefix(Char *, Char *); -Char **saveblk(Char **); -Char *strip(Char *); -Char *quote(Char *); -char *strsave(const char *); -char *strspl(char *, char *); -__dead void udvar(Char *); - -#ifndef SHORT_STRINGS -# ifdef NOTUSED -char *strstr(const char *, const char *); -# endif /* NOTUSED */ -char *strend(char *); -#endif - -/* - * parse.c - */ -void alias(struct wordent *); -void freesyn(struct command *); -struct command *syntax(struct wordent *, struct wordent *, int); - - -/* - * proc.c - */ -void dobg(Char **, struct command *); -void dobg1(Char **, struct command *); -void dofg(Char **, struct command *); -void dofg1(Char **, struct command *); -void dojobs(Char **, struct command *); -void dokill(Char **, struct command *); -void donotify(Char **, struct command *); -void dostop(Char **, struct command *); -void dowait(Char **, struct command *); -void palloc(int, struct command *); -void panystop(int); -void pchild(int); -void pendjob(void); -struct process *pfind(Char *); -int pfork(struct command *, int); -void pgetty(int, int); -void pjwait(struct process *); -void pnote(void); -void prestjob(void); -void psavejob(void); -void pstart(struct process *, int); -void pwait(void); - -/* - * sem.c - */ -void execute(struct command *, int, int *, int *); -void mypipe(int *); - -/* - * set.c - */ -struct varent*adrof1(Char *, struct varent *); -void doset(Char **, struct command *); -void dolet(Char **, struct command *); -Char *putn(int); -int getn(Char *); -Char *value1(Char *, struct varent *); -void set(Char *, Char *); -void set1(Char *, Char **, struct varent *); -void setq(Char *, Char **, struct varent *); -void unset(Char **, struct command *); -void unset1(Char *[], struct varent *); -void unsetv(Char *); -void setNS(Char *); -void shift(Char **, struct command *); -void plist(struct varent *); - -/* - * time.c - */ -void donice(Char **, struct command *); -void dotime(Char **, struct command *); -void prusage(FILE *, struct rusage *, struct rusage *, struct timespec *, - struct timespec *); -void ruadd(struct rusage *, struct rusage *); -void settimes(void); -void psecs(long); - -/* - * alloc.c - */ -void Free(ptr_t); -ptr_t Malloc(size_t); -ptr_t Realloc(ptr_t, size_t); -ptr_t Calloc(size_t, size_t); - -/* - * str.c: - */ -#ifdef SHORT_STRINGS -Char *s_strchr(const Char *, int); -Char *s_strrchr(const Char *, int); -Char *s_strcat(Char *, const Char *); -#ifdef NOTUSED -Char *s_strncat(Char *, const Char *, size_t); -#endif -Char *s_strcpy(Char *, const Char *); -Char *s_strncpy(Char *, const Char *, size_t); -Char *s_strspl(const Char *, const Char *); -size_t s_strlen(const Char *); -int s_strcmp(const Char *, const Char *); -int s_strncmp(const Char *, const Char *, size_t); -Char *s_strsave(const Char *); -Char *s_strend(const Char *); -Char *s_strstr(const Char *, const Char *); -Char *str2short(const char *); -Char **blk2short(char **); -char *short2str(const Char *); -char **short2blk(Char * const *); -#endif -char *short2qstr(const Char *); -char *vis_str(const Char *); - -#endif /* !_EXTERN_H_ */ diff --git a/bin/csh/file.c b/bin/csh/file.c deleted file mode 100644 index 0933b1ac6..000000000 --- a/bin/csh/file.c +++ /dev/null @@ -1,729 +0,0 @@ -/* $NetBSD: file.c,v 1.30 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)file.c 8.2 (Berkeley) 3/19/94"; -#else -__RCSID("$NetBSD: file.c,v 1.30 2013/07/16 17:47:43 christos Exp $"); -#endif -#endif /* not lint */ - -#ifdef FILEC - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifndef SHORT_STRINGS -#include -#endif /* SHORT_STRINGS */ - -#include "csh.h" -#include "extern.h" - -/* - * Tenex style file name recognition, .. and more. - * History: - * Author: Ken Greer, Sept. 1975, CMU. - * Finally got around to adding to the Cshell., Ken Greer, Dec. 1981. - */ - -#define ON 1 -#define OFF 0 -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#define ESC '\033' - -typedef enum { - LIST, RECOGNIZE -} COMMAND; - -static void setup_tty(int); -static void back_to_col_1(void); -static int pushback(Char *); -static void catn(Char *, Char *, size_t); -static void copyn(Char *, Char *, size_t); -static Char filetype(Char *, Char *); -static void print_by_column(Char *, Char *[], size_t); -static Char *tilde(Char *, Char *); -static void retype(void); -static void beep(void); -static void print_recognized_stuff(Char *); -static void extract_dir_and_name(Char *, Char *, Char *); -static Char *getentry(DIR *, int); -static void free_items(Char **, size_t); -static size_t tsearch(Char *, COMMAND, size_t); -static int recognize(Char *, Char *, size_t, size_t); -static int is_prefix(Char *, Char *); -static int is_suffix(Char *, Char *); -static int ignored(Char *); - -/* - * Put this here so the binary can be patched with adb to enable file - * completion by default. Filec controls completion, nobeep controls - * ringing the terminal bell on incomplete expansions. - */ -int filec = 0; - -static void -setup_tty(int on) -{ - struct termios tchars; - - (void)tcgetattr(SHIN, &tchars); - - if (on) { - tchars.c_cc[VEOL] = ESC; - if (tchars.c_lflag & ICANON) - on = TCSADRAIN; - else { - tchars.c_lflag |= ICANON; - on = TCSAFLUSH; - } - } - else { - tchars.c_cc[VEOL] = _POSIX_VDISABLE; - on = TCSADRAIN; - } - - (void)tcsetattr(SHIN, on, &tchars); -} - -/* - * Move back to beginning of current line - */ -static void -back_to_col_1(void) -{ - struct termios tty, tty_normal; - sigset_t nsigset, osigset; - - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGINT); - (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); - (void)tcgetattr(SHOUT, &tty); - tty_normal = tty; - tty.c_iflag &= ~INLCR; - tty.c_oflag &= ~ONLCR; - (void)tcsetattr(SHOUT, TCSADRAIN, &tty); - (void)write(SHOUT, "\r", 1); - (void)tcsetattr(SHOUT, TCSADRAIN, &tty_normal); - (void)sigprocmask(SIG_SETMASK, &osigset, NULL); -} - -/* - * Push string contents back into tty queue - */ -static int -pushback(Char *string) -{ - struct termios tty, tty_normal; - char buf[64], svchars[sizeof(buf)]; - sigset_t nsigset, osigset; - Char *p; - size_t bufidx, i, len_str, nbuf, nsv, onsv, retrycnt; - char c; - - nsv = 0; - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGINT); - (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); - (void)tcgetattr(SHOUT, &tty); - tty_normal = tty; - tty.c_lflag &= ~(ECHOKE | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOCTL); - /* FIONREAD works only in noncanonical mode. */ - tty.c_lflag &= ~ICANON; - tty.c_cc[VMIN] = 0; - (void)tcsetattr(SHOUT, TCSADRAIN, &tty); - - for (retrycnt = 5; ; retrycnt--) { - /* - * Push back characters. - */ - for (p = string; (c = (char)*p) != '\0'; p++) - (void)ioctl(SHOUT, TIOCSTI, (ioctl_t) &c); - for (i = 0; i < nsv; i++) - (void)ioctl(SHOUT, TIOCSTI, (ioctl_t) &svchars[i]); - - if (retrycnt == 0) - break; /* give up salvaging characters */ - - len_str = (size_t)(p - string); - - if (ioctl(SHOUT, FIONREAD, (ioctl_t) &nbuf) || - nbuf <= len_str + nsv || /* The string fit. */ - nbuf > sizeof(buf)) /* For future binary compatibility - (and safety). */ - break; - - /* - * User has typed characters before the pushback finished. - * Salvage the characters. - */ - - /* This read() should be in noncanonical mode. */ - if (read(SHOUT, &buf, nbuf) != (ssize_t)nbuf) - continue; /* hangup? */ - - onsv = nsv; - for (bufidx = 0, i = 0; bufidx < nbuf; bufidx++, i++) { - c = buf[bufidx]; - if ((i < len_str) ? c != (char)string[i] : - (i < len_str + onsv) ? c != svchars[i - len_str] : 1) { - /* Salvage a character. */ - if (nsv < (int)(sizeof svchars / sizeof svchars[0])) { - svchars[nsv++] = c; - i--; /* try this comparison with the next char */ - } else - break; /* too many */ - } - } - } - -#if 1 - /* - * XXX Is this a bug or a feature of kernel tty driver? - * - * FIONREAD in canonical mode does not return correct byte count - * in tty input queue, but this is required to avoid unwanted echo. - */ - tty.c_lflag |= ICANON; - (void)tcsetattr(SHOUT, TCSADRAIN, &tty); - (void)ioctl(SHOUT, FIONREAD, (ioctl_t) &i); -#endif - (void)tcsetattr(SHOUT, TCSADRAIN, &tty_normal); - (void)sigprocmask(SIG_SETMASK, &osigset, NULL); - - return (int)nsv; -} - -/* - * Concatenate src onto tail of des. - * Des is a string whose maximum length is count. - * Always null terminate. - */ -static void -catn(Char *des, Char *src, size_t count) -{ - while (count-- > 0 && *des) - des++; - while (count-- > 0) - if ((*des++ = *src++) == 0) - return; - *des = '\0'; -} - -/* - * Like strncpy but always leave room for trailing \0 - * and always null terminate. - */ -static void -copyn(Char *des, Char *src, size_t count) -{ - while (count-- > 0) - if ((*des++ = *src++) == 0) - return; - *des = '\0'; -} - -static Char -filetype(Char *dir, Char *file) -{ - struct stat statb; - Char path[MAXPATHLEN]; - - catn(Strcpy(path, dir), file, sizeof(path) / sizeof(Char)); - if (lstat(short2str(path), &statb) == 0) { - switch (statb.st_mode & S_IFMT) { - case S_IFDIR: - return ('/'); - case S_IFLNK: - if (stat(short2str(path), &statb) == 0 && /* follow it out */ - S_ISDIR(statb.st_mode)) - return ('>'); - else - return ('@'); - case S_IFSOCK: - return ('='); - default: - if (statb.st_mode & 0111) - return ('*'); - } - } - return (' '); -} - -static struct winsize win; - -/* - * Print sorted down columns - */ -static void -print_by_column(Char *dir, Char *items[], size_t count) -{ - size_t c, columns, i, maxwidth, r, rows; - - maxwidth = 0; - - if (ioctl(SHOUT, TIOCGWINSZ, (ioctl_t) & win) < 0 || win.ws_col == 0) - win.ws_col = 80; - for (i = 0; i < count; i++) - maxwidth = maxwidth > (r = Strlen(items[i])) ? maxwidth : r; - maxwidth += 2; /* for the file tag and space */ - columns = win.ws_col / maxwidth; - if (columns == 0) - columns = 1; - rows = (count + (columns - 1)) / columns; - for (r = 0; r < rows; r++) { - for (c = 0; c < columns; c++) { - i = c * rows + r; - if (i < count) { - size_t w; - - (void)fprintf(cshout, "%s", vis_str(items[i])); - (void)fputc(dir ? filetype(dir, items[i]) : ' ', cshout); - if (c < columns - 1) { /* last column? */ - w = Strlen(items[i]) + 1; - for (; w < maxwidth; w++) - (void) fputc(' ', cshout); - } - } - } - (void)fputc('\r', cshout); - (void)fputc('\n', cshout); - } -} - -/* - * Expand file name with possible tilde usage - * ~person/mumble - * expands to - * home_directory_of_person/mumble - */ -static Char * -tilde(Char *new, Char *old) -{ - static Char person[40]; - struct passwd *pw; - Char *o, *p; - - if (old[0] != '~') - return (Strcpy(new, old)); - - for (p = person, o = &old[1]; *o && *o != '/'; *p++ = *o++) - continue; - *p = '\0'; - if (person[0] == '\0') - (void)Strcpy(new, value(STRhome)); - else { - pw = getpwnam(short2str(person)); - if (pw == NULL) - return (NULL); - (void)Strcpy(new, str2short(pw->pw_dir)); - } - (void)Strcat(new, o); - return (new); -} - -/* - * Cause pending line to be printed - */ -static void -retype(void) -{ - struct termios tty; - - (void)tcgetattr(SHOUT, &tty); - tty.c_lflag |= PENDIN; - (void)tcsetattr(SHOUT, TCSADRAIN, &tty); -} - -static void -beep(void) -{ - if (adrof(STRnobeep) == 0) - (void)write(SHOUT, "\007", 1); -} - -/* - * Erase that silly ^[ and - * print the recognized part of the string - */ -static void -print_recognized_stuff(Char *recognized_part) -{ - /* An optimized erasing of that silly ^[ */ - (void)fputc('\b', cshout); - (void)fputc('\b', cshout); - switch (Strlen(recognized_part)) { - case 0: /* erase two Characters: ^[ */ - (void)fputc(' ', cshout); - (void)fputc(' ', cshout); - (void)fputc('\b', cshout); - (void)fputc('\b', cshout); - break; - case 1: /* overstrike the ^, erase the [ */ - (void)fprintf(cshout, "%s", vis_str(recognized_part)); - (void)fputc(' ', cshout); - (void)fputc('\b', cshout); - break; - default: /* overstrike both Characters ^[ */ - (void)fprintf(cshout, "%s", vis_str(recognized_part)); - break; - } - (void)fflush(cshout); -} - -/* - * Parse full path in file into 2 parts: directory and file names - * Should leave final slash (/) at end of dir. - */ -static void -extract_dir_and_name(Char *path, Char *dir, Char *name) -{ - Char *p; - - p = Strrchr(path, '/'); - if (p == NULL) { - copyn(name, path, MAXNAMLEN); - dir[0] = '\0'; - } - else { - copyn(name, ++p, MAXNAMLEN); - copyn(dir, path, (size_t)(p - path)); - } -} - -static Char * -getentry(DIR *dir_fd, int looking_for_lognames) -{ - struct dirent *dirp; - struct passwd *pw; - - if (looking_for_lognames) { - if ((pw = getpwent()) == NULL) - return (NULL); - return (str2short(pw->pw_name)); - } - if ((dirp = readdir(dir_fd)) != NULL) - return (str2short(dirp->d_name)); - return (NULL); -} - -static void -free_items(Char **items, size_t numitems) -{ - size_t i; - - for (i = 0; i < numitems; i++) - xfree((ptr_t) items[i]); - xfree((ptr_t) items); -} - -#define FREE_ITEMS(items, numitems) { \ - sigset_t nsigset, osigset;\ -\ - sigemptyset(&nsigset);\ - (void) sigaddset(&nsigset, SIGINT);\ - (void) sigprocmask(SIG_BLOCK, &nsigset, &osigset);\ - free_items(items, numitems);\ - (void) sigprocmask(SIG_SETMASK, &osigset, NULL);\ -} - -/* - * Perform a RECOGNIZE or LIST command on string "word". - */ -static size_t -tsearch(Char *word, COMMAND command, size_t max_word_length) -{ - Char dir[MAXPATHLEN + 1], extended_name[MAXNAMLEN + 1]; - Char name[MAXNAMLEN + 1], tilded_dir[MAXPATHLEN + 1]; - DIR *dir_fd; - Char *entry; - int ignoring, looking_for_lognames; - size_t name_length, nignored, numitems; - Char **items = NULL; - size_t maxitems = 0; - - numitems = 0; - ignoring = TRUE; - nignored = 0; - - looking_for_lognames = (*word == '~') && (Strchr(word, '/') == NULL); - if (looking_for_lognames) { - (void)setpwent(); - copyn(name, &word[1], MAXNAMLEN); /* name sans ~ */ - dir_fd = NULL; - } - else { - extract_dir_and_name(word, dir, name); - if (tilde(tilded_dir, dir) == 0) - return (0); - dir_fd = opendir(*tilded_dir ? short2str(tilded_dir) : "."); - if (dir_fd == NULL) - return (0); - } - -again: /* search for matches */ - name_length = Strlen(name); - for (numitems = 0; (entry = getentry(dir_fd, looking_for_lognames)) != NULL;) { - if (!is_prefix(name, entry)) - continue; - /* Don't match . files on null prefix match */ - if (name_length == 0 && entry[0] == '.' && - !looking_for_lognames) - continue; - if (command == LIST) { - if ((size_t)numitems >= maxitems) { - maxitems += 1024; - if (items == NULL) - items = xmalloc(sizeof(*items) * maxitems); - else - items = xrealloc((ptr_t) items, - sizeof(*items) * maxitems); - } - items[numitems] = xmalloc((size_t) (Strlen(entry) + 1) * - sizeof(Char)); - copyn(items[numitems], entry, MAXNAMLEN); - numitems++; - } - else { /* RECOGNIZE command */ - if (ignoring && ignored(entry)) - nignored++; - else if (recognize(extended_name, - entry, name_length, ++numitems)) - break; - } - } - if (ignoring && numitems == 0 && nignored > 0) { - ignoring = FALSE; - nignored = 0; - if (looking_for_lognames) - (void)setpwent(); - else - rewinddir(dir_fd); - goto again; - } - - if (looking_for_lognames) - (void)endpwent(); - else - (void)closedir(dir_fd); - if (numitems == 0) - return (0); - if (command == RECOGNIZE) { - if (looking_for_lognames) - copyn(word, STRtilde, 1); - else - /* put back dir part */ - copyn(word, dir, max_word_length); - /* add extended name */ - catn(word, extended_name, max_word_length); - return (numitems); - } - else { /* LIST */ - qsort((ptr_t) items, numitems, sizeof(items[0]), - (int (*) (const void *, const void *)) sortscmp); - print_by_column(looking_for_lognames ? NULL : tilded_dir, - items, numitems); - if (items != NULL) - FREE_ITEMS(items, numitems); - } - return (0); -} - -/* - * Object: extend what user typed up to an ambiguity. - * Algorithm: - * On first match, copy full entry (assume it'll be the only match) - * On subsequent matches, shorten extended_name to the first - * Character mismatch between extended_name and entry. - * If we shorten it back to the prefix length, stop searching. - */ -static int -recognize(Char *extended_name, Char *entry, size_t name_length, size_t numitems) -{ - if (numitems == 1) /* 1st match */ - copyn(extended_name, entry, MAXNAMLEN); - else { /* 2nd & subsequent matches */ - Char *ent, *x; - size_t len = 0; - - x = extended_name; - for (ent = entry; *x && *x == *ent++; x++, len++) - continue; - *x = '\0'; /* Shorten at 1st Char diff */ - if (len == name_length) /* Ambiguous to prefix? */ - return (-1); /* So stop now and save time */ - } - return (0); -} - -/* - * Return true if check matches initial Chars in template. - * This differs from PWB imatch in that if check is null - * it matches anything. - */ -static int -is_prefix(Char *check, Char *template) -{ - do - if (*check == 0) - return (TRUE); - while (*check++ == *template++); - return (FALSE); -} - -/* - * Return true if the Chars in template appear at the - * end of check, I.e., are its suffix. - */ -static int -is_suffix(Char *check, Char *template) -{ - Char *c, *t; - - for (c = check; *c++;) - continue; - for (t = template; *t++;) - continue; - for (;;) { - if (t == template) - return 1; - if (c == check || *--t != *--c) - return 0; - } -} - -ssize_t -tenex(Char *inputline, size_t inputline_size) -{ - char tinputline[BUFSIZE]; - ssize_t num_read; - size_t numitems; - - setup_tty(ON); - - while ((num_read = read(SHIN, tinputline, BUFSIZE)) > 0) { - size_t i, nr = (size_t) num_read; - - - static Char delims[] = {' ', '\'', '"', '\t', ';', '&', '<', - '>', '(', ')', '|', '^', '%', '\0'}; - Char *str_end, *word_start, last_Char, should_retype; - size_t space_left; - COMMAND command; - - for (i = 0; i < nr; i++) - inputline[i] = (unsigned char) tinputline[i]; - last_Char = inputline[nr - 1] & ASCII; - - if (last_Char == '\n' || nr == inputline_size) - break; - command = (last_Char == ESC) ? RECOGNIZE : LIST; - if (command == LIST) - (void)fputc('\n', cshout); - str_end = &inputline[nr]; - if (last_Char == ESC) - --str_end; /* wipeout trailing cmd Char */ - *str_end = '\0'; - /* - * Find LAST occurence of a delimiter in the inputline. The word start - * is one Character past it. - */ - for (word_start = str_end; word_start > inputline; --word_start) - if (Strchr(delims, word_start[-1])) - break; - space_left = inputline_size - (size_t)(word_start - inputline) - 1; - numitems = tsearch(word_start, command, space_left); - - if (command == RECOGNIZE) { - /* print from str_end on */ - print_recognized_stuff(str_end); - if (numitems != 1) /* Beep = No match/ambiguous */ - beep(); - } - - /* - * Tabs in the input line cause trouble after a pushback. tty driver - * won't backspace over them because column positions are now - * incorrect. This is solved by retyping over current line. - */ - should_retype = FALSE; - if (Strchr(inputline, '\t')) { /* tab Char in input line? */ - back_to_col_1(); - should_retype = TRUE; - } - if (command == LIST) /* Always retype after a LIST */ - should_retype = TRUE; - if (pushback(inputline)) - should_retype = TRUE; - if (should_retype) { - if (command == RECOGNIZE) - (void) fputc('\n', cshout); - printprompt(); - } - if (should_retype) - retype(); - } - setup_tty(OFF); - return num_read; -} - -static int -ignored(Char *entry) -{ - struct varent *vp; - Char **cp; - - if ((vp = adrof(STRfignore)) == NULL || (cp = vp->vec) == NULL) - return (FALSE); - for (; *cp != NULL; cp++) - if (is_suffix(entry, *cp)) - return (TRUE); - return (FALSE); -} -#endif /* FILEC */ diff --git a/bin/csh/func.c b/bin/csh/func.c deleted file mode 100644 index 2501a8290..000000000 --- a/bin/csh/func.c +++ /dev/null @@ -1,1456 +0,0 @@ -/* $NetBSD: func.c,v 1.40 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)func.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: func.c,v 1.40 2013/07/16 17:47:43 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "csh.h" -#include "extern.h" -#include "pathnames.h" - -extern char **environ; -extern int progprintf(int, char **); - -static void islogin(void); -static void reexecute(struct command *); -static void preread(void); -static void doagain(void); -static void search(int, int, Char *); -static int getword(Char *); -static int keyword(Char *); -static void toend(void); -static void xecho(int, Char **); -static void Unsetenv(Char *); -static void wpfree(struct whyle *); - -struct biltins * -isbfunc(struct command *t) -{ - static struct biltins label = {"", dozip, 0, 0}; - static struct biltins foregnd = {"%job", dofg1, 0, 0}; - static struct biltins backgnd = {"%job &", dobg1, 0, 0}; - struct biltins *bp, *bp1, *bp2; - Char *cp; - - cp = t->t_dcom[0]; - - if (lastchr(cp) == ':') { - label.bname = short2str(cp); - return (&label); - } - if (*cp == '%') { - if (t->t_dflg & F_AMPERSAND) { - t->t_dflg &= ~F_AMPERSAND; - backgnd.bname = short2str(cp); - return (&backgnd); - } - foregnd.bname = short2str(cp); - return (&foregnd); - } - /* - * Binary search Bp1 is the beginning of the current search range. Bp2 is - * one past the end. - */ - for (bp1 = bfunc, bp2 = bfunc + nbfunc; bp1 < bp2;) { - int i; - - bp = bp1 + ((bp2 - bp1) >> 1); - if ((i = *cp - *bp->bname) == 0 && - (i = Strcmp(cp, str2short(bp->bname))) == 0) - return bp; - if (i < 0) - bp2 = bp; - else - bp1 = bp + 1; - } - return (0); -} - -void -func(struct command *t, struct biltins *bp) -{ - int i; - - xechoit(t->t_dcom); - setname(bp->bname); - i = blklen(t->t_dcom) - 1; - if (i < bp->minargs) - stderror(ERR_NAME | ERR_TOOFEW); - if (i > bp->maxargs) - stderror(ERR_NAME | ERR_TOOMANY); - (*bp->bfunct) (t->t_dcom, t); -} - -void -/*ARGSUSED*/ -doonintr(Char **v, struct command *t) -{ - Char *cp, *vv; - sigset_t nsigset; - - vv = v[1]; - if (parintr == SIG_IGN) - return; - if (setintr && intty) - stderror(ERR_NAME | ERR_TERMINAL); - cp = gointr; - gointr = 0; - xfree((ptr_t) cp); - if (vv == 0) { - if (setintr) { - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGINT); - (void)sigprocmask(SIG_BLOCK, &nsigset, NULL); - } else - (void)signal(SIGINT, SIG_DFL); - gointr = 0; - } - else if (eq((vv = strip(vv)), STRminus)) { - (void)signal(SIGINT, SIG_IGN); - gointr = Strsave(STRminus); - } - else { - gointr = Strsave(vv); - (void)signal(SIGINT, pintr); - } -} - -void -/*ARGSUSED*/ -donohup(Char **v, struct command *t) -{ - if (intty) - stderror(ERR_NAME | ERR_TERMINAL); - if (setintr == 0) { - (void) signal(SIGHUP, SIG_IGN); - } -} - -void -/*ARGSUSED*/ -dozip(Char **v, struct command *t) -{ - ; -} - -void -prvars(void) -{ - plist(&shvhed); -} - -void -/*ARGSUSED*/ -doalias(Char **v, struct command *t) -{ - struct varent *vp; - Char *p; - - v++; - p = *v++; - if (p == 0) - plist(&aliases); - else if (*v == 0) { - vp = adrof1(strip(p), &aliases); - if (vp) { - blkpr(cshout, vp->vec); - (void) fputc('\n', cshout); - } - } - else { - if (eq(p, STRalias) || eq(p, STRunalias)) { - setname(vis_str(p)); - stderror(ERR_NAME | ERR_DANGER); - } - set1(strip(p), saveblk(v), &aliases); - } -} - -void -/*ARGSUSED*/ -unalias(Char **v, struct command *t) -{ - unset1(v, &aliases); -} - -void -/*ARGSUSED*/ -dologout(Char **v, struct command *t) -{ - islogin(); - goodbye(); -} - -void -/*ARGSUSED*/ -dologin(Char **v, struct command *t) -{ - islogin(); - rechist(); - (void)signal(SIGTERM, parterm); - (void)execl(_PATH_LOGIN, "login", short2str(v[1]), NULL); - untty(); - xexit(1); - /* NOTREACHED */ -} - -static void -islogin(void) -{ - if (chkstop == 0 && setintr) - panystop(0); - if (loginsh) - return; - stderror(ERR_NOTLOGIN); - /* NOTREACHED */ -} - -void -doif(Char **v, struct command *kp) -{ - Char **vv; - int i; - - v++; - i = expr(&v); - vv = v; - if (*vv == NULL) - stderror(ERR_NAME | ERR_EMPTYIF); - if (eq(*vv, STRthen)) { - if (*++vv) - stderror(ERR_NAME | ERR_IMPRTHEN); - setname(vis_str(STRthen)); - /* - * If expression was zero, then scan to else, otherwise just fall into - * following code. - */ - if (!i) - search(T_IF, 0, NULL); - return; - } - /* - * Simple command attached to this if. Left shift the node in this tree, - * munging it so we can reexecute it. - */ - if (i) { - lshift(kp->t_dcom, (size_t)(vv - kp->t_dcom)); - reexecute(kp); - donefds(); - } -} - -/* - * Reexecute a command, being careful not - * to redo i/o redirection, which is already set up. - */ -static void -reexecute(struct command *kp) -{ - kp->t_dflg &= F_SAVE; - kp->t_dflg |= F_REPEAT; - /* - * If tty is still ours to arbitrate, arbitrate it; otherwise dont even set - * pgrp's as the jobs would then have no way to get the tty (we can't give - * it to them, and our parent wouldn't know their pgrp, etc. - */ - execute(kp, (tpgrp > 0 ? tpgrp : -1), NULL, NULL); -} - -void -/*ARGSUSED*/ -doelse(Char **v, struct command *t) -{ - search(T_ELSE, 0, NULL); -} - -void -/*ARGSUSED*/ -dogoto(Char **v, struct command *t) -{ - Char *lp; - - gotolab(lp = globone(v[1], G_ERROR)); - xfree((ptr_t) lp); -} - -void -gotolab(Char *lab) -{ - struct whyle *wp; - /* - * While we still can, locate any unknown ends of existing loops. This - * obscure code is the WORST result of the fact that we don't really parse. - */ - for (wp = whyles; wp; wp = wp->w_next) - if (wp->w_end.type == F_SEEK && wp->w_end.f_seek == 0) { - search(T_BREAK, 0, NULL); - btell(&wp->w_end); - } - else - bseek(&wp->w_end); - search(T_GOTO, 0, lab); - /* - * Eliminate loops which were exited. - */ - wfree(); -} - -void -/*ARGSUSED*/ -doswitch(Char **v, struct command *t) -{ - Char *cp, *lp; - - v++; - if (!*v || *(*v++) != '(') - stderror(ERR_SYNTAX); - cp = **v == ')' ? STRNULL : *v++; - if (*(*v++) != ')') - v--; - if (*v) - stderror(ERR_SYNTAX); - search(T_SWITCH, 0, lp = globone(cp, G_ERROR)); - xfree((ptr_t) lp); -} - -void -/*ARGSUSED*/ -dobreak(Char **v, struct command *t) -{ - if (whyles) - toend(); - else - stderror(ERR_NAME | ERR_NOTWHILE); -} - -void -/*ARGSUSED*/ -doexit(Char **v, struct command *t) -{ - if (chkstop == 0 && (intty || intact) && evalvec == 0) - panystop(0); - /* - * Don't DEMAND parentheses here either. - */ - v++; - if (*v) { - set(STRstatus, putn(expr(&v))); - if (*v) - stderror(ERR_NAME | ERR_EXPRESSION); - } - btoeof(); - if (intty) - (void) close(SHIN); -} - -void -/*ARGSUSED*/ -doforeach(Char **v, struct command *t) -{ - struct whyle *nwp; - Char *cp, *sp; - - v++; - sp = cp = strip(*v); - if (!letter(*sp)) - stderror(ERR_NAME | ERR_VARBEGIN); - while (*cp && alnum(*cp)) - cp++; - if (*cp) - stderror(ERR_NAME | ERR_VARALNUM); - if ((cp - sp) > MAXVARLEN) - stderror(ERR_NAME | ERR_VARTOOLONG); - cp = *v++; - if (v[0][0] != '(' || v[blklen(v) - 1][0] != ')') - stderror(ERR_NAME | ERR_NOPAREN); - v++; - gflag = 0, tglob(v); - v = globall(v); - if (v == 0) - stderror(ERR_NAME | ERR_NOMATCH); - nwp = (struct whyle *) xcalloc(1, sizeof *nwp); - nwp->w_fe = nwp->w_fe0 = v; - gargv = 0; - btell(&nwp->w_start); - nwp->w_fename = Strsave(cp); - nwp->w_next = whyles; - nwp->w_end.type = F_SEEK; - whyles = nwp; - /* - * Pre-read the loop so as to be more comprehensible to a terminal user. - */ - if (intty) - preread(); - doagain(); -} - -void -/*ARGSUSED*/ -dowhile(Char **v, struct command *t) -{ - int status; - int again; - - again = whyles != 0 && SEEKEQ(&whyles->w_start, &lineloc) && - whyles->w_fename == 0; - v++; - /* - * Implement prereading here also, taking care not to evaluate the - * expression before the loop has been read up from a terminal. - */ - if (intty && !again) - status = !exp0(&v, 1); - else - status = !expr(&v); - if (*v) - stderror(ERR_NAME | ERR_EXPRESSION); - if (!again) { - struct whyle *nwp = - (struct whyle *)xcalloc(1, sizeof(*nwp)); - - nwp->w_start = lineloc; - nwp->w_end.type = F_SEEK; - nwp->w_end.f_seek = 0; - nwp->w_next = whyles; - whyles = nwp; - if (intty) { - /* - * The tty preread - */ - preread(); - doagain(); - return; - } - } - if (status) - /* We ain't gonna loop no more, no more! */ - toend(); -} - -static void -preread(void) -{ - sigset_t nsigset; - - whyles->w_end.type = I_SEEK; - if (setintr) { - sigemptyset(&nsigset); - (void) sigaddset(&nsigset, SIGINT); - (void) sigprocmask(SIG_UNBLOCK, &nsigset, NULL); - } - - search(T_BREAK, 0, NULL); /* read the expression in */ - if (setintr) - (void)sigprocmask(SIG_BLOCK, &nsigset, NULL); - btell(&whyles->w_end); -} - -void -/*ARGSUSED*/ -doend(Char **v, struct command *t) -{ - if (!whyles) - stderror(ERR_NAME | ERR_NOTWHILE); - btell(&whyles->w_end); - doagain(); -} - -void -/*ARGSUSED*/ -docontin(Char **v, struct command *t) -{ - if (!whyles) - stderror(ERR_NAME | ERR_NOTWHILE); - doagain(); -} - -static void -doagain(void) -{ - /* Repeating a while is simple */ - if (whyles->w_fename == 0) { - bseek(&whyles->w_start); - return; - } - /* - * The foreach variable list actually has a spurious word ")" at the end of - * the w_fe list. Thus we are at the of the list if one word beyond this - * is 0. - */ - if (!whyles->w_fe[1]) { - dobreak(NULL, NULL); - return; - } - set(whyles->w_fename, Strsave(*whyles->w_fe++)); - bseek(&whyles->w_start); -} - -void -dorepeat(Char **v, struct command *kp) -{ - int i; - sigset_t nsigset; - - i = getn(v[1]); - if (setintr) { - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGINT); - (void)sigprocmask(SIG_BLOCK, &nsigset, NULL); - } - lshift(v, 2); - while (i > 0) { - if (setintr) - (void)sigprocmask(SIG_UNBLOCK, &nsigset, NULL); - reexecute(kp); - --i; - } - donefds(); - if (setintr) - (void) sigprocmask(SIG_UNBLOCK, &nsigset, NULL); -} - -void -/*ARGSUSED*/ -doswbrk(Char **v, struct command *t) -{ - search(T_BRKSW, 0, NULL); -} - -int -srchx(Char *cp) -{ - struct srch *sp, *sp1, *sp2; - int i; - - /* - * Binary search Sp1 is the beginning of the current search range. Sp2 is - * one past the end. - */ - for (sp1 = srchn, sp2 = srchn + nsrchn; sp1 < sp2;) { - sp = sp1 + ((sp2 - sp1) >> 1); - if ((i = *cp - *sp->s_name) == 0 && - (i = Strcmp(cp, str2short(sp->s_name))) == 0) - return sp->s_value; - if (i < 0) - sp2 = sp; - else - sp1 = sp + 1; - } - return (-1); -} - -static Char Stype; -static Char *Sgoal; - -/*VARARGS2*/ -static void -search(int type, int level, Char *goal) -{ - Char wordbuf[BUFSIZE]; - Char *aword, *cp; - struct whyle *wp; - int wlevel = 0; - - aword = wordbuf; - Stype = (Char)type; - Sgoal = goal; - if (type == T_GOTO) { - struct Ain a; - a.type = F_SEEK; - a.f_seek = 0; - bseek(&a); - } - do { - if (intty && fseekp == feobp && aret == F_SEEK) - (void)fprintf(cshout, "? "), (void)fflush(cshout); - aword[0] = 0; - (void)getword(aword); - switch (srchx(aword)) { - case T_CASE: - if (type != T_SWITCH || level != 0) - break; - (void) getword(aword); - if (lastchr(aword) == ':') - aword[Strlen(aword) - 1] = 0; - cp = strip(Dfix1(aword)); - if (Gmatch(goal, cp)) - level = -1; - xfree((ptr_t) cp); - break; - case T_DEFAULT: - if (type == T_SWITCH && level == 0) - level = -1; - break; - case T_ELSE: - if (level == 0 && type == T_IF) - return; - break; - case T_END: - if (type == T_BRKSW) { - if (wlevel == 0) { - wp = whyles; - if (wp) { - whyles = wp->w_next; - wpfree(wp); - } - } - } - if (type == T_BREAK) - level--; - wlevel--; - break; - case T_ENDIF: - if (type == T_IF || type == T_ELSE) - level--; - break; - case T_ENDSW: - if (type == T_SWITCH || type == T_BRKSW) - level--; - break; - case T_IF: - while (getword(aword)) - continue; - if ((type == T_IF || type == T_ELSE) && - eq(aword, STRthen)) - level++; - break; - case T_LABEL: - if (type == T_GOTO && getword(aword) && eq(aword, goal)) - level = -1; - break; - case T_SWITCH: - if (type == T_SWITCH || type == T_BRKSW) - level++; - break; - case T_FOREACH: - case T_WHILE: - wlevel++; - if (type == T_BREAK) - level++; - break; - default: - if (type != T_GOTO && (type != T_SWITCH || level != 0)) - break; - if (lastchr(aword) != ':') - break; - aword[Strlen(aword) - 1] = 0; - if ((type == T_GOTO && eq(aword, goal)) || - (type == T_SWITCH && eq(aword, STRdefault))) - level = -1; - break; - } - (void) getword(NULL); - } while (level >= 0); -} - -static void -wpfree(struct whyle *wp) -{ - if (wp->w_fe0) - blkfree(wp->w_fe0); - if (wp->w_fename) - xfree((ptr_t) wp->w_fename); - xfree((ptr_t) wp); -} - -static int -getword(Char *wp) -{ - int c, d, found, kwd; - Char *owp; - - c = readc(1); - d = 0; - found = 0; - kwd = 0; - owp = wp; - do { - while (c == ' ' || c == '\t') - c = readc(1); - if (c == '#') - do - c = readc(1); - while (c >= 0 && c != '\n'); - if (c < 0) - goto past; - if (c == '\n') { - if (wp) - break; - return (0); - } - unreadc(c); - found = 1; - do { - c = readc(1); - if (c == '\\' && (c = readc(1)) == '\n') - c = ' '; - if (c == '\'' || c == '"') { - if (d == 0) - d = c; - else if (d == c) - d = 0; - } - if (c < 0) - goto past; - if (wp) { - *wp++ = (Char)c; - *wp = 0; /* end the string b4 test */ - } - } while ((d || (!(kwd = keyword(owp)) && c != ' ' - && c != '\t')) && c != '\n'); - } while (wp == 0); - - /* - * if we have read a keyword ( "if", "switch" or "while" ) then we do not - * need to unreadc the look-ahead char - */ - if (!kwd) { - unreadc(c); - if (found) - *--wp = 0; - } - - return (found); - -past: - switch (Stype) { - case T_BREAK: - stderror(ERR_NAME | ERR_NOTFOUND, "end"); - /* NOTREACHED */ - case T_ELSE: - stderror(ERR_NAME | ERR_NOTFOUND, "endif"); - /* NOTREACHED */ - case T_GOTO: - setname(vis_str(Sgoal)); - stderror(ERR_NAME | ERR_NOTFOUND, "label"); - /* NOTREACHED */ - case T_IF: - stderror(ERR_NAME | ERR_NOTFOUND, "then/endif"); - /* NOTREACHED */ - case T_BRKSW: - case T_SWITCH: - stderror(ERR_NAME | ERR_NOTFOUND, "endsw"); - /* NOTREACHED */ - } - return (0); -} - -/* - * keyword(wp) determines if wp is one of the built-n functions if, - * switch or while. It seems that when an if statement looks like - * "if(" then getword above sucks in the '(' and so the search routine - * never finds what it is scanning for. Rather than rewrite doword, I hack - * in a test to see if the string forms a keyword. Then doword stops - * and returns the word "if" -strike - */ - -static int -keyword(Char *wp) -{ - static Char STRswitch[] = {'s', 'w', 'i', 't', 'c', 'h', '\0'}; - static Char STRwhile[] = {'w', 'h', 'i', 'l', 'e', '\0'}; - static Char STRif[] = {'i', 'f', '\0'}; - - if (!wp) - return (0); - - if ((Strcmp(wp, STRif) == 0) || (Strcmp(wp, STRwhile) == 0) - || (Strcmp(wp, STRswitch) == 0)) - return (1); - - return (0); -} - -static void -toend(void) -{ - if (whyles->w_end.type == F_SEEK && whyles->w_end.f_seek == 0) { - search(T_BREAK, 0, NULL); - btell(&whyles->w_end); - whyles->w_end.f_seek--; - } - else - bseek(&whyles->w_end); - wfree(); -} - -void -wfree(void) -{ - struct Ain o; - struct whyle *nwp; - - btell(&o); - - for (; whyles; whyles = nwp) { - struct whyle *wp = whyles; - nwp = wp->w_next; - - /* - * We free loops that have different seek types. - */ - if (wp->w_end.type != I_SEEK && wp->w_start.type == wp->w_end.type && - wp->w_start.type == o.type) { - if (wp->w_end.type == F_SEEK) { - if (o.f_seek >= wp->w_start.f_seek && - (wp->w_end.f_seek == 0 || o.f_seek < wp->w_end.f_seek)) - break; - } - else { - if (o.a_seek >= wp->w_start.a_seek && - (wp->w_end.a_seek == 0 || o.a_seek < wp->w_end.a_seek)) - break; - } - } - - wpfree(wp); - } -} - -void -/*ARGSUSED*/ -doecho(Char **v, struct command *t) -{ - xecho(' ', v); -} - -void -/*ARGSUSED*/ -doglob(Char **v, struct command *t) -{ - xecho(0, v); - (void)fflush(cshout); -} - -static void -xecho(int sep, Char **v) -{ - Char *cp; - sigset_t nsigset; - int nonl; - - nonl = 0; - if (setintr) { - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGINT); - (void)sigprocmask(SIG_UNBLOCK, &nsigset, NULL); - } - v++; - if (*v == 0) - goto done; - gflag = 0, tglob(v); - if (gflag) { - v = globall(v); - if (v == 0) - stderror(ERR_NAME | ERR_NOMATCH); - } - else { - v = gargv = saveblk(v); - trim(v); - } - if (sep == ' ' && *v && eq(*v, STRmn)) - nonl++, v++; - while ((cp = *v++) != NULL) { - int c; - - while ((c = *cp++) != '\0') - (void)vis_fputc(c | QUOTE, cshout); - - if (*v) - (void)vis_fputc(sep | QUOTE, cshout); - } -done: - if (sep && nonl == 0) - (void)fputc('\n', cshout); - else - (void)fflush(cshout); - if (setintr) - (void)sigprocmask(SIG_BLOCK, &nsigset, NULL); - if (gargv) - blkfree(gargv), gargv = 0; -} - -void -/*ARGSUSED*/ -dosetenv(Char **v, struct command *t) -{ - Char *lp, *vp; - sigset_t nsigset; - - v++; - if ((vp = *v++) == 0) { - Char **ep; - - if (setintr) { - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGINT); - (void)sigprocmask(SIG_UNBLOCK, &nsigset, NULL); - } - for (ep = STR_environ; *ep; ep++) - (void)fprintf(cshout, "%s\n", vis_str(*ep)); - return; - } - if ((lp = *v++) == 0) - lp = STRNULL; - Setenv(vp, lp = globone(lp, G_APPEND)); - if (eq(vp, STRPATH)) { - importpath(lp); - dohash(NULL, NULL); - } - else if (eq(vp, STRLANG) || eq(vp, STRLC_CTYPE)) { -#ifdef NLS - int k; - - (void)setlocale(LC_ALL, ""); - for (k = 0200; k <= 0377 && !Isprint(k); k++) - continue; - AsciiOnly = k > 0377; -#else - AsciiOnly = 0; -#endif /* NLS */ - } - xfree((ptr_t) lp); -} - -void -/*ARGSUSED*/ -dounsetenv(Char **v, struct command *t) -{ - static Char *name = NULL; - Char **ep, *p, *n; - int i, maxi; - - if (name) - xfree((ptr_t) name); - /* - * Find the longest environment variable - */ - for (maxi = 0, ep = STR_environ; *ep; ep++) { - for (i = 0, p = *ep; *p && *p != '='; p++, i++) - continue; - if (i > maxi) - maxi = i; - } - - name = xmalloc((size_t)(maxi + 1) * sizeof(Char)); - - while (++v && *v) - for (maxi = 1; maxi;) - for (maxi = 0, ep = STR_environ; *ep; ep++) { - for (n = name, p = *ep; *p && *p != '='; *n++ = *p++) - continue; - *n = '\0'; - if (!Gmatch(name, *v)) - continue; - maxi = 1; - if (eq(name, STRLANG) || eq(name, STRLC_CTYPE)) { -#ifdef NLS - int k; - - (void) setlocale(LC_ALL, ""); - for (k = 0200; k <= 0377 && !Isprint(k); k++) - continue; - AsciiOnly = k > 0377; -#else - AsciiOnly = getenv("LANG") == NULL && - getenv("LC_CTYPE") == NULL; -#endif /* NLS */ - } - /* - * Delete name, and start again cause the environment changes - */ - Unsetenv(name); - break; - } - xfree((ptr_t) name); - name = NULL; -} - -void -Setenv(Char *name, Char *val) -{ - Char *blk[2], *cp, *dp, **ep, **oep; - - ep = STR_environ; - oep = ep; - - for (; *ep; ep++) { - for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) - continue; - if (*cp != 0 || *dp != '=') - continue; - cp = Strspl(STRequal, val); - xfree((ptr_t)* ep); - *ep = strip(Strspl(name, cp)); - xfree((ptr_t)cp); - blkfree((Char **)environ); - environ = short2blk(STR_environ); - return; - } - cp = Strspl(name, STRequal); - blk[0] = strip(Strspl(cp, val)); - xfree((ptr_t)cp); - blk[1] = 0; - STR_environ = blkspl(STR_environ, blk); - blkfree((Char **)environ); - environ = short2blk(STR_environ); - xfree((ptr_t) oep); -} - -static void -Unsetenv(Char *name) -{ - Char *cp, *dp, **ep, **oep; - - ep = STR_environ; - oep = ep; - - for (; *ep; ep++) { - for (cp = name, dp = *ep; *cp && *cp == *dp; cp++, dp++) - continue; - if (*cp != 0 || *dp != '=') - continue; - cp = *ep; - *ep = 0; - STR_environ = blkspl(STR_environ, ep + 1); - environ = short2blk(STR_environ); - *ep = cp; - xfree((ptr_t) cp); - xfree((ptr_t) oep); - return; - } -} - -void -/*ARGSUSED*/ -doumask(Char **v, struct command *t) -{ - Char *cp; - mode_t i; - - cp = v[1]; - if (cp == 0) { - i = umask(0); - (void)umask(i); - (void)fprintf(cshout, "%o\n", i); - return; - } - i = 0; - while (Isdigit(*cp) && *cp != '8' && *cp != '9') - i = i * 8 + (mode_t)(*cp++ - '0'); - if (*cp || i > 0777) - stderror(ERR_NAME | ERR_MASK); - (void)umask(i); -} - -typedef rlim_t RLIM_TYPE; - -static const struct limits { - int limconst; - const char *limname; - int limdiv; - const char *limscale; -} limits[] = { - { RLIMIT_CPU, "cputime", 1, "seconds" }, - { RLIMIT_FSIZE, "filesize", 1024, "kbytes" }, - { RLIMIT_DATA, "datasize", 1024, "kbytes" }, - { RLIMIT_STACK, "stacksize", 1024, "kbytes" }, - { RLIMIT_CORE, "coredumpsize", 1024, "kbytes" }, - { RLIMIT_RSS, "memoryuse", 1024, "kbytes" }, - { RLIMIT_MEMLOCK, "memorylocked", 1024, "kbytes" }, - { RLIMIT_NPROC, "maxproc", 1, "" }, - { RLIMIT_NTHR, "maxthread", 1, "" }, - { RLIMIT_NOFILE, "openfiles", 1, "" }, - { RLIMIT_SBSIZE, "sbsize", 1, "bytes" }, - { RLIMIT_AS, "vmemoryuse", 1024, "kbytes" }, - { -1, NULL, 0, NULL } -}; - -static const struct limits *findlim(Char *); -static RLIM_TYPE getval(const struct limits *, Char **); -static void limtail(Char *, const char *); -static void plim(const struct limits *, Char); -static int setlim(const struct limits *, Char, RLIM_TYPE); - -static const struct limits * -findlim(Char *cp) -{ - const struct limits *lp, *res; - - res = NULL; - for (lp = limits; lp->limconst >= 0; lp++) - if (prefix(cp, str2short(lp->limname))) { - if (res) - stderror(ERR_NAME | ERR_AMBIG); - res = lp; - } - if (res) - return (res); - stderror(ERR_NAME | ERR_LIMIT); - /* NOTREACHED */ -} - -void -/*ARGSUSED*/ -dolimit(Char **v, struct command *t) -{ - const struct limits *lp; - RLIM_TYPE limit; - char hard; - - hard = 0; - v++; - if (*v && eq(*v, STRmh)) { - hard = 1; - v++; - } - if (*v == 0) { - for (lp = limits; lp->limconst >= 0; lp++) - plim(lp, hard); - return; - } - lp = findlim(v[0]); - if (v[1] == 0) { - plim(lp, hard); - return; - } - limit = getval(lp, v + 1); - if (setlim(lp, hard, limit) < 0) - stderror(ERR_SILENT); -} - -static RLIM_TYPE -getval(const struct limits *lp, Char **v) -{ - Char *cp; - double d; - - cp = *v++; - d = atof(short2str(cp)); - - while (Isdigit(*cp) || *cp == '.' || *cp == 'e' || *cp == 'E') - cp++; - if (*cp == 0) { - if (*v == 0) - return ((RLIM_TYPE)((d + 0.5) * lp->limdiv)); - cp = *v; - } - switch (*cp) { - case ':': - if (lp->limconst != RLIMIT_CPU) - goto badscal; - return ((RLIM_TYPE)(d * 60.0 + atof(short2str(cp + 1)))); - case 'M': - if (lp->limconst == RLIMIT_CPU) - goto badscal; - *cp = 'm'; - limtail(cp, "megabytes"); - d *= 1024.0 * 1024.0; - break; - case 'h': - if (lp->limconst != RLIMIT_CPU) - goto badscal; - limtail(cp, "hours"); - d *= 3600.0; - break; - case 'k': - if (lp->limconst == RLIMIT_CPU) - goto badscal; - limtail(cp, "kbytes"); - d *= 1024.0; - break; - case 'm': - if (lp->limconst == RLIMIT_CPU) { - limtail(cp, "minutes"); - d *= 60.0; - break; - } - *cp = 'm'; - limtail(cp, "megabytes"); - d *= 1024.0 * 1024.0; - break; - case 's': - if (lp->limconst != RLIMIT_CPU) - goto badscal; - limtail(cp, "seconds"); - break; - case 'u': - limtail(cp, "unlimited"); - return (RLIM_INFINITY); - default: - badscal: - stderror(ERR_NAME | ERR_SCALEF); - /* NOTREACHED */ - } - d += 0.5; - if (d > (double) RLIM_INFINITY) - return RLIM_INFINITY; - else - return ((RLIM_TYPE)d); -} - -static void -limtail(Char *cp, const char *str) -{ - while (*cp && *cp == *str) - cp++, str++; - if (*cp) - stderror(ERR_BADSCALE, str); -} - - -/*ARGSUSED*/ -static void -plim(const struct limits *lp, Char hard) -{ - struct rlimit rlim; - RLIM_TYPE limit; - - (void)fprintf(cshout, "%-13.13s", lp->limname); - - (void)getrlimit(lp->limconst, &rlim); - limit = hard ? rlim.rlim_max : rlim.rlim_cur; - - if (limit == RLIM_INFINITY) - (void)fprintf(cshout, "unlimited"); - else if (lp->limconst == RLIMIT_CPU) - psecs((long) limit); - else - (void)fprintf(cshout, "%jd %s", - (intmax_t) (limit / (RLIM_TYPE)lp->limdiv), lp->limscale); - (void)fputc('\n', cshout); -} - -void -/*ARGSUSED*/ -dounlimit(Char **v, struct command *t) -{ - const struct limits *lp; - int lerr; - Char hard; - - lerr = 0; - hard = 0; - v++; - if (*v && eq(*v, STRmh)) { - hard = 1; - v++; - } - if (*v == 0) { - for (lp = limits; lp->limconst >= 0; lp++) - if (setlim(lp, hard, (RLIM_TYPE)RLIM_INFINITY) < 0) - lerr++; - if (lerr) - stderror(ERR_SILENT); - return; - } - while (*v) { - lp = findlim(*v++); - if (setlim(lp, hard, (RLIM_TYPE)RLIM_INFINITY) < 0) - stderror(ERR_SILENT); - } -} - -static int -setlim(const struct limits *lp, Char hard, RLIM_TYPE limit) -{ - struct rlimit rlim; - - (void)getrlimit(lp->limconst, &rlim); - - if (hard) - rlim.rlim_max = limit; - else if (limit == RLIM_INFINITY && geteuid() != 0) - rlim.rlim_cur = rlim.rlim_max; - else - rlim.rlim_cur = limit; - - if (rlim.rlim_max < rlim.rlim_cur) - rlim.rlim_max = rlim.rlim_cur; - - if (setrlimit(lp->limconst, &rlim) < 0) { - (void)fprintf(csherr, "%s: %s: Can't %s%s limit (%s)\n", bname, - lp->limname, limit == RLIM_INFINITY ? "remove" : "set", - hard ? " hard" : "", strerror(errno)); - return (-1); - } - return (0); -} - -void -/*ARGSUSED*/ -dosuspend(Char **v, struct command *t) -{ - int ctpgrp; - void (*old)(int); - - if (loginsh) - stderror(ERR_SUSPLOG); - untty(); - - old = signal(SIGTSTP, SIG_DFL); - (void)kill(0, SIGTSTP); - /* the shell stops here */ - (void)signal(SIGTSTP, old); - - if (tpgrp != -1) { -retry: - ctpgrp = tcgetpgrp(FSHTTY); - if (ctpgrp != opgrp) { - old = signal(SIGTTIN, SIG_DFL); - (void)kill(0, SIGTTIN); - (void)signal(SIGTTIN, old); - goto retry; - } - (void)setpgid(0, shpgrp); - (void)tcsetpgrp(FSHTTY, shpgrp); - } -} - -/* This is the dreaded EVAL built-in. - * If you don't fiddle with file descriptors, and reset didfds, - * this command will either ignore redirection inside or outside - * its arguments, e.g. eval "date >x" vs. eval "date" >x - * The stuff here seems to work, but I did it by trial and error rather - * than really knowing what was going on. If tpgrp is zero, we are - * probably a background eval, e.g. "eval date &", and we want to - * make sure that any processes we start stay in our pgrp. - * This is also the case for "time eval date" -- stay in same pgrp. - * Otherwise, under stty tostop, processes will stop in the wrong - * pgrp, with no way for the shell to get them going again. -IAN! - */ -static Char **gv = NULL; - -void -/*ARGSUSED*/ -doeval(Char **v, struct command *t) -{ - jmp_buf osetexit; - Char *oevalp, **oevalvec, **savegv; - int my_reenter, odidfds, oSHERR, oSHIN, oSHOUT, saveERR, saveIN, saveOUT; - - savegv = gv; - UNREGISTER(v); - - oevalvec = evalvec; - oevalp = evalp; - odidfds = didfds; - oSHIN = SHIN; - oSHOUT = SHOUT; - oSHERR = SHERR; - - v++; - if (*v == 0) - return; - gflag = 0, tglob(v); - if (gflag) { - gv = v = globall(v); - gargv = 0; - if (v == 0) - stderror(ERR_NOMATCH); - v = copyblk(v); - } - else { - gv = NULL; - v = copyblk(v); - trim(v); - } - - saveIN = dcopy(SHIN, -1); - saveOUT = dcopy(SHOUT, -1); - saveERR = dcopy(SHERR, -1); - - getexit(osetexit); - - if ((my_reenter = setexit()) == 0) { - evalvec = v; - evalp = 0; - SHIN = dcopy(0, -1); - SHOUT = dcopy(1, -1); - SHERR = dcopy(2, -1); - didfds = 0; - process(0); - } - - evalvec = oevalvec; - evalp = oevalp; - doneinp = 0; - didfds = odidfds; - if (SHIN != -1) - (void)close(SHIN); - if (SHOUT != -1) - (void)close(SHOUT); - if (SHERR != -1) - (void)close(SHERR); - SHIN = dmove(saveIN, oSHIN); - SHOUT = dmove(saveOUT, oSHOUT); - SHERR = dmove(saveERR, oSHERR); - if (gv) - blkfree(gv), gv = NULL; - resexit(osetexit); - gv = savegv; - if (my_reenter) - stderror(ERR_SILENT); -} - -void -/*ARGSUSED*/ -doprintf(Char **v, struct command *t) -{ - char **c; - int ret; - - ret = progprintf(blklen(v), c = short2blk(v)); - (void)fflush(cshout); - (void)fflush(csherr); - - blkfree((Char **) c); - if (ret) - stderror(ERR_SILENT); -} diff --git a/bin/csh/glob.c b/bin/csh/glob.c deleted file mode 100644 index 7f01c9c24..000000000 --- a/bin/csh/glob.c +++ /dev/null @@ -1,923 +0,0 @@ -/* $NetBSD: glob.c,v 1.27 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)glob.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: glob.c,v 1.27 2013/07/16 17:47:43 christos Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "csh.h" -#include "extern.h" - -static int noglob; -static int gargsiz, pargsiz; - -/* - * Values for gflag - */ -#define G_NONE 0 /* No globbing needed */ -#define G_GLOB 1 /* string contains *?[] characters */ -#define G_CSH 2 /* string contains ~`{ characters */ - -#define GLOBSPACE 100 /* Alloc increment */ - -#define LBRC '{' -#define RBRC '}' -#define LBRK '[' -#define RBRK ']' -#define EOS '\0' - -Char **gargv = NULL; -Char **pargv = NULL; -long gargc = 0; -long pargc = 0; - -/* - * globbing is now done in two stages. In the first pass we expand - * csh globbing idioms ~`{ and then we proceed doing the normal - * globbing if needed ?*[ - * - * Csh type globbing is handled in globexpand() and the rest is - * handled in glob() which is part of the 4.4BSD libc. - * - */ -static Char *globtilde(Char **, Char *); -static Char *handleone(Char *, Char **, int); -static Char **libglob(Char **); -static Char **globexpand(Char **); -static int globbrace(Char *, Char *, Char ***); -static void expbrace(Char ***, Char ***, size_t); -static int pmatch(Char *, Char *); -static void pword(void); -static void psave(int); -static void backeval(Char *, int); - -static Char * -globtilde(Char **nv, Char *s) -{ - Char gbuf[MAXPATHLEN], *b, *e, *gstart, *u; - - gstart = gbuf; - *gstart++ = *s++; - u = s; - for (b = gstart, e = &gbuf[MAXPATHLEN - 1]; - *s && *s != '/' && *s != ':' && b < e; - *b++ = *s++) - continue; - *b = EOS; - if (gethdir(gstart)) { - blkfree(nv); - if (*gstart) - stderror(ERR_UNKUSER, vis_str(gstart)); - else - stderror(ERR_NOHOME); - } - b = &gstart[Strlen(gstart)]; - while (*s) - *b++ = *s++; - *b = EOS; - --u; - xfree((ptr_t) u); - return (Strsave(gstart)); -} - -static int -globbrace(Char *s, Char *p, Char ***bl) -{ - Char gbuf[MAXPATHLEN]; - Char *lm, *pe, *pl, *pm, **nv, **vl; - int i, len, size; - - size = GLOBSPACE; - nv = vl = xmalloc(sizeof(Char *) * (size_t)size); - *vl = NULL; - len = 0; - /* copy part up to the brace */ - for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++) - continue; - - /* check for balanced braces */ - for (i = 0, pe = ++p; *pe; pe++) - if (*pe == LBRK) { - /* Ignore everything between [] */ - for (++pe; *pe != RBRK && *pe != EOS; pe++) - continue; - if (*pe == EOS) { - blkfree(nv); - return (-RBRK); - } - } - else if (*pe == LBRC) - i++; - else if (*pe == RBRC) { - if (i == 0) - break; - i--; - } - - if (i != 0 || *pe == '\0') { - blkfree(nv); - return (-RBRC); - } - - for (i = 0, pl = pm = p; pm <= pe; pm++) - switch (*pm) { - case LBRK: - for (++pm; *pm != RBRK && *pm != EOS; pm++) - continue; - if (*pm == EOS) { - *vl = NULL; - blkfree(nv); - return (-RBRK); - } - break; - case LBRC: - i++; - break; - case RBRC: - if (i) { - i--; - break; - } - /* FALLTHROUGH */ - case ',': - if (i && *pm == ',') - break; - else { - Char savec = *pm; - - *pm = EOS; - (void)Strcpy(lm, pl); - (void)Strcat(gbuf, pe + 1); - *pm = savec; - *vl++ = Strsave(gbuf); - len++; - pl = pm + 1; - if (vl == &nv[size]) { - size += GLOBSPACE; - nv = (Char **)xrealloc((ptr_t) nv, - (size_t)size * sizeof(Char *)); - vl = &nv[size - GLOBSPACE]; - } - } - break; - default: - break; - } - *vl = NULL; - *bl = nv; - return (len); -} - -static void -expbrace(Char ***nvp, Char ***elp, size_t size) -{ - Char **ex, **nv, *s, **vl; - - vl = nv = *nvp; - if (elp != NULL) - ex = *elp; - else - for (ex = vl; *ex; ex++) - continue; - - for (s = *vl; s; s = *++vl) { - Char *b, **bp, **vp; - - /* leave {} untouched for find */ - if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0'))) - continue; - if ((b = Strchr(s, '{')) != NULL) { - Char **bl; - int len; - - if ((len = globbrace(s, b, &bl)) < 0) { - xfree((ptr_t)nv); - stderror(ERR_MISSING, -len); - } - xfree((ptr_t) s); - if (len == 1) { - *vl-- = *bl; - xfree((ptr_t) bl); - continue; - } - len = blklen(bl); - if (&ex[len] >= &nv[size]) { - ptrdiff_t l, e; - - l = &ex[len] - &nv[size]; - size += (size_t)(GLOBSPACE > l ? GLOBSPACE : l); - l = vl - nv; - e = ex - nv; - nv = (Char **)xrealloc((ptr_t)nv, - (size_t)size * sizeof(Char *)); - vl = nv + l; - ex = nv + e; - } - vp = vl--; - *vp = *bl; - len--; - for (bp = ex; bp != vp; bp--) - bp[len] = *bp; - ex += len; - vp++; - for (bp = bl + 1; *bp; *vp++ = *bp++) - continue; - xfree((ptr_t)bl); - } - - } - if (elp != NULL) - *elp = ex; - *nvp = nv; -} - -static Char ** -globexpand(Char **v) -{ - Char **ex, **nv, *s, **vl; - size_t size; - - size = GLOBSPACE; - nv = vl = xmalloc(sizeof(Char *) * size); - *vl = NULL; - - /* - * Step 1: expand backquotes. - */ - while ((s = *v++) != NULL) { - if (Strchr(s, '`')) { - int i; - - (void) dobackp(s, 0); - for (i = 0; i < pargc; i++) { - *vl++ = pargv[i]; - if (vl == &nv[size]) { - size += GLOBSPACE; - nv = (Char **)xrealloc((ptr_t) nv, - (size_t)size * sizeof(Char *)); - vl = &nv[size - GLOBSPACE]; - } - } - xfree((ptr_t)pargv); - pargv = NULL; - } - else { - *vl++ = Strsave(s); - if (vl == &nv[size]) { - size += GLOBSPACE; - nv = (Char **)xrealloc((ptr_t)nv, - size * sizeof(Char *)); - vl = &nv[size - GLOBSPACE]; - } - } - } - *vl = NULL; - - if (noglob) - return (nv); - - /* - * Step 2: expand braces - */ - ex = vl; - expbrace(&nv, &ex, size); - - /* - * Step 3: expand ~ - */ - vl = nv; - for (s = *vl; s; s = *++vl) - if (*s == '~') - *vl = globtilde(nv, s); - vl = nv; - return (vl); -} - -static Char * -handleone(Char *str, Char **vl, int action) -{ - Char *cp, **vlp; - - vlp = vl; - switch (action) { - case G_ERROR: - setname(vis_str(str)); - blkfree(vl); - stderror(ERR_NAME | ERR_AMBIG); - /* NOTREACHED */ - case G_APPEND: - trim(vlp); - str = Strsave(*vlp++); - do { - cp = Strspl(str, STRspace); - xfree((ptr_t)str); - str = Strspl(cp, *vlp); - xfree((ptr_t)cp); - } - while (*++vlp); - blkfree(vl); - break; - case G_IGNORE: - str = Strsave(strip(*vlp)); - blkfree(vl); - break; - default: - break; - } - return (str); -} - -static Char ** -libglob(Char **vl) -{ - glob_t globv; - char *ptr; - int gflgs, magic, match, nonomatch; - - gflgs = GLOB_NOMAGIC; - magic = 0; - match = 0; - nonomatch = adrof(STRnonomatch) != 0; - - if (!vl || !vl[0]) - return (vl); - - globv.gl_offs = 0; - globv.gl_pathv = 0; - globv.gl_pathc = 0; - - if (nonomatch) - gflgs |= GLOB_NOCHECK; - - do { - ptr = short2qstr(*vl); - switch (glob(ptr, gflgs, 0, &globv)) { - case GLOB_ABORTED: - setname(vis_str(*vl)); - stderror(ERR_NAME | ERR_GLOB); - /* NOTREACHED */ - case GLOB_NOSPACE: - stderror(ERR_NOMEM); - /* NOTREACHED */ - default: - break; - } - if (globv.gl_flags & GLOB_MAGCHAR) { - match |= (globv.gl_matchc != 0); - magic = 1; - } - gflgs |= GLOB_APPEND; - } - while (*++vl); - vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ? - NULL : blk2short(globv.gl_pathv); - globfree(&globv); - return (vl); -} - -Char * -globone(Char *str, int action) -{ - Char *v[2], **vl, **vo; - int gflg; - - noglob = adrof(STRnoglob) != 0; - gflag = 0; - v[0] = str; - v[1] = 0; - tglob(v); - gflg = gflag; - if (gflg == G_NONE) - return (strip(Strsave(str))); - - if (gflg & G_CSH) { - /* - * Expand back-quote, tilde and brace - */ - vo = globexpand(v); - if (noglob || (gflg & G_GLOB) == 0) { - if (vo[0] == NULL) { - xfree((ptr_t)vo); - return (Strsave(STRNULL)); - } - if (vo[1] != NULL) - return (handleone(str, vo, action)); - else { - str = strip(vo[0]); - xfree((ptr_t) vo); - return (str); - } - } - } - else if (noglob || (gflg & G_GLOB) == 0) - return (strip(Strsave(str))); - else - vo = v; - - vl = libglob(vo); - if ((gflg & G_CSH) && vl != vo) - blkfree(vo); - if (vl == NULL) { - setname(vis_str(str)); - stderror(ERR_NAME | ERR_NOMATCH); - } - if (vl[0] == NULL) { - xfree((ptr_t)vl); - return (Strsave(STRNULL)); - } - if (vl[1] != NULL) - return (handleone(str, vl, action)); - else { - str = strip(*vl); - xfree((ptr_t)vl); - return (str); - } -} - -Char ** -globall(Char **v) -{ - Char **vl, **vo; - int gflg; - - gflg = gflag; - if (!v || !v[0]) { - gargv = saveblk(v); - gargc = blklen(gargv); - return (gargv); - } - - noglob = adrof(STRnoglob) != 0; - - if (gflg & G_CSH) - /* - * Expand back-quote, tilde and brace - */ - vl = vo = globexpand(v); - else - vl = vo = saveblk(v); - - if (!noglob && (gflg & G_GLOB)) { - vl = libglob(vo); - if ((gflg & G_CSH) && vl != vo) - blkfree(vo); - } - else - trim(vl); - - gargc = vl ? blklen(vl) : 0; - return (gargv = vl); -} - -void -ginit(void) -{ - gargsiz = GLOBSPACE; - gargv = xmalloc(sizeof(Char *) * (size_t)gargsiz); - gargv[0] = 0; - gargc = 0; -} - -void -rscan(Char **t, void (*f)(int)) -{ - Char *p; - - while ((p = *t++) != NULL) - while (*p) - (*f) (*p++); -} - -void -trim(Char **t) -{ - Char *p; - - while ((p = *t++) != NULL) - while (*p) - *p++ &= TRIM; -} - -void -tglob(Char **t) -{ - Char *p, c; - - while ((p = *t++) != NULL) { - if (*p == '~' || *p == '=') - gflag |= G_CSH; - else if (*p == '{' && - (p[1] == '\0' || (p[1] == '}' && p[2] == '\0'))) - continue; - while ((c = *p++) != '\0') { - /* - * eat everything inside the matching backquotes - */ - if (c == '`') { - gflag |= G_CSH; - while (*p && *p != '`') - if (*p++ == '\\') { - if (*p) /* Quoted chars */ - p++; - else - break; - } - if (*p) /* The matching ` */ - p++; - else - break; - } - else if (c == '{') - gflag |= G_CSH; - else if (isglob(c)) - gflag |= G_GLOB; - } - } -} - -/* - * Command substitute cp. If literal, then this is a substitution from a - * << redirection, and so we should not crunch blanks and tabs, separating - * words only at newlines. - */ -Char ** -dobackp(Char *cp, int literal) -{ - Char word[MAXPATHLEN], *ep, *lp, *rp; - - if (pargv) { -#ifdef notdef - abort(); -#endif - blkfree(pargv); - } - pargsiz = GLOBSPACE; - pargv = xmalloc(sizeof(Char *) * (size_t)pargsiz); - pargv[0] = NULL; - pargcp = pargs = word; - pargc = 0; - pnleft = MAXPATHLEN - 4; - for (;;) { - for (lp = cp; *lp != '`'; lp++) { - if (*lp == 0) { - if (pargcp != pargs) - pword(); - return (pargv); - } - psave(*lp); - } - lp++; - for (rp = lp; *rp && *rp != '`'; rp++) - if (*rp == '\\') { - rp++; - if (!*rp) - goto oops; - } - if (!*rp) { - oops: - stderror(ERR_UNMATCHED, '`'); - } - ep = Strsave(lp); - ep[rp - lp] = 0; - backeval(ep, literal); - cp = rp + 1; - } -} - -static void -backeval(Char *cp, int literal) -{ - struct command faket; - char tibuf[BUFSIZE]; - Char ibuf[BUFSIZE], *fakecom[2], *ip; - int pvec[2], c, quoted; - ssize_t icnt; - int hadnl; - - hadnl = 0; - icnt = 0; - quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0; - faket.t_dtyp = NODE_COMMAND; - faket.t_dflg = 0; - faket.t_dlef = 0; - faket.t_drit = 0; - faket.t_dspr = 0; - faket.t_dcom = fakecom; - fakecom[0] = STRfakecom1; - fakecom[1] = 0; - - /* - * We do the psave job to temporarily change the current job so that the - * following fork is considered a separate job. This is so that when - * backquotes are used in a builtin function that calls glob the "current - * job" is not corrupted. We only need one level of pushed jobs as long as - * we are sure to fork here. - */ - psavejob(); - - /* - * It would be nicer if we could integrate this redirection more with the - * routines in sh.sem.c by doing a fake execute on a builtin function that - * was piped out. - */ - mypipe(pvec); - if (pfork(&faket, -1) == 0) { - struct wordent fparaml; - struct command *t; - - (void)close(pvec[0]); - (void)dmove(pvec[1], 1); - (void)dmove(SHERR, 2); - initdesc(); - /* - * Bugfix for nested backquotes by Michael Greim , - * posted to comp.bugs.4bsd 12 Sep. 1989. - */ - if (pargv) /* mg, 21.dec.88 */ - blkfree(pargv), pargv = 0, pargsiz = 0; - /* mg, 21.dec.88 */ - arginp = cp; - for (arginp = cp; *cp; cp++) { - *cp &= TRIM; - if (*cp == '\n' || *cp == '\r') - *cp = ';'; - } - - /* - * In the child ``forget'' everything about current aliases or - * eval vectors. - */ - alvec = NULL; - evalvec = NULL; - alvecp = NULL; - evalp = NULL; - (void) lex(&fparaml); - if (seterr) - stderror(ERR_OLD); - alias(&fparaml); - t = syntax(fparaml.next, &fparaml, 0); - if (seterr) - stderror(ERR_OLD); - if (t) - t->t_dflg |= F_NOFORK; - (void)signal(SIGTSTP, SIG_IGN); - (void)signal(SIGTTIN, SIG_IGN); - (void)signal(SIGTTOU, SIG_IGN); - execute(t, -1, NULL, NULL); - exitstat(); - } - xfree((ptr_t)cp); - (void)close(pvec[1]); - c = 0; - ip = NULL; - do { - int cnt; - - cnt = 0; - - for (;;) { - if (icnt == 0) { - int i; - - ip = ibuf; - do - icnt = read(pvec[0], tibuf, BUFSIZE); - while (icnt == -1 && errno == EINTR); - if (icnt <= 0) { - c = -1; - break; - } - for (i = 0; i < icnt; i++) - ip[i] = (unsigned char) tibuf[i]; - } - if (hadnl) - break; - --icnt; - c = (*ip++ & TRIM); - if (c == 0) - break; - if (c == '\n') { - /* - * Continue around the loop one more time, so that we can eat - * the last newline without terminating this word. - */ - hadnl = 1; - continue; - } - if (!quoted && (c == ' ' || c == '\t')) - break; - cnt++; - psave(c | quoted); - } - /* - * Unless at end-of-file, we will form a new word here if there were - * characters in the word, or in any case when we take text literally. - * If we didn't make empty words here when literal was set then we - * would lose blank lines. - */ - if (c != -1 && (cnt || literal)) - pword(); - hadnl = 0; - } while (c >= 0); - (void)close(pvec[0]); - pwait(); - prestjob(); -} - -static void -psave(int c) -{ - if (--pnleft <= 0) - stderror(ERR_WTOOLONG); - *pargcp++ = (Char)c; -} - -static void -pword(void) -{ - psave(0); - if (pargc == pargsiz - 1) { - pargsiz += GLOBSPACE; - pargv = (Char **)xrealloc((ptr_t)pargv, - (size_t)pargsiz * sizeof(Char *)); - } - pargv[pargc++] = Strsave(pargs); - pargv[pargc] = NULL; - pargcp = pargs; - pnleft = MAXPATHLEN - 4; -} - -int -Gmatch(Char *string, Char *pattern) -{ - Char **blk, **p; - int gpol, gres; - - gpol = 1; - gres = 0; - - if (*pattern == '^') { - gpol = 0; - pattern++; - } - - blk = xmalloc(GLOBSPACE * sizeof(Char *)); - blk[0] = Strsave(pattern); - blk[1] = NULL; - - expbrace(&blk, NULL, GLOBSPACE); - - for (p = blk; *p; p++) - gres |= pmatch(string, *p); - - blkfree(blk); - return(gres == gpol); -} - -static int -pmatch(Char *string, Char *pattern) -{ - int match, negate_range; - Char patternc, rangec, stringc; - - for (;; ++string) { - stringc = *string & TRIM; - patternc = *pattern++; - switch (patternc) { - case 0: - return (stringc == 0); - case '?': - if (stringc == 0) - return (0); - break; - case '*': - if (!*pattern) - return (1); - while (*string) - if (Gmatch(string++, pattern)) - return (1); - return (0); - case '[': - match = 0; - if ((negate_range = (*pattern == '^')) != 0) - pattern++; - while ((rangec = *pattern++) != '\0') { - if (rangec == ']') - break; - if (match) - continue; - if (rangec == '-' && *(pattern-2) != '[' && *pattern != ']') { - match = (stringc <= (*pattern & TRIM) && - (*(pattern-2) & TRIM) <= stringc); - pattern++; - } - else - match = (stringc == (rangec & TRIM)); - } - if (rangec == 0) - stderror(ERR_NAME | ERR_MISSING, ']'); - if (match == negate_range) - return (0); - break; - default: - if ((patternc & TRIM) != stringc) - return (0); - break; - - } - } -} - -void -Gcat(Char *s1, Char *s2) -{ - Char *p, *q; - ptrdiff_t n; - - for (p = s1; *p++;) - continue; - for (q = s2; *q++;) - continue; - n = (p - s1) + (q - s2) - 1; - if (++gargc >= gargsiz) { - gargsiz += GLOBSPACE; - gargv = (Char **)xrealloc((ptr_t)gargv, - (size_t)gargsiz * sizeof(Char *)); - } - gargv[gargc] = 0; - p = gargv[gargc - 1] = xmalloc((size_t)n * sizeof(Char)); - for (q = s1; (*p++ = *q++) != '\0';) - continue; - for (p--, q = s2; (*p++ = *q++) != '\0';) - continue; -} - -#ifdef FILEC -int -sortscmp(const ptr_t a, const ptr_t b) -{ -#if defined(NLS) && !defined(NOSTRCOLL) - char buf[2048]; -#endif - - if (!a) /* check for NULL */ - return (b ? 1 : 0); - if (!b) - return (-1); - - if (!*(Char **)a) /* check for NULL */ - return (*(Char **)b ? 1 : 0); - if (!*(Char **)b) - return (-1); - -#if defined(NLS) && !defined(NOSTRCOLL) - (void)strcpy(buf, short2str(*(Char **)a)); - return ((int)strcoll(buf, short2str(*(Char **)b))); -#else - return ((int)Strcmp(*(Char **)a, *(Char **)b)); -#endif -} -#endif /* FILEC */ diff --git a/bin/csh/hist.c b/bin/csh/hist.c deleted file mode 100644 index 1c5bf9d21..000000000 --- a/bin/csh/hist.c +++ /dev/null @@ -1,207 +0,0 @@ -/* $NetBSD: hist.c,v 1.20 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: hist.c,v 1.20 2013/07/16 17:47:43 christos Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include - -#include "csh.h" -#include "extern.h" - -static void hfree(struct Hist *); -static void dohist1(struct Hist *, int *, int, int); -static void phist(struct Hist *, int); - -void -savehist(struct wordent *sp) -{ - struct Hist *hp, *np; - Char *cp; - int histlen; - - histlen = 0; - - /* throw away null lines */ - if (sp->next->word[0] == '\n') - return; - cp = value(STRhistory); - if (*cp) { - Char *p = cp; - - while (*p) { - if (!Isdigit(*p)) { - histlen = 0; - break; - } - histlen = histlen * 10 + *p++ - '0'; - } - } - for (hp = &Histlist; (np = hp->Hnext) != NULL;) - if (eventno - np->Href >= histlen || histlen == 0) - hp->Hnext = np->Hnext, hfree(np); - else - hp = np; - (void) enthist(++eventno, sp, 1); -} - -#ifdef EDIT -void -loadhist(struct Hist *hp) { - char *h = NULL; - - if (hi == NULL || hp == NULL) - return; - loadhist(hp->Hnext); - if (sprlex(&h, &hp->Hlex) != -1) { - HistEvent ev; - history(hi, &ev, H_ENTER, h); - } -} -#endif - -struct Hist * -enthist(int event, struct wordent *lp, int docopy) -{ - struct Hist *np; - -#ifdef EDIT - if (hi) { - char *h = NULL; - if (sprlex(&h, lp) != -1) { - HistEvent ev; - history(hi, &ev, H_ENTER, h); - } - } -#endif - np = xmalloc(sizeof(*np)); - np->Hnum = np->Href = event; - if (docopy) { - copylex(&np->Hlex, lp); - } - else { - np->Hlex.next = lp->next; - lp->next->prev = &np->Hlex; - np->Hlex.prev = lp->prev; - lp->prev->next = &np->Hlex; - } - np->Hnext = Histlist.Hnext; - Histlist.Hnext = np; - return (np); -} - -static void -hfree(struct Hist *hp) -{ - freelex(&hp->Hlex); - xfree((ptr_t) hp); -} - -void -/*ARGSUSED*/ -dohist(Char **v, struct command *t) -{ - sigset_t nsigset; - int hflg, n, rflg; - - hflg = 0; - rflg = 0; - - if (getn(value(STRhistory)) == 0) - return; - if (setintr) { - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGINT); - (void)sigprocmask(SIG_UNBLOCK, &nsigset, NULL); - } - while (*++v && **v == '-') { - Char *vp = *v; - - while (*++vp) - switch (*vp) { - case 'h': - hflg++; - break; - case 'r': - rflg++; - break; - case '-': /* ignore multiple '-'s */ - break; - default: - stderror(ERR_HISTUS); - /* NOTREACHED */ - } - } - if (*v) - n = getn(*v); - else { - n = getn(value(STRhistory)); - } - dohist1(Histlist.Hnext, &n, rflg, hflg); -} - -static void -dohist1(struct Hist *hp, int *np, int rflg, int hflg) -{ - int print; - - print = (*np) > 0; - - for (; hp != 0; hp = hp->Hnext) { - (*np)--; - hp->Href++; - if (rflg == 0) { - dohist1(hp->Hnext, np, rflg, hflg); - if (print) - phist(hp, hflg); - return; - } - if (*np >= 0) - phist(hp, hflg); - } -} - -static void -phist(struct Hist *hp, int hflg) -{ - if (hflg == 0) - (void)fprintf(cshout, "%6d\t", hp->Hnum); - prlex(cshout, &hp->Hlex); -} diff --git a/bin/csh/init.c b/bin/csh/init.c deleted file mode 100644 index 06a34270b..000000000 --- a/bin/csh/init.c +++ /dev/null @@ -1,131 +0,0 @@ -/* $NetBSD: init.c,v 1.11 2013/01/22 19:28:00 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)init.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: init.c,v 1.11 2013/01/22 19:28:00 christos Exp $"); -#endif -#endif /* not lint */ - -#include - -#include "csh.h" -#include "extern.h" - -#define INF 1000 - -struct biltins bfunc[] = -{ - { "@", dolet, 0, INF }, - { "alias", doalias, 0, INF }, - { "bg", dobg, 0, INF }, - { "break", dobreak, 0, 0 }, - { "breaksw", doswbrk, 0, 0 }, - { "case", dozip, 0, 1 }, - { "cd", dochngd, 0, INF }, - { "chdir", dochngd, 0, INF }, - { "continue", docontin, 0, 0 }, - { "default", dozip, 0, 0 }, - { "dirs", dodirs, 0, INF }, - { "echo", doecho, 0, INF }, - { "else", doelse, 0, INF }, - { "end", doend, 0, 0 }, - { "endif", dozip, 0, 0 }, - { "endsw", dozip, 0, 0 }, - { "eval", doeval, 0, INF }, - { "exec", execash, 1, INF }, - { "exit", doexit, 0, INF }, - { "fg", dofg, 0, INF }, - { "foreach", doforeach, 3, INF }, - { "glob", doglob, 0, INF }, - { "goto", dogoto, 1, 1 }, - { "hashstat", hashstat, 0, 0 }, - { "history", dohist, 0, 2 }, - { "if", doif, 1, INF }, - { "jobs", dojobs, 0, 1 }, - { "kill", dokill, 1, INF }, - { "limit", dolimit, 0, 3 }, - { "linedit", doecho, 0, INF }, - { "login", dologin, 0, 1 }, - { "logout", dologout, 0, 0 }, - { "nice", donice, 0, INF }, - { "nohup", donohup, 0, INF }, - { "notify", donotify, 0, INF }, - { "onintr", doonintr, 0, 2 }, - { "popd", dopopd, 0, INF }, - { "printf", doprintf, 1, INF }, - { "pushd", dopushd, 0, INF }, - { "rehash", dohash, 0, 0 }, - { "repeat", dorepeat, 2, INF }, - { "set", doset, 0, INF }, - { "setenv", dosetenv, 0, 2 }, - { "shift", shift, 0, 1 }, - { "source", dosource, 1, 2 }, - { "stop", dostop, 1, INF }, - { "suspend", dosuspend, 0, 0 }, - { "switch", doswitch, 1, INF }, - { "time", dotime, 0, INF }, - { "umask", doumask, 0, 1 }, - { "unalias", unalias, 1, INF }, - { "unhash", dounhash, 0, 0 }, - { "unlimit", dounlimit, 0, INF }, - { "unset", unset, 1, INF }, - { "unsetenv", dounsetenv, 1, INF }, - { "wait", dowait, 0, 0 }, - { "which", dowhich, 1, INF }, - { "while", dowhile, 1, INF } -}; -int nbfunc = sizeof(bfunc) / sizeof(*bfunc); - -struct srch srchn[] = -{ - { "@", T_LET }, - { "break", T_BREAK }, - { "breaksw", T_BRKSW }, - { "case", T_CASE }, - { "default", T_DEFAULT }, - { "else", T_ELSE }, - { "end", T_END }, - { "endif", T_ENDIF }, - { "endsw", T_ENDSW }, - { "exit", T_EXIT }, - { "foreach", T_FOREACH }, - { "goto", T_GOTO }, - { "if", T_IF }, - { "label", T_LABEL }, - { "set", T_SET }, - { "switch", T_SWITCH }, - { "while", T_WHILE } -}; -int nsrchn = sizeof(srchn) / sizeof(*srchn); diff --git a/bin/csh/lex.c b/bin/csh/lex.c deleted file mode 100644 index 8c1bca818..000000000 --- a/bin/csh/lex.c +++ /dev/null @@ -1,1631 +0,0 @@ -/* $NetBSD: lex.c,v 1.31 2013/08/06 05:42:43 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)lex.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: lex.c,v 1.31 2013/08/06 05:42:43 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "csh.h" -#include "extern.h" - -/* - * These lexical routines read input and form lists of words. - * There is some involved processing here, because of the complications - * of input buffering, and especially because of history substitution. - */ - -static Char *word(void); -static int getC1(int); -static void getdol(void); -static void getexcl(int); -static struct Hist *findev(Char *, int); -static void setexclp(Char *); -static int bgetc(void); -static void bfree(void); -static struct wordent *gethent(int); -static int matchs(Char *, Char *); -static int getsel(int *, int *, int); -static struct wordent *getsub(struct wordent *); -static Char *subword(Char *, int, int *); -static struct wordent *dosub(int, struct wordent *, int); - -/* - * Peekc is a peek character for getC, peekread for readc. - * There is a subtlety here in many places... history routines - * will read ahead and then insert stuff into the input stream. - * If they push back a character then they must push it behind - * the text substituted by the history substitution. On the other - * hand in several places we need 2 peek characters. To make this - * all work, the history routines read with getC, and make use both - * of ungetC and unreadc. The key observation is that the state - * of getC at the call of a history reference is such that calls - * to getC from the history routines will always yield calls of - * readc, unless this peeking is involved. That is to say that during - * getexcl the variables lap, exclp, and exclnxt are all zero. - * - * Getdol invokes history substitution, hence the extra peek, peekd, - * which it can ungetD to be before history substitutions. - */ -static int peekc = 0, peekd = 0; -static int peekread = 0; - -/* (Tail of) current word from ! subst */ -static Char *exclp = NULL; - -/* The rest of the ! subst words */ -static struct wordent *exclnxt = NULL; - -/* Count of remaining words in ! subst */ -static int exclc = 0; - -/* "Globp" for alias resubstitution */ -Char **alvec, *alvecp; -int aret = F_SEEK; - -/* - * Labuf implements a general buffer for lookahead during lexical operations. - * Text which is to be placed in the input stream can be stuck here. - * We stick parsed ahead $ constructs during initial input, - * process id's from `$$', and modified variable values (from qualifiers - * during expansion in sh.dol.c) here. - */ -static Char labuf[BUFSIZE]; - -/* - * Lex returns to its caller not only a wordlist (as a "var" parameter) - * but also whether a history substitution occurred. This is used in - * the main (process) routine to determine whether to echo, and also - * when called by the alias routine to determine whether to keep the - * argument list. - */ -static int hadhist = 0; - -/* - * Avoid alias expansion recursion via \!# - */ -int hleft; - -static int getCtmp; - -#define getC(f) ((getCtmp = peekc) ? (peekc = 0, getCtmp) : getC1(f)) -#define ungetC(c) peekc = c -#define ungetD(c) peekd = c - -int -lex(struct wordent *hp) -{ - struct wordent *wdp; - int c; - - btell(&lineloc); - hp->next = hp->prev = hp; - hp->word = STRNULL; - hadhist = 0; - do - c = readc(0); - while (c == ' ' || c == '\t'); - if (c == HISTSUB && intty) - /* ^lef^rit from tty is short !:s^lef^rit */ - getexcl(c); - else - unreadc(c); - wdp = hp; - /* - * The following loop is written so that the links needed by freelex will - * be ready and rarin to go even if it is interrupted. - */ - do { - struct wordent *new; - - new = xmalloc(sizeof(*wdp)); - new->word = 0; - new->prev = wdp; - new->next = hp; - wdp->next = new; - wdp = new; - wdp->word = word(); - } while (wdp->word[0] != '\n'); - hp->prev = wdp; - return (hadhist); -} - -void -prlex(FILE *fp, struct wordent *sp0) -{ - struct wordent *sp; - - sp = sp0->next; - for (;;) { - (void)fprintf(fp, "%s", vis_str(sp->word)); - sp = sp->next; - if (sp == sp0) - break; - if (sp->word[0] != '\n') - (void) fputc(' ', fp); - } -} - -#ifdef EDIT -int -sprlex(char **s, struct wordent *sp0) -{ - struct wordent *sp; - - sp = sp0->next; - char *os = *s; - for (;;) { - char *w = vis_str(sp->word); - if (os == NULL) { - if (asprintf(s, "%s", w) < 0) - return -1; - os = *s; - } else if (*os != '\n') { - if (asprintf(s, "%s %s", os, w) < 0) { - free(os); - return 1; - } - free(os); - os = *s; - } - sp = sp->next; - if (sp == sp0) - break; - } - return 0; -} -#endif - -void -copylex(struct wordent *hp, struct wordent *fp) -{ - struct wordent *wdp; - - wdp = hp; - fp = fp->next; - do { - struct wordent *new; - - new = xmalloc(sizeof(*wdp)); - new->prev = wdp; - new->next = hp; - wdp->next = new; - wdp = new; - wdp->word = Strsave(fp->word); - fp = fp->next; - } while (wdp->word[0] != '\n'); - hp->prev = wdp; -} - -void -freelex(struct wordent *vp) -{ - struct wordent *fp; - - while (vp->next != vp) { - fp = vp->next; - vp->next = fp->next; - xfree((ptr_t) fp->word); - xfree((ptr_t) fp); - } - vp->prev = vp; -} - -static Char * -word(void) -{ - Char wbuf[BUFSIZE], *wp; - int i, c, c1; - int dolflg; - - wp = wbuf; - i = BUFSIZE - 4; -loop: - while ((c = getC(DOALL)) == ' ' || c == '\t') - continue; - if (cmap(c, _META | _ESC)) - switch (c) { - case '&': - case '|': - case '<': - case '>': - *wp++ = (Char)c; - c1 = getC(DOALL); - if (c1 == c) - *wp++ = (Char)c1; - else - ungetC(c1); - goto ret; - - case '#': - if (intty) - break; - c = 0; - do { - c1 = c; - c = getC(0); - } while (c != '\n'); - if (c1 == '\\') - goto loop; - /* FALLTHROUGH */ - - case ';': - case '(': - case ')': - case '\n': - *wp++ = (Char)c; - goto ret; - - case '\\': - c = getC(0); - if (c == '\n') { - if (onelflg == 1) - onelflg = 2; - goto loop; - } - if (c != HIST) - *wp++ = '\\', --i; - c |= QUOTE; - break; - } - c1 = 0; - dolflg = DOALL; - for (;;) { - if (c1) { - if (c == c1) { - c1 = 0; - dolflg = DOALL; - } - else if (c == '\\') { - c = getC(0); - if (c == HIST) - c |= QUOTE; - else { - if (c == '\n') - /* - * if (c1 == '`') c = ' '; else - */ - c |= QUOTE; - ungetC(c); - c = '\\'; - } - } - else if (c == '\n') { - seterror(ERR_UNMATCHED, c1); - ungetC(c); - break; - } - } - else if (cmap(c, _META | _QF | _QB | _ESC)) { - if (c == '\\') { - c = getC(0); - if (c == '\n') { - if (onelflg == 1) - onelflg = 2; - break; - } - if (c != HIST) - *wp++ = '\\', --i; - c |= QUOTE; - } - else if (cmap(c, _QF | _QB)) { /* '"` */ - c1 = c; - dolflg = c == '"' ? DOALL : DOEXCL; - } - else if (c != '#' || !intty) { - ungetC(c); - break; - } - } - if (--i > 0) { - *wp++ = (Char)c; - c = getC(dolflg); - } - else { - seterror(ERR_WTOOLONG); - wp = &wbuf[1]; - break; - } - } -ret: - *wp = 0; - return (Strsave(wbuf)); -} - -static int -getC1(int flag) -{ - int c; - - for (;;) { - if ((c = peekc) != '\0') { - peekc = 0; - return (c); - } - if (lap) { - if ((c = *lap++) == 0) - lap = 0; - else { - if (cmap(c, _META | _QF | _QB)) - c |= QUOTE; - return (c); - } - } - if ((c = peekd) != '\0') { - peekd = 0; - return (c); - } - if (exclp) { - if ((c = *exclp++) != '\0') - return (c); - if (exclnxt && --exclc >= 0) { - exclnxt = exclnxt->next; - setexclp(exclnxt->word); - return (' '); - } - exclp = 0; - exclnxt = 0; - } - if (exclnxt) { - exclnxt = exclnxt->next; - if (--exclc < 0) - exclnxt = 0; - else - setexclp(exclnxt->word); - continue; - } - c = readc(0); - if (c == '$' && (flag & DODOL)) { - getdol(); - continue; - } - if (c == HIST && (flag & DOEXCL)) { - getexcl(0); - continue; - } - break; - } - return (c); -} - -static void -getdol(void) -{ - Char name[4*MAXVARLEN+1], *ep, *np; - int c, sc; - int special, toolong; - - special = 0; - np = name, *np++ = '$'; - c = sc = getC(DOEXCL); - if (any("\t \n", c)) { - ungetD(c); - ungetC('$' | QUOTE); - return; - } - if (c == '{') - *np++ = (Char)c, c = getC(DOEXCL); - if (c == '#' || c == '?') - special++, *np++ = (Char)c, c = getC(DOEXCL); - *np++ = (Char)c; - switch (c) { - case '<': - case '$': - case '!': - if (special) - seterror(ERR_SPDOLLT); - *np = 0; - addla(name); - return; - case '\n': - ungetD(c); - np--; - seterror(ERR_NEWLINE); - *np = 0; - addla(name); - return; - case '*': - if (special) - seterror(ERR_SPSTAR); - *np = 0; - addla(name); - return; - default: - toolong = 0; - if (Isdigit(c)) { -#ifdef notdef - /* let $?0 pass for now */ - if (special) { - seterror(ERR_DIGIT); - *np = 0; - addla(name); - return; - } -#endif - /* we know that np < &name[4] */ - ep = &np[MAXVARLEN]; - while ((c = getC(DOEXCL)) != '\0'){ - if (!Isdigit(c)) - break; - if (np < ep) - *np++ = (Char)c; - else - toolong = 1; - } - } - else if (letter(c)) { - /* we know that np < &name[4] */ - ep = &np[MAXVARLEN]; - toolong = 0; - while ((c = getC(DOEXCL)) != '\0') { - /* Bugfix for ${v123x} from Chris Torek, DAS DEC-90. */ - if (!letter(c) && !Isdigit(c)) - break; - if (np < ep) - *np++ = (Char)c; - else - toolong = 1; - } - } - else { - *np = 0; - seterror(ERR_VARILL); - addla(name); - return; - } - if (toolong) { - seterror(ERR_VARTOOLONG); - *np = 0; - addla(name); - return; - } - break; - } - if (c == '[') { - *np++ = (Char)c; - /* - * Name up to here is a max of MAXVARLEN + 8. - */ - ep = &np[2 * MAXVARLEN + 8]; - do { - /* - * Michael Greim: Allow $ expansion to take place in selector - * expressions. (limits the number of characters returned) - */ - c = getC(DOEXCL | DODOL); - if (c == '\n') { - ungetD(c); - np--; - seterror(ERR_NLINDEX); - *np = 0; - addla(name); - return; - } - if (np < ep) - *np++ = (Char)c; - } while (c != ']'); - *np = '\0'; - if (np >= ep) { - seterror(ERR_SELOVFL); - addla(name); - return; - } - c = getC(DOEXCL); - } - /* - * Name up to here is a max of 2 * MAXVARLEN + 8. - */ - if (c == ':') { - /* - * if the :g modifier is followed by a newline, then error right away! - * -strike - */ - int amodflag, gmodflag; - - amodflag = 0; - gmodflag = 0; - do { - *np++ = (Char)c, c = getC(DOEXCL); - if (c == 'g' || c == 'a') { - if (c == 'g') - gmodflag++; - else - amodflag++; - *np++ = (Char)c; c = getC(DOEXCL); - } - if ((c == 'g' && !gmodflag) || (c == 'a' && !amodflag)) { - if (c == 'g') - gmodflag++; - else - amodflag++; - *np++ = (Char)c, c = getC(DOEXCL); - } - *np++ = (Char)c; - /* scan s// [eichin:19910926.0512EST] */ - if (c == 's') { - int delimcnt = 2; - int delim = getC(0); - *np++ = (Char)delim; - - if (!delim || letter(delim) - || Isdigit(delim) || any(" \t\n", delim)) { - seterror(ERR_BADSUBST); - break; - } - while ((c = getC(0)) != -1) { - *np++ = (Char)c; - if(c == delim) delimcnt--; - if(!delimcnt) break; - } - if(delimcnt) { - seterror(ERR_BADSUBST); - break; - } - c = 's'; - } - if (!any("htrqxes", c)) { - if ((amodflag || gmodflag) && c == '\n') - stderror(ERR_VARSYN); /* strike */ - seterror(ERR_VARMOD, c); - *np = 0; - addla(name); - return; - } - } - while ((c = getC(DOEXCL)) == ':'); - ungetD(c); - } - else - ungetD(c); - if (sc == '{') { - c = getC(DOEXCL); - if (c != '}') { - ungetD(c); - seterror(ERR_MISSING, '}'); - *np = 0; - addla(name); - return; - } - *np++ = (Char)c; - } - *np = 0; - addla(name); - return; -} - -void -addla(Char *cp) -{ - Char buf[BUFSIZE]; - - if (Strlen(cp) + (lap ? Strlen(lap) : 0) >= - (sizeof(labuf) - 4) / sizeof(Char)) { - seterror(ERR_EXPOVFL); - return; - } - if (lap) - (void)Strcpy(buf, lap); - (void)Strcpy(labuf, cp); - if (lap) - (void)Strcat(labuf, buf); - lap = labuf; -} - -static Char lhsb[32]; -static Char slhs[32]; -static Char rhsb[64]; -static int quesarg; - -static void -getexcl(int sc) -{ - struct wordent *hp, *ip; - int c, dol, left, right; - - if (sc == 0) { - sc = getC(0); - if (sc != '{') { - ungetC(sc); - sc = 0; - } - } - quesarg = -1; - lastev = eventno; - hp = gethent(sc); - if (hp == 0) - return; - hadhist = 1; - dol = 0; - if (hp == alhistp) - for (ip = hp->next->next; ip != alhistt; ip = ip->next) - dol++; - else - for (ip = hp->next->next; ip != hp->prev; ip = ip->next) - dol++; - left = 0, right = dol; - if (sc == HISTSUB) { - ungetC('s'), unreadc(HISTSUB), c = ':'; - goto subst; - } - c = getC(0); - if (!any(":^$*-%", c)) - goto subst; - left = right = -1; - if (c == ':') { - c = getC(0); - unreadc(c); - if (letter(c) || c == '&') { - c = ':'; - left = 0, right = dol; - goto subst; - } - } - else - ungetC(c); - if (!getsel(&left, &right, dol)) - return; - c = getC(0); - if (c == '*') - ungetC(c), c = '-'; - if (c == '-') { - if (!getsel(&left, &right, dol)) - return; - c = getC(0); - } -subst: - exclc = right - left + 1; - while (--left >= 0) - hp = hp->next; - if (sc == HISTSUB || c == ':') { - do { - hp = getsub(hp); - c = getC(0); - } while (c == ':'); - } - unreadc(c); - if (sc == '{') { - c = getC(0); - if (c != '}') - seterror(ERR_BADBANG); - } - exclnxt = hp; -} - -static struct wordent * -getsub(struct wordent *en) -{ - Char orhsb[sizeof(rhsb) / sizeof(Char)]; - Char *cp; - int c, delim, sc; - int global; - - do { - exclnxt = 0; - global = 0; - sc = c = getC(0); - if (c == 'g' || c == 'a') { - global |= (c == 'g') ? 1 : 2; - sc = c = getC(0); - } - if (((c =='g') && !(global & 1)) || ((c == 'a') && !(global & 2))) { - global |= (c == 'g') ? 1 : 2; - sc = c = getC(0); - } - - switch (c) { - case 'p': - justpr++; - return (en); - case 'x': - case 'q': - global |= 1; - /* FALLTHROUGH */ - case 'h': - case 'r': - case 't': - case 'e': - break; - case '&': - if (slhs[0] == 0) { - seterror(ERR_NOSUBST); - return (en); - } - (void) Strcpy(lhsb, slhs); - break; -#ifdef notdef - case '~': - if (lhsb[0] == 0) - goto badlhs; - break; -#endif - case 's': - delim = getC(0); - if (letter(delim) || Isdigit(delim) || any(" \t\n", delim)) { - unreadc(delim); - lhsb[0] = 0; - seterror(ERR_BADSUBST); - return (en); - } - cp = lhsb; - for (;;) { - c = getC(0); - if (c == '\n') { - unreadc(c); - break; - } - if (c == delim) - break; - if (cp > &lhsb[sizeof(lhsb) / sizeof(Char) - 2]) { - lhsb[0] = 0; - seterror(ERR_BADSUBST); - return (en); - } - if (c == '\\') { - c = getC(0); - if (c != delim && c != '\\') - *cp++ = '\\'; - } - *cp++ = (Char)c; - } - if (cp != lhsb) - *cp++ = 0; - else if (lhsb[0] == 0) { - seterror(ERR_LHS); - return (en); - } - cp = rhsb; - (void)Strcpy(orhsb, cp); - for (;;) { - c = getC(0); - if (c == '\n') { - unreadc(c); - break; - } - if (c == delim) - break; -#ifdef notdef - if (c == '~') { - if (&cp[Strlen(orhsb)] > &rhsb[sizeof(rhsb) / - sizeof(Char) - 2]) - goto toorhs; - (void)Strcpy(cp, orhsb); - cp = Strend(cp); - continue; - } -#endif - if (cp > &rhsb[sizeof(rhsb) / sizeof(Char) - 2]) { - seterror(ERR_RHSLONG); - return (en); - } - if (c == '\\') { - c = getC(0); - if (c != delim /* && c != '~' */ ) - *cp++ = '\\'; - } - *cp++ = (Char)c; - } - *cp++ = 0; - break; - default: - if (c == '\n') - unreadc(c); - seterror(ERR_BADBANGMOD, c); - return (en); - } - (void)Strcpy(slhs, lhsb); - if (exclc) - en = dosub(sc, en, global); - } - while ((c = getC(0)) == ':'); - unreadc(c); - return (en); -} - -static struct wordent * -dosub(int sc, struct wordent *en, int global) -{ - struct wordent lexi, *hp, *wdp; - int i; - int didone, didsub; - - didone = 0; - didsub = 0; - i = exclc; - hp = &lexi; - - wdp = hp; - while (--i >= 0) { - struct wordent *new = (struct wordent *)xcalloc(1, sizeof *wdp); - - new->word = 0; - new->prev = wdp; - new->next = hp; - wdp->next = new; - wdp = new; - en = en->next; - if (en->word) { - Char *tword, *otword; - - if ((global & 1) || didsub == 0) { - tword = subword(en->word, sc, &didone); - if (didone) - didsub = 1; - if (global & 2) { - while (didone && tword != STRNULL) { - otword = tword; - tword = subword(otword, sc, &didone); - if (Strcmp(tword, otword) == 0) { - xfree((ptr_t) otword); - break; - } - else - xfree((ptr_t)otword); - } - } - } - else - tword = Strsave(en->word); - wdp->word = tword; - } - } - if (didsub == 0) - seterror(ERR_MODFAIL); - hp->prev = wdp; - return (&enthist(-1000, &lexi, 0)->Hlex); -} - -static Char * -subword(Char *cp, int type, int *adid) -{ - Char wbuf[BUFSIZE]; - Char *mp, *np, *wp; - ssize_t i; - - *adid = 0; - switch (type) { - case 'r': - case 'e': - case 'h': - case 't': - case 'q': - case 'x': - wp = domod(cp, type); - if (wp == 0) - return (Strsave(cp)); - *adid = 1; - return (wp); - default: - wp = wbuf; - i = BUFSIZE - 4; - for (mp = cp; *mp; mp++) - if (matchs(mp, lhsb)) { - for (np = cp; np < mp;) - *wp++ = *np++, --i; - for (np = rhsb; *np; np++) - switch (*np) { - case '\\': - if (np[1] == '&') - np++; - /* FALLTHROUGH */ - default: - if (--i < 0) { - seterror(ERR_SUBOVFL); - return (STRNULL); - } - *wp++ = *np; - continue; - case '&': - i -= (ssize_t)Strlen(lhsb); - if (i < 0) { - seterror(ERR_SUBOVFL); - return (STRNULL); - } - *wp = 0; - (void) Strcat(wp, lhsb); - wp = Strend(wp); - continue; - } - mp += Strlen(lhsb); - i -= (ssize_t)Strlen(mp); - if (i < 0) { - seterror(ERR_SUBOVFL); - return (STRNULL); - } - *wp = 0; - (void) Strcat(wp, mp); - *adid = 1; - return (Strsave(wbuf)); - } - return (Strsave(cp)); - } -} - -Char * -domod(Char *cp, int type) -{ - Char *wp, *xp; - int c; - - switch (type) { - case 'x': - case 'q': - wp = Strsave(cp); - for (xp = wp; (c = *xp) != '\0'; xp++) - if ((c != ' ' && c != '\t') || type == 'q') - *xp |= QUOTE; - return (wp); - case 'h': - case 't': - if (!any(short2str(cp), '/')) - return (type == 't' ? Strsave(cp) : 0); - wp = Strend(cp); - while (*--wp != '/') - continue; - if (type == 'h') - xp = Strsave(cp), xp[wp - cp] = 0; - else - xp = Strsave(wp + 1); - return (xp); - case 'e': - case 'r': - wp = Strend(cp); - for (wp--; wp >= cp && *wp != '/'; wp--) - if (*wp == '.') { - if (type == 'e') - xp = Strsave(wp + 1); - else - xp = Strsave(cp), xp[wp - cp] = 0; - return (xp); - } - return (Strsave(type == 'e' ? STRNULL : cp)); - default: - break; - } - return (0); -} - -static int -matchs(Char *str, Char *pat) -{ - while (*str && *pat && *str == *pat) - str++, pat++; - return (*pat == 0); -} - -static int -getsel(int *al, int *ar, int dol) -{ - int c, i; - int first; - - c = getC(0); - first = *al < 0; - - switch (c) { - case '%': - if (quesarg == -1) { - seterror(ERR_BADBANGARG); - return (0); - } - if (*al < 0) - *al = quesarg; - *ar = quesarg; - break; - case '-': - if (*al < 0) { - *al = 0; - *ar = dol - 1; - unreadc(c); - } - return (1); - case '^': - if (*al < 0) - *al = 1; - *ar = 1; - break; - case '$': - if (*al < 0) - *al = dol; - *ar = dol; - break; - case '*': - if (*al < 0) - *al = 1; - *ar = dol; - if (*ar < *al) { - *ar = 0; - *al = 1; - return (1); - } - break; - default: - if (Isdigit(c)) { - i = 0; - while (Isdigit(c)) { - i = i * 10 + c - '0'; - c = getC(0); - } - if (i < 0) - i = dol + 1; - if (*al < 0) - *al = i; - *ar = i; - } - else if (*al < 0) - *al = 0, *ar = dol; - else - *ar = dol - 1; - unreadc(c); - break; - } - if (first) { - c = getC(0); - unreadc(c); - if (any("-$*", c)) - return (1); - } - if (*al > *ar || *ar > dol) { - seterror(ERR_BADBANGARG); - return (0); - } - return (1); - -} - -static struct wordent * -gethent(int sc) -{ - struct Hist *hp; - Char *np; - char *str; - int c, event; - int back; - - back = 0; - c = sc == HISTSUB ? HIST : getC(0); - if (c == HIST) { - if (alhistp) - return (alhistp); - event = eventno; - } - else - switch (c) { - case ':': - case '^': - case '$': - case '*': - case '%': - ungetC(c); - if (lastev == eventno && alhistp) - return (alhistp); - event = lastev; - break; - case '#': /* !# is command being typed in (mrh) */ - if (--hleft == 0) { - seterror(ERR_HISTLOOP); - return (0); - } - else - return (¶ml); - /* NOTREACHED */ - case '-': - back = 1; - c = getC(0); - /* FALLTHROUGH */ - default: - if (any("(=~", c)) { - unreadc(c); - ungetC(HIST); - return (0); - } - np = lhsb; - event = 0; - while (!cmap(c, _ESC | _META | _QF | _QB) && !any("${}:", c)) { - if (event != -1 && Isdigit(c)) - event = event * 10 + c - '0'; - else - event = -1; - if (np < &lhsb[sizeof(lhsb) / sizeof(Char) - 2]) - *np++ = (Char)c; - c = getC(0); - } - unreadc(c); - if (np == lhsb) { - ungetC(HIST); - return (0); - } - *np++ = 0; - if (event != -1) { - /* - * History had only digits - */ - if (back) - event = eventno + (alhistp == 0) - (event ? event : 0); - break; - } - hp = findev(lhsb, 0); - if (hp) - lastev = hp->Hnum; - return (&hp->Hlex); - case '?': - np = lhsb; - for (;;) { - c = getC(0); - if (c == '\n') { - unreadc(c); - break; - } - if (c == '?') - break; - if (np < &lhsb[sizeof(lhsb) / sizeof(Char) - 2]) - *np++ = (Char)c; - } - if (np == lhsb) { - if (lhsb[0] == 0) { - seterror(ERR_NOSEARCH); - return (0); - } - } - else - *np++ = 0; - hp = findev(lhsb, 1); - if (hp) - lastev = hp->Hnum; - return (&hp->Hlex); - } - - for (hp = Histlist.Hnext; hp; hp = hp->Hnext) - if (hp->Hnum == event) { - hp->Href = eventno; - lastev = hp->Hnum; - return (&hp->Hlex); - } - np = putn(event); - str = vis_str(np); - xfree((ptr_t) np); - seterror(ERR_NOEVENT, str); - return (0); -} - -static struct Hist * -findev(Char *cp, int anyarg) -{ - struct Hist *hp; - - for (hp = Histlist.Hnext; hp; hp = hp->Hnext) { - Char *dp, *p, *q; - struct wordent *lp; - int argno; - - lp = hp->Hlex.next; - argno = 0; - - /* - * The entries added by alias substitution don't have a newline but do - * have a negative event number. Savehist() trims off these entries, - * but it happens before alias expansion, too early to delete those - * from the previous command. - */ - if (hp->Hnum < 0) - continue; - if (lp->word[0] == '\n') - continue; - if (!anyarg) { - p = cp; - q = lp->word; - do - if (!*p) - return (hp); - while (*p++ == *q++); - continue; - } - do { - for (dp = lp->word; *dp; dp++) { - p = cp; - q = dp; - do - if (!*p) { - quesarg = argno; - return (hp); - } - while (*p++ == *q++); - } - lp = lp->next; - argno++; - } while (lp->word[0] != '\n'); - } - seterror(ERR_NOEVENT, vis_str(cp)); - return (0); -} - - -static void -setexclp(Char *cp) -{ - if (cp && cp[0] == '\n') - return; - exclp = cp; -} - -void -unreadc(int c) -{ - peekread = c; -} - -int -readc(int wanteof) -{ - static int sincereal; - int c; - - aret = F_SEEK; - if ((c = peekread) != '\0') { - peekread = 0; - return (c); - } -top: - aret = F_SEEK; - if (alvecp) { - aret = A_SEEK; - if ((c = *alvecp++) != '\0') - return (c); - if (alvec && *alvec) { - alvecp = *alvec++; - return (' '); - } - else { - aret = F_SEEK; - alvecp = NULL; - return('\n'); - } - } - if (alvec) { - if ((alvecp = *alvec) != '\0') { - alvec++; - goto top; - } - /* Infinite source! */ - return ('\n'); - } - if (evalp) { - aret = E_SEEK; - if ((c = *evalp++) != '\0') - return (c); - if (evalvec && *evalvec) { - evalp = *evalvec++; - return (' '); - } - aret = F_SEEK; - evalp = 0; - } - if (evalvec) { - if (evalvec == (Char **) 1) { - doneinp = 1; - reset(); - } - if ((evalp = *evalvec) != '\0') { - evalvec++; - goto top; - } - evalvec = (Char **) 1; - return ('\n'); - } - do { - if (arginp == (Char *) 1 || onelflg == 1) { - if (wanteof) - return (-1); - exitstat(); - } - if (arginp) { - if ((c = *arginp++) == 0) { - arginp = (Char *) 1; - return ('\n'); - } - return (c); - } -reread: - c = bgetc(); - if (c < 0) { - struct termios tty; - if (wanteof) - return (-1); - /* was isatty but raw with ignoreeof yields problems */ - if (tcgetattr(SHIN, &tty) == 0 && (tty.c_lflag & ICANON)) - { - /* was 'short' for FILEC */ - pid_t ctpgrp; - - if (++sincereal > 25) - goto oops; - if (tpgrp != -1 && - (ctpgrp = tcgetpgrp(FSHTTY)) != -1 && - tpgrp != ctpgrp) { - (void)tcsetpgrp(FSHTTY, tpgrp); - (void)kill(-ctpgrp, SIGHUP); - (void)fprintf(csherr, "Reset tty pgrp from %ld to %ld\n", - (long)ctpgrp, (long)tpgrp); - goto reread; - } - if (adrof(STRignoreeof)) { - if (loginsh) - (void)fprintf(csherr,"\nUse \"logout\" to logout.\n"); - else - (void)fprintf(csherr,"\nUse \"exit\" to leave csh.\n"); - reset(); - } - if (chkstop == 0) - panystop(1); - } - oops: - doneinp = 1; - reset(); - } - sincereal = 0; - if (c == '\n' && onelflg) - onelflg--; - } while (c == 0); - return (c); -} - -static int -bgetc(void) -{ -#ifdef FILEC - char tbuf[BUFSIZE + 1]; - Char ttyline[BUFSIZE]; - int buf, off; - ssize_t c, numleft, roomleft; - - numleft = 0; -#else /* FILEC */ - char tbuf[BUFSIZE + 1]; - int c, buf, off; -#endif /* !FILEC */ - - if (cantell) { - if (fseekp < fbobp || fseekp > feobp) { - fbobp = feobp = fseekp; - (void)lseek(SHIN, fseekp, SEEK_SET); - } - if (fseekp == feobp) { - int i; - - fbobp = feobp; - do - c = read(SHIN, tbuf, BUFSIZE); - while (c < 0 && errno == EINTR); - if (c <= 0) - return (-1); - for (i = 0; i < c; i++) - fbuf[0][i] = (unsigned char) tbuf[i]; - feobp += c; - } - c = fbuf[0][fseekp - fbobp]; - fseekp++; - return (int)(c); - } - -again: - buf = (int) fseekp / BUFSIZE; - if (buf >= fblocks) { - Char **nfbuf; - - nfbuf = (Char **)xcalloc((size_t) (fblocks + 2), sizeof(char **)); - if (fbuf) { - (void)blkcpy(nfbuf, fbuf); - xfree((ptr_t) fbuf); - } - fbuf = nfbuf; - fbuf[fblocks] = (Char *)xcalloc(BUFSIZE, sizeof(Char)); - fblocks++; - if (!intty) - goto again; - } - if (fseekp >= feobp) { - buf = (int) feobp / BUFSIZE; - off = (int) feobp % BUFSIZE; - roomleft = BUFSIZE - off; - -#ifdef FILEC - for (;;) { - if ((editing || filec) && intty) { -#ifdef EDIT - if (editing) { - const char *p; - int d; - if ((p = el_gets(el, &d)) != NULL) { - size_t i; - /* XXX: Truncation */ - numleft = d > BUFSIZE ? BUFSIZE : d; - for (i = 0; *p && i < BUFSIZE; i++, p++) - ttyline[i] = *p; - ttyline[i - (i == BUFSIZE)] = '\0'; - } - } -#endif - c = numleft ? numleft : tenex(ttyline, BUFSIZE); - if (c > roomleft) { - /* start with fresh buffer */ - feobp = fseekp = fblocks * BUFSIZE; - numleft = c; - goto again; - } - if (c > 0) - (void)memcpy(fbuf[buf] + off, ttyline, - (size_t)c * sizeof(**fbuf)); - numleft = 0; - } - else { -#endif - c = read(SHIN, tbuf, (size_t)roomleft); - if (c > 0) { - int i; - Char *ptr = fbuf[buf] + off; - - for (i = 0; i < c; i++) - ptr[i] = (unsigned char) tbuf[i]; - } -#ifdef FILEC - } -#endif - if (c >= 0) - break; - if (errno == EWOULDBLOCK) { - int iooff = 0; - - (void)ioctl(SHIN, FIONBIO, (ioctl_t) & iooff); - } - else if (errno != EINTR) - break; -#ifdef FILEC - } -#endif - if (c <= 0) - return (-1); - feobp += c; -#ifndef FILEC - goto again; -#else - if (filec && !intty) - goto again; -#endif - } - c = fbuf[buf][(int)fseekp % BUFSIZE]; - fseekp++; - return (int)(c); -} - -static void -bfree(void) -{ - int i, sb; - - if (cantell) - return; - if (whyles) - return; - sb = (int)(fseekp - 1) / BUFSIZE; - if (sb > 0) { - for (i = 0; i < sb; i++) - xfree((ptr_t) fbuf[i]); - (void)blkcpy(fbuf, &fbuf[sb]); - fseekp -= BUFSIZE * sb; - feobp -= BUFSIZE * sb; - fblocks -= sb; - } -} - -void -bseek(struct Ain *l) -{ - switch (aret = l->type) { - case A_SEEK: - alvec = l->a_seek; - alvecp = l->c_seek; - return; - case E_SEEK: - evalvec = l->a_seek; - evalp = l->c_seek; - return; - case F_SEEK: - fseekp = l->f_seek; - return; - default: - (void)fprintf(csherr, "Bad seek type %d\n", aret); - abort(); - } -} - -void -btell(struct Ain *l) -{ - switch (l->type = aret) { - case A_SEEK: - l->a_seek = alvec; - l->c_seek = alvecp; - return; - case E_SEEK: - l->a_seek = evalvec; - l->c_seek = evalp; - return; - case F_SEEK: - l->f_seek = fseekp; - l->a_seek = NULL; - return; - default: - (void)fprintf(csherr, "Bad seek type %d\n", aret); - abort(); - } -} - -void -btoeof(void) -{ - (void)lseek(SHIN, (off_t) 0, SEEK_END); - aret = F_SEEK; - fseekp = feobp; - alvec = NULL; - alvecp = NULL; - evalvec = NULL; - evalp = NULL; - wfree(); - bfree(); -} - -void -settell(void) -{ - cantell = 0; - if (arginp || onelflg || intty) - return; - if (lseek(SHIN, (off_t) 0, SEEK_CUR) < 0 || errno == ESPIPE) - return; - fbuf = (Char **)xcalloc(2, sizeof(Char **)); - fblocks = 1; - fbuf[0] = (Char *)xcalloc(BUFSIZE, sizeof(Char)); - fseekp = fbobp = feobp = lseek(SHIN, (off_t) 0, SEEK_CUR); - cantell = 1; -} diff --git a/bin/csh/misc.c b/bin/csh/misc.c deleted file mode 100644 index 88d2f8e94..000000000 --- a/bin/csh/misc.c +++ /dev/null @@ -1,407 +0,0 @@ -/* $NetBSD: misc.c,v 1.20 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: misc.c,v 1.20 2013/07/16 17:47:43 christos Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include -#include -#include -#include - -#include "csh.h" -#include "extern.h" - -static int renum(int, int); - -int -any(const char *s, int c) -{ - if (!s) - return (0); /* Check for nil pointer */ - while (*s) - if (*s++ == c) - return (1); - return (0); -} - -char * -strsave(const char *s) -{ - const char *n; - char *p, *r; - - if (s == NULL) - s = ""; - for (n = s; *n++;) - continue; - r = p = xmalloc((size_t)(n - s) * sizeof(*p)); - while ((*p++ = *s++) != '\0') - continue; - return (r); -} - -Char ** -blkend(Char **up) -{ - while (*up) - up++; - return (up); -} - - -void -blkpr(FILE *fp, Char **av) -{ - for (; *av; av++) { - (void)fprintf(fp, "%s", vis_str(*av)); - if (av[1]) - (void)fprintf(fp, " "); - } -} - -int -blklen(Char **av) -{ - int i; - - i = 0; - while (*av++) - i++; - return (i); -} - -Char ** -blkcpy(Char **oav, Char **bv) -{ - Char **av; - - av = oav; - while ((*av++ = *bv++) != NULL) - continue; - return (oav); -} - -Char ** -blkcat(Char **up, Char **vp) -{ - (void)blkcpy(blkend(up), vp); - return (up); -} - -void -blkfree(Char **av0) -{ - Char **av; - - av = av0; - if (!av0) - return; - for (; *av; av++) - xfree((ptr_t) * av); - xfree((ptr_t) av0); -} - -Char ** -saveblk(Char **v) -{ - Char **newv, **onewv; - - if (v == NULL) - return NULL; - - newv = xcalloc((size_t)(blklen(v) + 1), sizeof(*newv)); - onewv = newv; - while (*v) - *newv++ = Strsave(*v++); - return (onewv); -} - -#ifdef NOTUSED -char * -strstr(char *s, char *t) -{ - do { - char *ss; - char *tt; - - ss = s; - tt = t; - - do - if (*tt == '\0') - return (s); - while (*ss++ == *tt++); - } while (*s++ != '\0'); - return (NULL); -} - -#endif /* NOTUSED */ - -#ifndef SHORT_STRINGS -char * -strspl(char *cp, char *dp) -{ - char *ep, *p, *q; - - if (!cp) - cp = ""; - if (!dp) - dp = ""; - for (p = cp; *p++;) - continue; - for (q = dp; *q++;) - continue; - ep = xmalloc((size_t)(((p - cp) + (q - dp) - 1) * sizeof(*ep))); - for (p = ep, q = cp; *p++ = *q++;) - continue; - for (p--, q = dp; *p++ = *q++;) - continue; - return (ep); -} - -#endif - -Char ** -blkspl(Char **up, Char **vp) -{ - Char **wp; - - wp = xcalloc((size_t)(blklen(up) + blklen(vp) + 1), sizeof(*wp)); - (void)blkcpy(wp, up); - return (blkcat(wp, vp)); -} - -Char -lastchr(Char *cp) -{ - if (!cp) - return (0); - if (!*cp) - return (0); - while (cp[1]) - cp++; - return (*cp); -} - -/* - * This routine is called after an error to close up - * any units which may have been left open accidentally. - */ -void -closem(void) -{ - int f; - int nofile; - -#ifdef F_CLOSEM - nofile = FOLDSTD + 1; - if (fcntl(nofile, F_CLOSEM, 0) == -1) -#endif - nofile = NOFILE; - - for (f = 0; f < nofile; f++) - if (f != SHIN && f != SHOUT && f != SHERR && f != OLDSTD && - f != FSHTTY) - (void) close(f); -} - -void -donefds(void) -{ - (void)close(0); - (void)close(1); - (void)close(2); - - didfds = 0; -} - -/* - * Move descriptor i to j. - * If j is -1 then we just want to get i to a safe place, - * i.e. to a unit > 2. This also happens in dcopy. - */ -int -dmove(int i, int j) -{ - if (i == j || i < 0) - return (i); - if (j >= 0) { - (void)dup2(i, j); - if (j != i) - (void)close(i); - return (j); - } - j = dcopy(i, j); - if (j != i) - (void)close(i); - return (j); -} - -int -dcopy(int i, int j) -{ - if (i == j || i < 0 || (j < 0 && i > 2)) - return (i); - if (j >= 0) { - (void)dup2(i, j); - return (j); - } - return (renum(i, j)); -} - -static int -renum(int i, int j) -{ - int k; - - k = dup(i); - if (k < 0) - return (-1); - if (j == -1 && k > 2) - return (k); - if (k != j) { - j = renum(k, j); - (void)close(k); - return (j); - } - return (k); -} - -/* - * Left shift a command argument list, discarding - * the first c arguments. Used in "shift" commands - * as well as by commands like "repeat". - */ -void -lshift(Char **v, size_t c) -{ - Char **u; - - for (u = v; *u && c-- > 0; u++) - xfree((ptr_t) *u); - (void)blkcpy(v, u); -} - -int -number(Char *cp) -{ - if (!cp) - return(0); - if (*cp == '-') { - cp++; - if (!Isdigit(*cp)) - return (0); - cp++; - } - while (*cp && Isdigit(*cp)) - cp++; - return (*cp == 0); -} - -Char ** -copyblk(Char **v) -{ - Char **nv; - - nv = xcalloc((size_t)(blklen(v) + 1), sizeof(*nv)); - - return (blkcpy(nv, v)); -} - -#ifndef SHORT_STRINGS -char * -strend(char *cp) -{ - if (!cp) - return (cp); - while (*cp) - cp++; - return (cp); -} - -#endif /* SHORT_STRINGS */ - -Char * -strip(Char *cp) -{ - Char *dp; - - dp = cp; - if (!cp) - return (cp); - while ((*dp++ &= TRIM) != '\0') - continue; - return (cp); -} - -Char * -quote(Char *cp) -{ - Char *dp; - - dp = cp; - if (!cp) - return (cp); - while (*dp != '\0') - *dp++ |= QUOTE; - return (cp); -} - -void -udvar(Char *name) -{ - setname(vis_str(name)); - stderror(ERR_NAME | ERR_UNDVAR); - /* NOTREACHED */ -} - -int -prefix(Char *sub, Char *str) -{ - for (;;) { - if (*sub == 0) - return (1); - if (*str == 0) - return (0); - if (*sub++ != *str++) - return (0); - } -} diff --git a/bin/csh/parse.c b/bin/csh/parse.c deleted file mode 100644 index 25bc43867..000000000 --- a/bin/csh/parse.c +++ /dev/null @@ -1,640 +0,0 @@ -/* $NetBSD: parse.c,v 1.17 2007/07/16 18:26:10 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: parse.c,v 1.17 2007/07/16 18:26:10 christos Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include -#include - -#include "csh.h" -#include "extern.h" - -static void asyntax(struct wordent *, struct wordent *); -static void asyn0(struct wordent *, struct wordent *); -static void asyn3(struct wordent *, struct wordent *); -static struct wordent *freenod(struct wordent *, struct wordent *); -static struct command *syn0(struct wordent *, struct wordent *, int); -static struct command *syn1(struct wordent *, struct wordent *, int); -static struct command *syn1a(struct wordent *, struct wordent *, int); -static struct command *syn1b(struct wordent *, struct wordent *, int); -static struct command *syn2(struct wordent *, struct wordent *, int); -static struct command *syn3(struct wordent *, struct wordent *, int); - -#define ALEFT 21 /* max of 20 alias expansions */ -#define HLEFT 11 /* max of 10 history expansions */ -/* - * Perform aliasing on the word list lex - * Do a (very rudimentary) parse to separate into commands. - * If word 0 of a command has an alias, do it. - * Repeat a maximum of 20 times. - */ -static int aleft; -extern int hleft; - -void -alias(struct wordent *lexp) -{ - jmp_buf osetexit; - - aleft = ALEFT; - hleft = HLEFT; - getexit(osetexit); - (void)setexit(); - if (haderr) { - resexit(osetexit); - reset(); - } - if (--aleft == 0) - stderror(ERR_ALIASLOOP); - asyntax(lexp->next, lexp); - resexit(osetexit); -} - -static void -asyntax(struct wordent *p1, struct wordent *p2) -{ - while (p1 != p2) - if (any(";&\n", p1->word[0])) - p1 = p1->next; - else { - asyn0(p1, p2); - return; - } -} - -static void -asyn0(struct wordent *p1, struct wordent *p2) -{ - struct wordent *p; - int l; - - l = 0; - for (p = p1; p != p2; p = p->next) - switch (p->word[0]) { - case '(': - l++; - continue; - case ')': - l--; - if (l < 0) - stderror(ERR_TOOMANYRP); - continue; - case '>': - if (p->next != p2 && eq(p->next->word, STRand)) - p = p->next; - continue; - case '&': - case '|': - case ';': - case '\n': - if (l != 0) - continue; - asyn3(p1, p); - asyntax(p->next, p2); - return; - } - if (l == 0) - asyn3(p1, p2); -} - -static void -asyn3(struct wordent *p1, struct wordent *p2) -{ - struct varent *ap; - struct wordent alout; - int redid; - - if (p1 == p2) - return; - if (p1->word[0] == '(') { - for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) - if (p2 == p1) - return; - if (p2 == p1->next) - return; - asyn0(p1->next, p2); - return; - } - ap = adrof1(p1->word, &aliases); - if (ap == 0) - return; - alhistp = p1->prev; - alhistt = p2; - alvec = ap->vec; - redid = lex(&alout); - alhistp = alhistt = 0; - alvec = 0; - if (seterr) { - freelex(&alout); - stderror(ERR_OLD); - } - if (p1->word[0] && eq(p1->word, alout.next->word)) { - Char *cp; - - cp = alout.next->word; - alout.next->word = Strspl(STRQNULL, cp); - xfree((ptr_t) cp); - } - p1 = freenod(p1, redid ? p2 : p1->next); - if (alout.next != &alout) { - p1->next->prev = alout.prev->prev; - alout.prev->prev->next = p1->next; - alout.next->prev = p1; - p1->next = alout.next; - xfree((ptr_t)alout.prev->word); - xfree((ptr_t)(alout.prev)); - } - reset(); /* throw! */ -} - -static struct wordent * -freenod(struct wordent *p1, struct wordent *p2) -{ - struct wordent *retp; - - retp = p1->prev; - while (p1 != p2) { - xfree((ptr_t)p1->word); - p1 = p1->next; - xfree((ptr_t) (p1->prev)); - } - retp->next = p2; - p2->prev = retp; - return (retp); -} - -#define PHERE 1 -#define PIN 2 -#define POUT 4 -#define PERR 8 - -/* - * syntax - * empty - * syn0 - */ -struct command * -syntax(struct wordent *p1, struct wordent *p2, int flags) -{ - while (p1 != p2) - if (any(";&\n", p1->word[0])) - p1 = p1->next; - else - return (syn0(p1, p2, flags)); - return (0); -} - -/* - * syn0 - * syn1 - * syn1 & syntax - */ -static struct command * -syn0(struct wordent *p1, struct wordent *p2, int flags) -{ - struct wordent *p; - struct command *t, *t1; - int l; - - l = 0; - for (p = p1; p != p2; p = p->next) - switch (p->word[0]) { - case '(': - l++; - continue; - case ')': - l--; - if (l < 0) - seterror(ERR_TOOMANYRP); - continue; - case '|': - if (p->word[1] == '|') - continue; - /* FALLTHROUGH */ - case '>': - if (p->next != p2 && eq(p->next->word, STRand)) - p = p->next; - continue; - case '&': - if (l != 0) - break; - if (p->word[1] == '&') - continue; - t1 = syn1(p1, p, flags); - if (t1->t_dtyp == NODE_LIST || - t1->t_dtyp == NODE_AND || - t1->t_dtyp == NODE_OR) { - t = (struct command *)xcalloc(1, sizeof(*t)); - t->t_dtyp = NODE_PAREN; - t->t_dflg = F_AMPERSAND | F_NOINTERRUPT; - t->t_dspr = t1; - t1 = t; - } - else - t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT; - t = (struct command *)xcalloc(1, sizeof(*t)); - t->t_dtyp = NODE_LIST; - t->t_dflg = 0; - t->t_dcar = t1; - t->t_dcdr = syntax(p, p2, flags); - return (t); - } - if (l == 0) - return (syn1(p1, p2, flags)); - seterror(ERR_TOOMANYLP); - return (0); -} - -/* - * syn1 - * syn1a - * syn1a ; syntax - */ -static struct command * -syn1(struct wordent *p1, struct wordent *p2, int flags) -{ - struct wordent *p; - struct command *t; - int l; - - l = 0; - for (p = p1; p != p2; p = p->next) - switch (p->word[0]) { - case '(': - l++; - continue; - case ')': - l--; - continue; - case ';': - case '\n': - if (l != 0) - break; - t = (struct command *) xcalloc(1, sizeof(*t)); - t->t_dtyp = NODE_LIST; - t->t_dcar = syn1a(p1, p, flags); - t->t_dcdr = syntax(p->next, p2, flags); - if (t->t_dcdr == 0) - t->t_dcdr = t->t_dcar, t->t_dcar = 0; - return (t); - } - return (syn1a(p1, p2, flags)); -} - -/* - * syn1a - * syn1b - * syn1b || syn1a - */ -static struct command * -syn1a(struct wordent *p1, struct wordent *p2, int flags) -{ - struct wordent *p; - struct command *t; - int l; - - l = 0; - for (p = p1; p != p2; p = p->next) - switch (p->word[0]) { - case '(': - l++; - continue; - case ')': - l--; - continue; - case '|': - if (p->word[1] != '|') - continue; - if (l == 0) { - t = (struct command *)xcalloc(1, sizeof(*t)); - t->t_dtyp = NODE_OR; - t->t_dcar = syn1b(p1, p, flags); - t->t_dcdr = syn1a(p->next, p2, flags); - t->t_dflg = 0; - return (t); - } - continue; - } - return (syn1b(p1, p2, flags)); -} - -/* - * syn1b - * syn2 - * syn2 && syn1b - */ -static struct command * -syn1b(struct wordent *p1, struct wordent *p2, int flags) -{ - struct wordent *p; - struct command *t; - int l; - - l = 0; - for (p = p1; p != p2; p = p->next) - switch (p->word[0]) { - case '(': - l++; - continue; - case ')': - l--; - continue; - case '&': - if (p->word[1] == '&' && l == 0) { - t = (struct command *)xcalloc(1, sizeof(*t)); - t->t_dtyp = NODE_AND; - t->t_dcar = syn2(p1, p, flags); - t->t_dcdr = syn1b(p->next, p2, flags); - t->t_dflg = 0; - return (t); - } - continue; - } - return (syn2(p1, p2, flags)); -} - -/* - * syn2 - * syn3 - * syn3 | syn2 - * syn3 |& syn2 - */ -static struct command * -syn2(struct wordent *p1, struct wordent *p2, int flags) -{ - struct wordent *p, *pn; - struct command *t; - int f, l; - - l = 0; - for (p = p1; p != p2; p = p->next) - switch (p->word[0]) { - case '(': - l++; - continue; - case ')': - l--; - continue; - case '|': - if (l != 0) - continue; - t = (struct command *)xcalloc(1, sizeof(*t)); - f = flags | POUT; - pn = p->next; - if (pn != p2 && pn->word[0] == '&') { - f |= PERR; - t->t_dflg |= F_STDERR; - } - t->t_dtyp = NODE_PIPE; - t->t_dcar = syn3(p1, p, f); - if (pn != p2 && pn->word[0] == '&') - p = pn; - t->t_dcdr = syn2(p->next, p2, flags | PIN); - return (t); - } - return (syn3(p1, p2, flags)); -} - -static char RELPAR[] = {'<', '>', '(', ')', '\0'}; - -/* - * syn3 - * ( syn0 ) [ < in ] [ > out ] - * word word* [ < in ] [ > out ] - * KEYWORD ( word* ) word* [ < in ] [ > out ] - * - * KEYWORD = (@ exit foreach if set switch test while) - */ -static struct command * -syn3(struct wordent *p1, struct wordent *p2, int flags) -{ - struct wordent *lp, *p, *rp; - struct command *t; - Char **av; - int c, l, n; - int specp; - - specp = 0; - if (p1 != p2) { - p = p1; -again: - switch (srchx(p->word)) { - case T_ELSE: - p = p->next; - if (p != p2) - goto again; - break; - case T_EXIT: - case T_FOREACH: - case T_IF: - case T_LET: - case T_SET: - case T_SWITCH: - case T_WHILE: - specp = 1; - break; - } - } - n = 0; - l = 0; - for (p = p1; p != p2; p = p->next) - switch (p->word[0]) { - case '(': - if (specp) - n++; - l++; - continue; - case ')': - if (specp) - n++; - l--; - continue; - case '>': - case '<': - if (l != 0) { - if (specp) - n++; - continue; - } - if (p->next == p2) - continue; - if (any(RELPAR, p->next->word[0])) - continue; - n--; - continue; - default: - if (!specp && l != 0) - continue; - n++; - continue; - } - if (n < 0) - n = 0; - t = (struct command *)xcalloc(1, sizeof(*t)); - av = (Char **)xcalloc((size_t)(n + 1), sizeof(Char **)); - t->t_dcom = av; - n = 0; - if (p2->word[0] == ')') - t->t_dflg = F_NOFORK; - lp = 0; - rp = 0; - l = 0; - for (p = p1; p != p2; p = p->next) { - c = p->word[0]; - switch (c) { - case '(': - if (l == 0) { - if (lp != 0 && !specp) - seterror(ERR_BADPLP); - lp = p->next; - } - l++; - goto savep; - case ')': - l--; - if (l == 0) - rp = p; - goto savep; - case '>': - if (l != 0) - goto savep; - if (p->word[1] == '>') - t->t_dflg |= F_APPEND; - if (p->next != p2 && eq(p->next->word, STRand)) { - t->t_dflg |= F_STDERR, p = p->next; - if (flags & (POUT | PERR)) { - seterror(ERR_OUTRED); - continue; - } - } - if (p->next != p2 && eq(p->next->word, STRbang)) - t->t_dflg |= F_OVERWRITE, p = p->next; - if (p->next == p2) { - seterror(ERR_MISRED); - continue; - } - p = p->next; - if (any(RELPAR, p->word[0])) { - seterror(ERR_MISRED); - continue; - } - if ((flags & POUT) && ((flags & PERR) == 0 || t->t_drit)) - seterror(ERR_OUTRED); - else - t->t_drit = Strsave(p->word); - continue; - case '<': - if (l != 0) - goto savep; - if (p->word[1] == '<') - t->t_dflg |= F_READ; - if (p->next == p2) { - seterror(ERR_MISRED); - continue; - } - p = p->next; - if (any(RELPAR, p->word[0])) { - seterror(ERR_MISRED); - continue; - } - if ((flags & PHERE) && (t->t_dflg & F_READ)) - seterror(ERR_REDPAR); - else if ((flags & PIN) || t->t_dlef) - seterror(ERR_INRED); - else - t->t_dlef = Strsave(p->word); - continue; - savep: - if (!specp) - continue; - /* FALLTHROUGH */ - default: - if (l != 0 && !specp) - continue; - if (seterr == 0) - av[n] = Strsave(p->word); - n++; - continue; - } - } - if (lp != 0 && !specp) { - if (n != 0) - seterror(ERR_BADPLPS); - t->t_dtyp = NODE_PAREN; - t->t_dspr = syn0(lp, rp, PHERE); - } - else { - if (n == 0) - seterror(ERR_NULLCOM); - t->t_dtyp = NODE_COMMAND; - } - return (t); -} - -void -freesyn(struct command *t) -{ - Char **v; - - if (t == 0) - return; - switch (t->t_dtyp) { - case NODE_COMMAND: - for (v = t->t_dcom; *v; v++) - xfree((ptr_t) * v); - xfree((ptr_t)(t->t_dcom)); - xfree((ptr_t)t->t_dlef); - xfree((ptr_t)t->t_drit); - break; - case NODE_PAREN: - freesyn(t->t_dspr); - xfree((ptr_t)t->t_dlef); - xfree((ptr_t)t->t_drit); - break; - case NODE_AND: - case NODE_OR: - case NODE_PIPE: - case NODE_LIST: - freesyn(t->t_dcar), freesyn(t->t_dcdr); - break; - } - xfree((ptr_t)t); -} diff --git a/bin/csh/pathnames.h b/bin/csh/pathnames.h deleted file mode 100644 index db2e37358..000000000 --- a/bin/csh/pathnames.h +++ /dev/null @@ -1,44 +0,0 @@ -/* $NetBSD: pathnames.h,v 1.8 2003/08/07 09:05:06 agc Exp $ */ - -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)pathnames.h 8.1 (Berkeley) 5/31/93 - */ - -#ifndef _PATHNAMES_H_ -#define _PATHNAMES_H_ - -#define _PATH_BIN "/bin" -#define _PATH_DOTCSHRC "/etc/csh.cshrc" -#define _PATH_DOTLOGIN "/etc/csh.login" -#define _PATH_DOTLOGOUT "/etc/csh.logout" -#define _PATH_LOGIN "/usr/bin/login" -#define _PATH_USRBIN "/usr/bin" - -#endif /* !_PATHNAMES_H_ */ diff --git a/bin/csh/proc.c b/bin/csh/proc.c deleted file mode 100644 index 5c53d98f7..000000000 --- a/bin/csh/proc.c +++ /dev/null @@ -1,1359 +0,0 @@ -/* $NetBSD: proc.c,v 1.36 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)proc.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: proc.c,v 1.36 2013/07/16 17:47:43 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include - -#include -#include -#include -#include -#include - -#include "csh.h" -#include "dir.h" -#include "extern.h" -#include "proc.h" - -#define BIGINDEX 9 /* largest desirable job index */ - -extern int insource; - -static void pflushall(void); -static void pflush(struct process *); -static void pclrcurr(struct process *); -static void padd(struct command *); -static int pprint(struct process *, int); -static void ptprint(struct process *); -static void pads(Char *); -static void pkill(Char **v, int); -static struct process *pgetcurr(struct process *); -static void okpcntl(void); - -/* - * pchild - called at interrupt level by the SIGCHLD signal - * indicating that at least one child has terminated or stopped - * thus at least one wait system call will definitely return a - * childs status. Top level routines (like pwait) must be sure - * to mask interrupts when playing with the proclist data structures! - */ -/* ARGSUSED */ -void -pchild(int notused) -{ - struct rusage ru; - struct process *fp, *pp; - int jobflags, pid, w; - -loop: - errno = 0; /* reset, just in case */ - pid = wait3(&w, - (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru); - - if (pid <= 0) { - if (errno == EINTR) { - errno = 0; - goto loop; - } - pnoprocesses = pid == -1; - return; - } - for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) - if (pid == pp->p_pid) - goto found; - goto loop; -found: - if (pid == atoi(short2str(value(STRchild)))) - unsetv(STRchild); - pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED); - if (WIFSTOPPED(w)) { - pp->p_flags |= PSTOPPED; - pp->p_reason = WSTOPSIG(w); - } - else { - if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime)) - (void)clock_gettime(CLOCK_MONOTONIC, &pp->p_etime); - - pp->p_rusage = ru; - if (WIFSIGNALED(w)) { - if (WTERMSIG(w) == SIGINT) - pp->p_flags |= PINTERRUPTED; - else - pp->p_flags |= PSIGNALED; - if (WCOREDUMP(w)) - pp->p_flags |= PDUMPED; - pp->p_reason = WTERMSIG(w); - } - else { - pp->p_reason = WEXITSTATUS(w); - if (pp->p_reason != 0) - pp->p_flags |= PAEXITED; - else - pp->p_flags |= PNEXITED; - } - } - jobflags = 0; - fp = pp; - do { - if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 && - !child && adrof(STRtime) && - fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec - >= atoi(short2str(value(STRtime)))) - fp->p_flags |= PTIME; - jobflags |= fp->p_flags; - } while ((fp = fp->p_friends) != pp); - pp->p_flags &= ~PFOREGND; - if (pp == pp->p_friends && (pp->p_flags & PPTIME)) { - pp->p_flags &= ~PPTIME; - pp->p_flags |= PTIME; - } - if ((jobflags & (PRUNNING | PREPORTED)) == 0) { - fp = pp; - do { - if (fp->p_flags & PSTOPPED) - fp->p_flags |= PREPORTED; - } while ((fp = fp->p_friends) != pp); - while (fp->p_pid != fp->p_jobid) - fp = fp->p_friends; - if (jobflags & PSTOPPED) { - if (pcurrent && pcurrent != fp) - pprevious = pcurrent; - pcurrent = fp; - } - else - pclrcurr(fp); - if (jobflags & PFOREGND) { - if (jobflags & (PSIGNALED | PSTOPPED | PPTIME) || -#ifdef IIASA - jobflags & PAEXITED || -#endif - !eq(dcwd->di_name, fp->p_cwd->di_name)) { - ; /* print in pjwait */ - } - /* PWP: print a newline after ^C */ - else if (jobflags & PINTERRUPTED) { - (void)vis_fputc('\r' | QUOTE, cshout); - (void)fputc('\n', cshout); - } - } - else { - if (jobflags & PNOTIFY || adrof(STRnotify)) { - (void)vis_fputc('\r' | QUOTE, cshout); - (void)fputc('\n', cshout); - (void)pprint(pp, NUMBER | NAME | REASON); - if ((jobflags & PSTOPPED) == 0) - pflush(pp); - } - else { - fp->p_flags |= PNEEDNOTE; - neednote++; - } - } - } - goto loop; -} - -void -pnote(void) -{ - struct process *pp; - sigset_t osigset, nsigset; - int flags; - - neednote = 0; - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGCHLD); - for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) { - if (pp->p_flags & PNEEDNOTE) { - (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); - pp->p_flags &= ~PNEEDNOTE; - flags = pprint(pp, NUMBER | NAME | REASON); - if ((flags & (PRUNNING | PSTOPPED)) == 0) - pflush(pp); - (void)sigprocmask(SIG_SETMASK, &osigset, NULL); - } - } -} - -/* - * pwait - wait for current job to terminate, maintaining integrity - * of current and previous job indicators. - */ -void -pwait(void) -{ - struct process *fp, *pp; - sigset_t osigset, nsigset; - - /* - * Here's where dead procs get flushed. - */ - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGCHLD); - (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); - for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next) - if (pp->p_pid == 0) { - fp->p_next = pp->p_next; - xfree((ptr_t) pp->p_command); - if (pp->p_cwd && --pp->p_cwd->di_count == 0) - if (pp->p_cwd->di_next == 0) - dfree(pp->p_cwd); - xfree((ptr_t) pp); - pp = fp; - } - (void)sigprocmask(SIG_SETMASK, &osigset, NULL); - pjwait(pcurrjob); -} - - -/* - * pjwait - wait for a job to finish or become stopped - * It is assumed to be in the foreground state (PFOREGND) - */ -void -pjwait(struct process *pp) -{ - struct process *fp; - sigset_t osigset, nsigset; - int jobflags, reason; - - while (pp->p_pid != pp->p_jobid) - pp = pp->p_friends; - fp = pp; - - do { - if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING) - (void)fprintf(csherr, "BUG: waiting for background job!\n"); - } while ((fp = fp->p_friends) != pp); - /* - * Now keep pausing as long as we are not interrupted (SIGINT), and the - * target process, or any of its friends, are running - */ - fp = pp; - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGCHLD); - (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); - for (;;) { - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGCHLD); - (void)sigprocmask(SIG_BLOCK, &nsigset, NULL); - jobflags = 0; - do - jobflags |= fp->p_flags; - while ((fp = (fp->p_friends)) != pp); - if ((jobflags & PRUNNING) == 0) - break; -#ifdef JOBDEBUG - (void)fprintf(csherr, "starting to sigsuspend for SIGCHLD on %d\n", - fp->p_pid); -#endif /* JOBDEBUG */ - nsigset = osigset; - (void)sigdelset(&nsigset, SIGCHLD); - (void)sigsuspend(&nsigset); - } - (void)sigprocmask(SIG_SETMASK, &osigset, NULL); - if (tpgrp > 0) /* get tty back */ - (void)tcsetpgrp(FSHTTY, tpgrp); - if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) || - !eq(dcwd->di_name, fp->p_cwd->di_name)) { - if (jobflags & PSTOPPED) { - (void) fputc('\n', cshout); - if (adrof(STRlistjobs)) { - Char *jobcommand[3]; - - jobcommand[0] = STRjobs; - if (eq(value(STRlistjobs), STRlong)) - jobcommand[1] = STRml; - else - jobcommand[1] = NULL; - jobcommand[2] = NULL; - - dojobs(jobcommand, NULL); - (void)pprint(pp, SHELLDIR); - } - else - (void)pprint(pp, AREASON | SHELLDIR); - } - else - (void)pprint(pp, AREASON | SHELLDIR); - } - if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr && - (!gointr || !eq(gointr, STRminus))) { - if ((jobflags & PSTOPPED) == 0) - pflush(pp); - pintr1(0); - } - reason = 0; - fp = pp; - do { - if (fp->p_reason) - reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ? - fp->p_reason | META : fp->p_reason; - } while ((fp = fp->p_friends) != pp); - if ((reason != 0) && (adrof(STRprintexitvalue))) { - (void)fprintf(cshout, "Exit %d\n", reason); - } - set(STRstatus, putn(reason)); - if (reason && exiterr) - exitstat(); - pflush(pp); -} - -/* - * dowait - wait for all processes to finish - */ -void -/*ARGSUSED*/ -dowait(Char **v, struct command *t) -{ - struct process *pp; - sigset_t osigset, nsigset; - - pjobs++; - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGCHLD); - (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); -loop: - for (pp = proclist.p_next; pp; pp = pp->p_next) - if (pp->p_pid && /* pp->p_pid == pp->p_jobid && */ - pp->p_flags & PRUNNING) { - sigemptyset(&nsigset); - (void)sigsuspend(&nsigset); - goto loop; - } - (void)sigprocmask(SIG_SETMASK, &osigset, NULL); - pjobs = 0; -} - -/* - * pflushall - flush all jobs from list (e.g. at fork()) - */ -static void -pflushall(void) -{ - struct process *pp; - - for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) - if (pp->p_pid) - pflush(pp); -} - -/* - * pflush - flag all process structures in the same job as the - * the argument process for deletion. The actual free of the - * space is not done here since pflush is called at interrupt level. - */ -static void -pflush(struct process *pp) -{ - struct process *np; - int idx; - - if (pp->p_pid == 0) { - (void)fprintf(csherr, "BUG: process flushed twice"); - return; - } - while (pp->p_pid != pp->p_jobid) - pp = pp->p_friends; - pclrcurr(pp); - if (pp == pcurrjob) - pcurrjob = 0; - idx = pp->p_index; - np = pp; - do { - np->p_index = np->p_pid = 0; - np->p_flags &= ~PNEEDNOTE; - } while ((np = np->p_friends) != pp); - if (idx == pmaxindex) { - for (np = proclist.p_next, idx = 0; np; np = np->p_next) - if (np->p_index > idx) - idx = np->p_index; - pmaxindex = idx; - } -} - -/* - * pclrcurr - make sure the given job is not the current or previous job; - * pp MUST be the job leader - */ -static void -pclrcurr(struct process *pp) -{ - if (pp == pcurrent) { - if (pprevious != NULL) { - pcurrent = pprevious; - pprevious = pgetcurr(pp); - } - else { - pcurrent = pgetcurr(pp); - pprevious = pgetcurr(pp); - } - } else if (pp == pprevious) - pprevious = pgetcurr(pp); -} - -/* +4 here is 1 for '\0', 1 ea for << >& >> */ -static Char command[PMAXLEN + 4]; -static size_t cmdlen; -static Char *cmdp; - -/* - * palloc - allocate a process structure and fill it up. - * an important assumption is made that the process is running. - */ -void -palloc(int pid, struct command *t) -{ - struct process *pp; - int i; - - pp = (struct process *)xcalloc(1, (size_t)sizeof(struct process)); - pp->p_pid = pid; - pp->p_flags = t->t_dflg & F_AMPERSAND ? PRUNNING : PRUNNING | PFOREGND; - if (t->t_dflg & F_TIME) - pp->p_flags |= PPTIME; - cmdp = command; - cmdlen = 0; - padd(t); - *cmdp++ = 0; - if (t->t_dflg & F_PIPEOUT) { - pp->p_flags |= PPOU; - if (t->t_dflg & F_STDERR) - pp->p_flags |= PERR; - } - pp->p_command = Strsave(command); - if (pcurrjob) { - struct process *fp; - - /* careful here with interrupt level */ - pp->p_cwd = 0; - pp->p_index = pcurrjob->p_index; - pp->p_friends = pcurrjob; - pp->p_jobid = pcurrjob->p_pid; - for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends) - continue; - fp->p_friends = pp; - } - else { - pcurrjob = pp; - pp->p_jobid = pid; - pp->p_friends = pp; - pp->p_cwd = dcwd; - dcwd->di_count++; - if (pmaxindex < BIGINDEX) - pp->p_index = ++pmaxindex; - else { - struct process *np; - - for (i = 1;; i++) { - for (np = proclist.p_next; np; np = np->p_next) - if (np->p_index == i) - goto tryagain; - pp->p_index = i; - if (i > pmaxindex) - pmaxindex = i; - break; - tryagain:; - } - } - if (pcurrent == NULL) - pcurrent = pp; - else if (pprevious == NULL) - pprevious = pp; - } - pp->p_next = proclist.p_next; - proclist.p_next = pp; - (void)clock_gettime(CLOCK_MONOTONIC, &pp->p_btime); -} - -static void -padd(struct command *t) -{ - Char **argp; - - if (t == 0) - return; - switch (t->t_dtyp) { - case NODE_PAREN: - pads(STRLparensp); - padd(t->t_dspr); - pads(STRspRparen); - break; - case NODE_COMMAND: - for (argp = t->t_dcom; *argp; argp++) { - pads(*argp); - if (argp[1]) - pads(STRspace); - } - break; - case NODE_OR: - case NODE_AND: - case NODE_PIPE: - case NODE_LIST: - padd(t->t_dcar); - switch (t->t_dtyp) { - case NODE_OR: - pads(STRspor2sp); - break; - case NODE_AND: - pads(STRspand2sp); - break; - case NODE_PIPE: - pads(STRsporsp); - break; - case NODE_LIST: - pads(STRsemisp); - break; - } - padd(t->t_dcdr); - return; - } - if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) { - pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp); - pads(t->t_dlef); - } - if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) { - pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow); - if (t->t_dflg & F_STDERR) - pads(STRand); - pads(STRspace); - pads(t->t_drit); - } -} - -static void -pads(Char *cp) -{ - size_t i; - - /* - * Avoid the Quoted Space alias hack! Reported by: - * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks) - */ - if (cp[0] == STRQNULL[0]) - cp++; - - i = Strlen(cp); - - if (cmdlen >= PMAXLEN) - return; - if (cmdlen + i >= PMAXLEN) { - (void)Strcpy(cmdp, STRsp3dots); - cmdlen = PMAXLEN; - cmdp += 4; - return; - } - (void)Strcpy(cmdp, cp); - cmdp += i; - cmdlen += i; -} - -/* - * psavejob - temporarily save the current job on a one level stack - * so another job can be created. Used for { } in exp6 - * and `` in globbing. - */ -void -psavejob(void) -{ - pholdjob = pcurrjob; - pcurrjob = NULL; -} - -/* - * prestjob - opposite of psavejob. This may be missed if we are interrupted - * somewhere, but pendjob cleans up anyway. - */ -void -prestjob(void) -{ - pcurrjob = pholdjob; - pholdjob = NULL; -} - -/* - * pendjob - indicate that a job (set of commands) has been completed - * or is about to begin. - */ -void -pendjob(void) -{ - struct process *pp, *tp; - - if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) { - pp = pcurrjob; - while (pp->p_pid != pp->p_jobid) - pp = pp->p_friends; - (void)fprintf(cshout, "[%d]", pp->p_index); - tp = pp; - do { - (void)fprintf(cshout, " %ld", (long)pp->p_pid); - pp = pp->p_friends; - } while (pp != tp); - (void)fputc('\n', cshout); - } - pholdjob = pcurrjob = 0; -} - -/* - * pprint - print a job - */ -static int -pprint(struct process *pp, int flag) -{ - static struct rusage zru; - struct process *tp; - const char *format; - int jobflags, pstatus, reason, status; - int hadnl; - - hadnl = 1; /* did we just have a newline */ - (void)fpurge(cshout); - - while (pp->p_pid != pp->p_jobid) - pp = pp->p_friends; - if (pp == pp->p_friends && (pp->p_flags & PPTIME)) { - pp->p_flags &= ~PPTIME; - pp->p_flags |= PTIME; - } - tp = pp; - status = reason = -1; - jobflags = 0; - do { - jobflags |= pp->p_flags; - pstatus = pp->p_flags & PALLSTATES; - if (tp != pp && !hadnl && !(flag & FANCY) && - ((pstatus == status && pp->p_reason == reason) || - !(flag & REASON))) { - (void)fputc(' ', cshout); - hadnl = 0; - } - else { - if (tp != pp && !hadnl) { - (void)fputc('\n', cshout); - hadnl = 1; - } - if (flag & NUMBER) { - if (pp == tp) - (void)fprintf(cshout, "[%d]%s %c ", pp->p_index, - pp->p_index < 10 ? " " : "", - pp == pcurrent ? '+' : - (pp == pprevious ? '-' : ' ')); - else - (void)fprintf(cshout, " "); - hadnl = 0; - } - if (flag & FANCY) { - (void)fprintf(cshout, "%5ld ", (long)pp->p_pid); - hadnl = 0; - } - if (flag & (REASON | AREASON)) { - if (flag & NAME) - format = "%-23s"; - else - format = "%s"; - if (pstatus == status) { - if (pp->p_reason == reason) { - (void)fprintf(cshout, format, ""); - hadnl = 0; - goto prcomd; - } - else - reason = pp->p_reason; - } else { - status = pstatus; - reason = pp->p_reason; - } - switch (status) { - case PRUNNING: - (void)fprintf(cshout, format, "Running "); - hadnl = 0; - break; - case PINTERRUPTED: - case PSTOPPED: - case PSIGNALED: - /* - * tell what happened to the background job - * From: Michael Schroeder - * - */ - if ((flag & REASON) - || ((flag & AREASON) - && reason != SIGINT - && (reason != SIGPIPE - || (pp->p_flags & PPOU) == 0))) { - (void)fprintf(cshout, format, - sys_siglist[(unsigned char) - pp->p_reason]); - hadnl = 0; - } - break; - case PNEXITED: - case PAEXITED: - if (flag & REASON) { - if (pp->p_reason) - (void)fprintf(cshout, "Exit %-18d", pp->p_reason); - else - (void)fprintf(cshout, format, "Done"); - hadnl = 0; - } - break; - default: - (void)fprintf(csherr, "BUG: status=%-9o", status); - } - } - } -prcomd: - if (flag & NAME) { - (void)fprintf(cshout, "%s", vis_str(pp->p_command)); - if (pp->p_flags & PPOU) - (void)fprintf(cshout, " |"); - if (pp->p_flags & PERR) - (void)fputc('&', cshout); - hadnl = 0; - } - if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED) { - (void)fprintf(cshout, " (core dumped)"); - hadnl = 0; - } - if (tp == pp->p_friends) { - if (flag & AMPERSAND) { - (void)fprintf(cshout, " &"); - hadnl = 0; - } - if (flag & JOBDIR && - !eq(tp->p_cwd->di_name, dcwd->di_name)) { - (void)fprintf(cshout, " (wd: "); - dtildepr(value(STRhome), tp->p_cwd->di_name); - (void)fputc(')', cshout); - hadnl = 0; - } - } - if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) { - if (!hadnl) - (void)fprintf(cshout, "\n\t"); - prusage(cshout, &zru, &pp->p_rusage, &pp->p_etime, - &pp->p_btime); - hadnl = 1; - } - if (tp == pp->p_friends) { - if (!hadnl) { - (void)fputc('\n', cshout); - hadnl = 1; - } - if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) { - (void)fprintf(cshout, "(wd now: "); - dtildepr(value(STRhome), dcwd->di_name); - (void)fprintf(cshout, ")\n"); - hadnl = 1; - } - } - } while ((pp = pp->p_friends) != tp); - if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) { - if (jobflags & NUMBER) - (void)fprintf(cshout, " "); - ptprint(tp); - hadnl = 1; - } - (void)fflush(cshout); - return (jobflags); -} - -static void -ptprint(struct process *tp) -{ - static struct rusage zru; - static struct timespec ztime; - struct rusage ru; - struct timespec tetime, diff; - struct process *pp; - - pp = tp; - ru = zru; - tetime = ztime; - do { - ruadd(&ru, &pp->p_rusage); - timespecsub(&pp->p_etime, &pp->p_btime, &diff); - if (timespeccmp(&diff, &tetime, >)) - tetime = diff; - } while ((pp = pp->p_friends) != tp); - prusage(cshout, &zru, &ru, &tetime, &ztime); -} - -/* - * dojobs - print all jobs - */ -void -/*ARGSUSED*/ -dojobs(Char **v, struct command *t) -{ - struct process *pp; - int flag, i; - - flag = NUMBER | NAME | REASON; - if (chkstop) - chkstop = 2; - if (*++v) { - if (v[1] || !eq(*v, STRml)) - stderror(ERR_JOBS); - flag |= FANCY | JOBDIR; - } - for (i = 1; i <= pmaxindex; i++) - for (pp = proclist.p_next; pp; pp = pp->p_next) - if (pp->p_index == i && pp->p_pid == pp->p_jobid) { - pp->p_flags &= ~PNEEDNOTE; - if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED))) - pflush(pp); - break; - } -} - -/* - * dofg - builtin - put the job into the foreground - */ -void -/*ARGSUSED*/ -dofg(Char **v, struct command *t) -{ - struct process *pp; - - okpcntl(); - ++v; - do { - pp = pfind(*v); - pstart(pp, 1); - pjwait(pp); - } while (*v && *++v); -} - -/* - * %... - builtin - put the job into the foreground - */ -void -/*ARGSUSED*/ -dofg1(Char **v, struct command *t) -{ - struct process *pp; - - okpcntl(); - pp = pfind(v[0]); - pstart(pp, 1); - pjwait(pp); -} - -/* - * dobg - builtin - put the job into the background - */ -void -/*ARGSUSED*/ -dobg(Char **v, struct command *t) -{ - struct process *pp; - - okpcntl(); - ++v; - do { - pp = pfind(*v); - pstart(pp, 0); - } while (*v && *++v); -} - -/* - * %... & - builtin - put the job into the background - */ -void -/*ARGSUSED*/ -dobg1(Char **v, struct command *t) -{ - struct process *pp; - - pp = pfind(v[0]); - pstart(pp, 0); -} - -/* - * dostop - builtin - stop the job - */ -void -/*ARGSUSED*/ -dostop(Char **v, struct command *t) -{ - pkill(++v, SIGSTOP); -} - -/* - * dokill - builtin - superset of kill (1) - */ -void -/*ARGSUSED*/ -dokill(Char **v, struct command *t) -{ - Char *signame; - char *name; - long signum; - char *ep; - - signum = SIGTERM; - v++; - if (v[0] && v[0][0] == '-') { - if (v[0][1] == 'l') { - if (v[1]) { - if (!Isdigit(v[1][0])) - stderror(ERR_NAME | ERR_BADSIG); - - signum = strtol(short2str(v[1]), &ep, 10); - if (signum < 0 || signum >= NSIG) - stderror(ERR_NAME | ERR_BADSIG); - else if (signum == 0) - (void)fputc('0', cshout); /* 0's symbolic name is '0' */ - else - (void)fprintf(cshout, "%s ", sys_signame[signum]); - } else { - for (signum = 1; signum < NSIG; signum++) { - (void)fprintf(cshout, "%s ", sys_signame[signum]); - if (signum == NSIG / 2) - (void)fputc('\n', cshout); - } - } - (void)fputc('\n', cshout); - return; - } - if (Isdigit(v[0][1])) { - signum = strtol(short2str(v[0] + 1), &ep, 10); - if (signum < 0 || signum >= NSIG || *ep) - stderror(ERR_NAME | ERR_BADSIG); - } - else { - if (v[0][1] == 's' && v[0][2] == '\0') - signame = *(++v); - else - signame = &v[0][1]; - - if (signame == NULL || v[1] == NULL) - stderror(ERR_NAME | ERR_TOOFEW); - - name = short2str(signame); - for (signum = 1; signum < NSIG; signum++) - if (!strcasecmp(sys_signame[signum], name) || - (!strncasecmp("SIG", name, 3) && /* skip "SIG" prefix */ - !strcasecmp(sys_signame[signum], name + 3))) - break; - - if (signum == NSIG) { - if (signame[0] == '0') - signum = 0; - else { - setname(vis_str(signame)); - stderror(ERR_NAME | ERR_UNKSIG); - } - } - } - v++; - } - pkill(v, (int)signum); -} - -static void -pkill(Char **v, int signum) -{ - struct process *pp, *np; - Char *cp; - sigset_t nsigset; - int err1, jobflags, pid; - char *ep; - - jobflags = 0; - err1 = 0; - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGCHLD); - if (setintr) - (void)sigaddset(&nsigset, SIGINT); - (void)sigprocmask(SIG_BLOCK, &nsigset, NULL); - gflag = 0, tglob(v); - if (gflag) { - v = globall(v); - if (v == 0) - stderror(ERR_NAME | ERR_NOMATCH); - } - else { - v = gargv = saveblk(v); - trim(v); - } - - while (v && (cp = *v)) { - if (*cp == '%') { - np = pp = pfind(cp); - do - jobflags |= np->p_flags; - while ((np = np->p_friends) != pp); - switch (signum) { - case SIGSTOP: - case SIGTSTP: - case SIGTTIN: - case SIGTTOU: - if ((jobflags & PRUNNING) == 0) { - (void)fprintf(csherr, "%s: Already suspended\n", - vis_str(cp)); - err1++; - goto cont; - } - break; - /* - * suspend a process, kill -CONT %, then type jobs; the shell - * says it is suspended, but it is running; thanks jaap.. - */ - case SIGCONT: - pstart(pp, 0); - goto cont; - } - if (kill(-pp->p_jobid, signum) < 0) { - (void)fprintf(csherr, "%s: %s\n", vis_str(cp), - strerror(errno)); - err1++; - } - if (signum == SIGTERM || signum == SIGHUP) - (void)kill(-pp->p_jobid, SIGCONT); - } - else if (!(Isdigit(*cp) || *cp == '-')) - stderror(ERR_NAME | ERR_JOBARGS); - else { - pid = (pid_t)strtoul(short2str(cp), &ep, 0); - if (*ep) { - (void)fprintf(csherr, "%s: Badly formed number\n", - short2str(cp)); - err1++; - goto cont; - } else if (kill(pid, signum) < 0) { - (void)fprintf(csherr, "%d: %s\n", pid, strerror(errno)); - err1++; - goto cont; - } - if (signum == SIGTERM || signum == SIGHUP) - (void)kill((pid_t) pid, SIGCONT); - } -cont: - v++; - } - if (gargv) - blkfree(gargv), gargv = 0; - (void)sigprocmask(SIG_UNBLOCK, &nsigset, NULL); - if (err1) - stderror(ERR_SILENT); -} - -/* - * pstart - start the job in foreground/background - */ -void -pstart(struct process *pp, int foregnd) -{ - struct process *np; - sigset_t osigset, nsigset; - long jobflags; - - jobflags = 0; - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGCHLD); - (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); - np = pp; - do { - jobflags |= np->p_flags; - if (np->p_flags & (PRUNNING | PSTOPPED)) { - np->p_flags |= PRUNNING; - np->p_flags &= ~PSTOPPED; - if (foregnd) - np->p_flags |= PFOREGND; - else - np->p_flags &= ~PFOREGND; - } - } while ((np = np->p_friends) != pp); - if (!foregnd) - pclrcurr(pp); - (void)pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND); - if (foregnd) - (void)tcsetpgrp(FSHTTY, pp->p_jobid); - if (jobflags & PSTOPPED) - (void)kill(-pp->p_jobid, SIGCONT); - (void)sigprocmask(SIG_SETMASK, &osigset, NULL); -} - -void -panystop(int neednl) -{ - struct process *pp; - - chkstop = 2; - for (pp = proclist.p_next; pp; pp = pp->p_next) - if (pp->p_flags & PSTOPPED) - stderror(ERR_STOPPED, neednl ? "\n" : ""); -} - -struct process * -pfind(Char *cp) -{ - struct process *pp, *np; - - if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) { - if (pcurrent == NULL) - stderror(ERR_NAME | ERR_JOBCUR); - return (pcurrent); - } - if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) { - if (pprevious == NULL) - stderror(ERR_NAME | ERR_JOBPREV); - return (pprevious); - } - if (Isdigit(cp[1])) { - int idx = atoi(short2str(cp + 1)); - - for (pp = proclist.p_next; pp; pp = pp->p_next) - if (pp->p_index == idx && pp->p_pid == pp->p_jobid) - return (pp); - stderror(ERR_NAME | ERR_NOSUCHJOB); - } - np = NULL; - for (pp = proclist.p_next; pp; pp = pp->p_next) - if (pp->p_pid == pp->p_jobid) { - if (cp[1] == '?') { - Char *dp; - - for (dp = pp->p_command; *dp; dp++) { - if (*dp != cp[2]) - continue; - if (prefix(cp + 2, dp)) - goto match; - } - } - else if (prefix(cp + 1, pp->p_command)) { - match: - if (np) - stderror(ERR_NAME | ERR_AMBIG); - np = pp; - } - } - if (np) - return (np); - stderror(ERR_NAME | (cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB)); - /* NOTREACHED */ -} - -/* - * pgetcurr - find most recent job that is not pp, preferably stopped - */ -static struct process * -pgetcurr(struct process *pp) -{ - struct process *np, *xp; - - xp = NULL; - for (np = proclist.p_next; np; np = np->p_next) - if (np != pcurrent && np != pp && np->p_pid && - np->p_pid == np->p_jobid) { - if (np->p_flags & PSTOPPED) - return (np); - if (xp == NULL) - xp = np; - } - return (xp); -} - -/* - * donotify - flag the job so as to report termination asynchronously - */ -void -/*ARGSUSED*/ -donotify(Char **v, struct command *t) -{ - struct process *pp; - - pp = pfind(*++v); - pp->p_flags |= PNOTIFY; -} - -/* - * Do the fork and whatever should be done in the child side that - * should not be done if we are not forking at all (like for simple builtin's) - * Also do everything that needs any signals fiddled with in the parent side - * - * Wanttty tells whether process and/or tty pgrps are to be manipulated: - * -1: leave tty alone; inherit pgrp from parent - * 0: already have tty; manipulate process pgrps only - * 1: want to claim tty; manipulate process and tty pgrps - * It is usually just the value of tpgrp. - */ - -int -pfork(struct command *t /* command we are forking for */, int wanttty) -{ - int pgrp, pid; - sigset_t osigset, nsigset; - int ignint; - - ignint = 0; - /* - * A child will be uninterruptible only under very special conditions. - * Remember that the semantics of '&' is implemented by disconnecting the - * process from the tty so signals do not need to ignored just for '&'. - * Thus signals are set to default action for children unless: we have had - * an "onintr -" (then specifically ignored) we are not playing with - * signals (inherit action) - */ - if (setintr) - ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) - || (gointr && eq(gointr, STRminus)); - /* - * Check for maximum nesting of 16 processes to avoid Forking loops - */ - if (child == 16) - stderror(ERR_NESTING, 16); - /* - * Hold SIGCHLD until we have the process installed in our table. - */ - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGCHLD); - (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); - while ((pid = fork()) < 0) - if (setintr == 0) - (void)sleep(FORKSLEEP); - else { - (void)sigprocmask(SIG_SETMASK, &osigset, NULL); - stderror(ERR_NOPROC); - } - if (pid == 0) { - settimes(); - pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); - pflushall(); - pcurrjob = NULL; - child++; - if (setintr) { - setintr = 0; /* until I think otherwise */ - /* - * Children just get blown away on SIGINT, SIGQUIT unless "onintr - * -" seen. - */ - (void)signal(SIGINT, ignint ? SIG_IGN : SIG_DFL); - (void)signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL); - if (wanttty >= 0) { - /* make stoppable */ - (void)signal(SIGTSTP, SIG_DFL); - (void)signal(SIGTTIN, SIG_DFL); - (void)signal(SIGTTOU, SIG_DFL); - } - (void)signal(SIGTERM, parterm); - } - else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) { - (void)signal(SIGINT, SIG_IGN); - (void)signal(SIGQUIT, SIG_IGN); - } - pgetty(wanttty, pgrp); - /* - * Nohup and nice apply only to NODE_COMMAND's but it would be nice - * (?!?) if you could say "nohup (foo;bar)" Then the parser would have - * to know about nice/nohup/time - */ - if (t->t_dflg & F_NOHUP) - (void)signal(SIGHUP, SIG_IGN); - if (t->t_dflg & F_NICE) - (void)setpriority(PRIO_PROCESS, 0, t->t_nice); - } - else { - if (wanttty >= 0) - (void)setpgid(pid, pcurrjob ? pcurrjob->p_jobid : pid); - palloc(pid, t); - (void)sigprocmask(SIG_SETMASK, &osigset, NULL); - } - - return (pid); -} - -static void -okpcntl(void) -{ - if (tpgrp == -1) - stderror(ERR_JOBCONTROL); - if (tpgrp == 0) - stderror(ERR_JOBCTRLSUB); - /* NOTREACHED */ -} - -/* - * if we don't have vfork(), things can still go in the wrong order - * resulting in the famous 'Stopped (tty output)'. But some systems - * don't permit the setpgid() call, (these are more recent secure - * systems such as ibm's aix). Then we'd rather print an error message - * than hang the shell! - * I am open to suggestions how to fix that. - */ -void -pgetty(int wanttty, int pgrp) -{ - sigset_t osigset, nsigset; - - /* - * christos: I am blocking the tty signals till I've set things - * correctly.... - */ - if (wanttty > 0) { - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGTSTP); - (void)sigaddset(&nsigset, SIGTTIN); - (void)sigaddset(&nsigset, SIGTTOU); - (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); - } - /* - * From: Michael Schroeder - * Don't check for tpgrp >= 0 so even non-interactive shells give - * background jobs process groups Same for the comparison in the other part - * of the #ifdef - */ - if (wanttty >= 0) - if (setpgid(0, pgrp) == -1) { - (void)fprintf(csherr, "csh: setpgid error.\n"); - xexit(0); - } - - if (wanttty > 0) { - (void)tcsetpgrp(FSHTTY, pgrp); - (void)sigprocmask(SIG_SETMASK, &osigset, NULL); - } - - if (tpgrp > 0) - tpgrp = 0; /* gave tty away */ -} diff --git a/bin/csh/proc.h b/bin/csh/proc.h deleted file mode 100644 index 783d29251..000000000 --- a/bin/csh/proc.h +++ /dev/null @@ -1,104 +0,0 @@ -/* $NetBSD: proc.h,v 1.14 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)proc.h 8.1 (Berkeley) 5/31/93 - */ - -#ifndef _PROC_H_ -#define _PROC_H_ - -/* - * Structure for each process the shell knows about: - * allocated and filled by pcreate. - * flushed by pflush; freeing always happens at top level - * so the interrupt level has less to worry about. - * processes are related to "friends" when in a pipeline; - * p_friends links makes a circular list of such jobs - */ -struct process { - struct process *p_next; /* next in global "proclist" */ - struct process *p_friends; /* next in job list (or self) */ - struct directory *p_cwd; /* cwd of the job (only in head) */ - int p_flags; /* various job status flags */ - int p_reason; /* reason for entering this state */ - int p_index; /* shorthand job index */ - pid_t p_pid; - pid_t p_jobid; /* pid of job leader */ - /* if a job is stopped/background p_jobid gives its pgrp */ - struct timespec p_btime; /* begin time */ - struct timespec p_etime; /* end time */ - struct rusage p_rusage; - Char *p_command; /* first PMAXLEN chars of command */ -}; - -/* flag values for p_flags */ -#define PRUNNING (1<<0) /* running */ -#define PSTOPPED (1<<1) /* stopped */ -#define PNEXITED (1<<2) /* normally exited */ -#define PAEXITED (1<<3) /* abnormally exited */ -#define PSIGNALED (1<<4) /* terminated by a signal != SIGINT */ -#define PNOTIFY (1<<5) /* notify async when done */ -#define PTIME (1<<6) /* job times should be printed */ -#define PAWAITED (1<<7) /* top level is waiting for it */ -#define PFOREGND (1<<8) /* started in shells pgrp */ -#define PDUMPED (1<<9) /* process dumped core */ -#define PERR (1<<10) /* diagnostic output also piped out */ -#define PPOU (1<<11) /* piped output */ -#define PREPORTED (1<<12) /* status has been reported */ -#define PINTERRUPTED (1<<13) /* job stopped via interrupt signal */ -#define PPTIME (1<<14) /* time individual process */ -#define PNEEDNOTE (1<<15) /* notify as soon as practical */ - -#define PALLSTATES (PRUNNING|PSTOPPED|PNEXITED|PAEXITED|PSIGNALED|PINTERRUPTED) - -#define PMAXLEN 80 - -/* defines for arguments to pprint */ -#define NUMBER 01 -#define NAME 02 -#define REASON 04 -#define AMPERSAND 010 -#define FANCY 020 -#define SHELLDIR 040 /* print shell's dir if not the same */ -#define JOBDIR 0100 /* print job's dir if not the same */ -#define AREASON 0200 - -struct process proclist; /* list head of all processes */ -int pnoprocesses; /* pchild found nothing to wait for */ - -struct process *pholdjob; /* one level stack of current jobs */ - -struct process *pcurrjob; /* current job */ -struct process *pcurrent; /* current job in table */ -struct process *pprevious; /* previous job in table */ - -int pmaxindex; /* current maximum job index */ - -#endif /* !_PROC_H_ */ diff --git a/bin/csh/sem.c b/bin/csh/sem.c deleted file mode 100644 index acda703d6..000000000 --- a/bin/csh/sem.c +++ /dev/null @@ -1,646 +0,0 @@ -/* $NetBSD: sem.c,v 1.29 2011/08/29 14:51:17 joerg Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)sem.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: sem.c,v 1.29 2011/08/29 14:51:17 joerg Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "csh.h" -#include "extern.h" -#include "proc.h" - -__dead static void vffree(int); -static Char *splicepipe(struct command *t, Char *); -static void doio(struct command *t, int *, int *); -static void chkclob(char *); - -void -execute(struct command *t, int wtty, int *pipein, int *pipeout) -{ - static sigset_t csigset, ocsigset; - static int nosigchld = 0, onosigchld = 0; - volatile int wanttty = wtty; - struct biltins * volatile bifunc; - int pv[2], pid; - sigset_t nsigset; - int forked; - - UNREGISTER(forked); - UNREGISTER(bifunc); - UNREGISTER(wanttty); - - forked = 0; - pid = 0; - - if (t == 0) - return; - - if (t->t_dflg & F_AMPERSAND) - wanttty = 0; - switch (t->t_dtyp) { - case NODE_COMMAND: - if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE) - (void)Strcpy(t->t_dcom[0], t->t_dcom[0] + 1); - if ((t->t_dflg & F_REPEAT) == 0) - Dfix(t); /* $ " ' \ */ - if (t->t_dcom[0] == 0) - return; - /* FALLTHROUGH */ - case NODE_PAREN: - if (t->t_dflg & F_PIPEOUT) - mypipe(pipeout); - /* - * Must do << early so parent will know where input pointer should be. - * If noexec then this is all we do. - */ - if (t->t_dflg & F_READ) { - (void)close(0); - heredoc(t->t_dlef); - if (noexec) - (void)close(0); - } - - set(STRstatus, Strsave(STR0)); - - /* - * This mess is the necessary kludge to handle the prefix builtins: - * nice, nohup, time. These commands can also be used by themselves, - * and this is not handled here. This will also work when loops are - * parsed. - */ - while (t->t_dtyp == NODE_COMMAND) - if (eq(t->t_dcom[0], STRnice)) { - if (t->t_dcom[1]) { - if (strchr("+-", t->t_dcom[1][0])) { - if (t->t_dcom[2]) { - setname("nice"); - t->t_nice = - getn(t->t_dcom[1]); - lshift(t->t_dcom, 2); - t->t_dflg |= F_NICE; - } - else - break; - } else { - t->t_nice = 4; - lshift(t->t_dcom, 1); - t->t_dflg |= F_NICE; - } - } else - break; - } else if (eq(t->t_dcom[0], STRnohup)) { - if (t->t_dcom[1]) { - t->t_dflg |= F_NOHUP; - lshift(t->t_dcom, 1); - } - else - break; - } else if (eq(t->t_dcom[0], STRtime)) { - if (t->t_dcom[1]) { - t->t_dflg |= F_TIME; - lshift(t->t_dcom, 1); - } - else - break; - } else - break; - - /* is it a command */ - if (t->t_dtyp == NODE_COMMAND) { - /* - * Check if we have a builtin function and remember which one. - */ - bifunc = isbfunc(t); - if (noexec && bifunc != NULL) { - /* - * Continue for builtins that are part of the scripting language - */ - if (bifunc->bfunct != dobreak && bifunc->bfunct != docontin && - bifunc->bfunct != doelse && bifunc->bfunct != doend && - bifunc->bfunct != doforeach && bifunc->bfunct != dogoto && - bifunc->bfunct != doif && bifunc->bfunct != dorepeat && - bifunc->bfunct != doswbrk && bifunc->bfunct != doswitch && - bifunc->bfunct != dowhile && bifunc->bfunct != dozip) - break; - } - } - else { /* not a command */ - bifunc = NULL; - if (noexec) - break; - } - - /* - * We fork only if we are timed, or are not the end of a parenthesized - * list and not a simple builtin function. Simple meaning one that is - * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not - * fork in some of these cases. - */ - /* - * Prevent forking cd, pushd, popd, chdir cause this will cause the - * shell not to change dir! - */ - if (bifunc && (bifunc->bfunct == dochngd || - bifunc->bfunct == dopushd || - bifunc->bfunct == dopopd)) - t->t_dflg &= ~(F_NICE); - if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 && - (!bifunc || t->t_dflg & - (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP)))) || - /* - * We have to fork for eval too. - */ - (bifunc && (t->t_dflg & (F_PIPEIN | F_PIPEOUT)) != 0 && - bifunc->bfunct == doeval)) { - if (t->t_dtyp == NODE_PAREN || - t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) { - forked++; - /* - * We need to block SIGCHLD here, so that if the process does - * not die before we can set the process group - */ - if (wanttty >= 0 && !nosigchld) { - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGCHLD); - (void)sigprocmask(SIG_BLOCK, &nsigset, &csigset); - nosigchld = 1; - } - - pid = pfork(t, wanttty); - if (pid == 0 && nosigchld) { - (void)sigprocmask(SIG_SETMASK, &csigset, NULL); - nosigchld = 0; - } - else if (pid != 0 && (t->t_dflg & F_AMPERSAND)) - backpid = pid; - - } - else { - int ochild, osetintr, ohaderr, odidfds; - int oSHIN, oSHOUT, oSHERR, oOLDSTD, otpgrp; - sigset_t osigset; - - /* - * Prepare for the vfork by saving everything that the child - * corrupts before it exec's. Note that in some signal - * implementations which keep the signal info in user space - * (e.g. Sun's) it will also be necessary to save and restore - * the current sigaction's for the signals the child touches - * before it exec's. - */ - if (wanttty >= 0 && !nosigchld && !noexec) { - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGCHLD); - (void)sigprocmask(SIG_BLOCK, &nsigset, &csigset); - nosigchld = 1; - } - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGCHLD); - (void)sigaddset(&nsigset, SIGINT); - (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); - ochild = child; - osetintr = setintr; - ohaderr = haderr; - odidfds = didfds; - oSHIN = SHIN; - oSHOUT = SHOUT; - oSHERR = SHERR; - oOLDSTD = OLDSTD; - otpgrp = tpgrp; - ocsigset = csigset; - onosigchld = nosigchld; - Vsav = Vdp = 0; - Vexpath = 0; - Vt = 0; - pid = vfork(); - - if (pid < 0) { - (void)sigprocmask(SIG_SETMASK, &osigset, NULL); - stderror(ERR_NOPROC); - } - forked++; - if (pid) { /* parent */ - child = ochild; - setintr = osetintr; - haderr = ohaderr; - didfds = odidfds; - SHIN = oSHIN; - SHOUT = oSHOUT; - SHERR = oSHERR; - OLDSTD = oOLDSTD; - tpgrp = otpgrp; - csigset = ocsigset; - nosigchld = onosigchld; - - xfree((ptr_t) Vsav); - Vsav = 0; - xfree((ptr_t) Vdp); - Vdp = 0; - xfree((ptr_t) Vexpath); - Vexpath = 0; - blkfree((Char **) Vt); - Vt = 0; - /* this is from pfork() */ - palloc(pid, t); - (void)sigprocmask(SIG_SETMASK, &osigset, NULL); - } - else { /* child */ - /* this is from pfork() */ - int pgrp; - int ignint = 0; - - if (nosigchld) { - (void)sigprocmask(SIG_SETMASK, &csigset, NULL); - nosigchld = 0; - } - - if (setintr) - ignint = - (tpgrp == -1 && - (t->t_dflg & F_NOINTERRUPT)) - || (gointr && eq(gointr, STRminus)); - pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); - child++; - if (setintr) { - setintr = 0; - if (ignint) { - (void)signal(SIGINT, SIG_IGN); - (void)signal(SIGQUIT, SIG_IGN); - } - else { - (void)signal(SIGINT, vffree); - (void)signal(SIGQUIT, SIG_DFL); - } - - if (wanttty >= 0) { - (void)signal(SIGTSTP, SIG_DFL); - (void)signal(SIGTTIN, SIG_DFL); - (void)signal(SIGTTOU, SIG_DFL); - } - - (void)signal(SIGTERM, parterm); - } - else if (tpgrp == -1 && - (t->t_dflg & F_NOINTERRUPT)) { - (void)signal(SIGINT, SIG_IGN); - (void)signal(SIGQUIT, SIG_IGN); - } - - pgetty(wanttty, pgrp); - if (t->t_dflg & F_NOHUP) - (void)signal(SIGHUP, SIG_IGN); - if (t->t_dflg & F_NICE) - (void)setpriority(PRIO_PROCESS, 0, t->t_nice); - } - - } - } - if (pid != 0) { - /* - * It would be better if we could wait for the whole job when we - * knew the last process had been started. Pwait, in fact, does - * wait for the whole job anyway, but this test doesn't really - * express our intentions. - */ - if (didfds == 0 && t->t_dflg & F_PIPEIN) { - (void)close(pipein[0]); - (void)close(pipein[1]); - } - if ((t->t_dflg & F_PIPEOUT) == 0) { - if (nosigchld) { - (void)sigprocmask(SIG_SETMASK, &csigset, NULL); - nosigchld = 0; - } - if ((t->t_dflg & F_AMPERSAND) == 0) - pwait(); - } - break; - } - doio(t, pipein, pipeout); - if (t->t_dflg & F_PIPEOUT) { - (void)close(pipeout[0]); - (void)close(pipeout[1]); - } - /* - * Perform a builtin function. If we are not forked, arrange for - * possible stopping - */ - if (bifunc) { - func(t, bifunc); - if (forked) - exitstat(); - break; - } - if (t->t_dtyp != NODE_PAREN) - doexec(NULL, t); - /* - * For () commands must put new 0,1,2 in FSH* and recurse - */ - (void) ioctl(OLDSTD = dcopy(0, FOLDSTD), FIOCLEX, NULL); - (void) ioctl(SHOUT = dcopy(1, FSHOUT), FIOCLEX, NULL); - (void) ioctl(SHERR = dcopy(2, FSHERR), FIOCLEX, NULL); - (void) close(SHIN); - - SHIN = -1; - didfds = 0; - wanttty = -1; - t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT; - execute(t->t_dspr, wanttty, NULL, NULL); - exitstat(); - /* NOTREACHED */ - case NODE_PIPE: - t->t_dcar->t_dflg |= F_PIPEOUT | - (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT)); - execute(t->t_dcar, wanttty, pipein, pv); - t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg & - (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT)); - if (wanttty > 0) - wanttty = 0; /* got tty already */ - execute(t->t_dcdr, wanttty, pv, pipeout); - break; - case NODE_LIST: - if (t->t_dcar) { - t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; - execute(t->t_dcar, wanttty, NULL, NULL); - /* - * In strange case of A&B make a new job after A - */ - if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr && - (t->t_dcdr->t_dflg & F_AMPERSAND) == 0) - pendjob(); - } - if (t->t_dcdr) { - t->t_dcdr->t_dflg |= t->t_dflg & - (F_NOFORK | F_NOINTERRUPT); - execute(t->t_dcdr, wanttty, NULL, NULL); - } - break; - case NODE_OR: - case NODE_AND: - if (t->t_dcar) { - t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; - execute(t->t_dcar, wanttty, NULL, NULL); - if ((getn(value(STRstatus)) == 0) != - (t->t_dtyp == NODE_AND)) - return; - } - if (t->t_dcdr) { - t->t_dcdr->t_dflg |= t->t_dflg & - (F_NOFORK | F_NOINTERRUPT); - execute(t->t_dcdr, wanttty, NULL, NULL); - } - break; - } - /* - * Fall through for all breaks from switch - * - * If there will be no more executions of this command, flush all file - * descriptors. Places that turn on the F_REPEAT bit are responsible for - * doing donefds after the last re-execution - */ - if (didfds && !(t->t_dflg & F_REPEAT)) - donefds(); -} - -static void -vffree(int i) -{ - Char **v; - - if ((v = gargv) != NULL) { - gargv = 0; - xfree((ptr_t) v); - } - if ((v = pargv) != NULL) { - pargv = 0; - xfree((ptr_t) v); - } - _exit(i); - /* NOTREACHED */ -} - -/* - * Expand and glob the words after an i/o redirection. - * If more than one word is generated, then update the command vector. - * - * This is done differently in all the shells: - * 1. in the bourne shell and ksh globbing is not performed - * 2. Bash/csh say ambiguous - * 3. zsh does i/o to/from all the files - * 4. itcsh concatenates the words. - * - * I don't know what is best to do. I think that Ambiguous is better - * than restructuring the command vector, because the user can get - * unexpected results. In any case, the command vector restructuring - * code is present and the user can choose it by setting noambiguous - */ -static Char * -splicepipe(struct command *t, Char *cp /* word after < or > */) -{ - Char *blk[2]; - - if (adrof(STRnoambiguous)) { - Char **pv; - - blk[0] = Dfix1(cp); /* expand $ */ - blk[1] = NULL; - - gflag = 0, tglob(blk); - if (gflag) { - pv = globall(blk); - if (pv == NULL) { - setname(vis_str(blk[0])); - xfree((ptr_t) blk[0]); - stderror(ERR_NAME | ERR_NOMATCH); - /* NOTREACHED */ - } - gargv = NULL; - if (pv[1] != NULL) { /* we need to fix the command vector */ - Char **av = blkspl(t->t_dcom, &pv[1]); - xfree((ptr_t) t->t_dcom); - t->t_dcom = av; - } - xfree((ptr_t) blk[0]); - blk[0] = pv[0]; - xfree((ptr_t) pv); - } - } - else { - blk[0] = globone(blk[1] = Dfix1(cp), G_ERROR); - xfree((ptr_t) blk[1]); - } - return(blk[0]); -} - -/* - * Perform io redirection. - * We may or maynot be forked here. - */ -static void -doio(struct command *t, int *pipein, int *pipeout) -{ - Char *cp; - int fd, flags; - - flags = t->t_dflg; - if (didfds || (flags & F_REPEAT)) - return; - if ((flags & F_READ) == 0) {/* F_READ already done */ - if (t->t_dlef) { - char tmp[MAXPATHLEN+1]; - - /* - * so < /dev/std{in,out,err} work - */ - (void)dcopy(SHIN, 0); - (void)dcopy(SHOUT, 1); - (void)dcopy(SHERR, 2); - cp = splicepipe(t, t->t_dlef); - (void)strlcpy(tmp, short2str(cp), sizeof(tmp)); - xfree((ptr_t) cp); - if ((fd = open(tmp, O_RDONLY)) < 0) { - stderror(ERR_SYSTEM, tmp, strerror(errno)); - /* NOTREACHED */ - } - (void)dmove(fd, 0); - } - else if (flags & F_PIPEIN) { - (void)close(0); - (void)dup(pipein[0]); - (void)close(pipein[0]); - (void)close(pipein[1]); - } - else if ((flags & F_NOINTERRUPT) && tpgrp == -1) { - (void)close(0); - (void)open(_PATH_DEVNULL, O_RDONLY); - } - else { - (void)close(0); - (void)dup(OLDSTD); - (void)ioctl(0, FIONCLEX, NULL); - } - } - if (t->t_drit) { - char tmp[MAXPATHLEN+1]; - - cp = splicepipe(t, t->t_drit); - (void)strlcpy(tmp, short2str(cp), sizeof(tmp)); - xfree((ptr_t) cp); - /* - * so > /dev/std{out,err} work - */ - (void)dcopy(SHOUT, 1); - (void)dcopy(SHERR, 2); - if ((flags & F_APPEND) && -#ifdef O_APPEND - (fd = open(tmp, O_WRONLY | O_APPEND)) >= 0); -#else - (fd = open(tmp, O_WRONLY)) >= 0) - (void)lseek(1, (off_t) 0, SEEK_END); -#endif - else { - if (!(flags & F_OVERWRITE) && adrof(STRnoclobber)) { - if (flags & F_APPEND) { - stderror(ERR_SYSTEM, tmp, strerror(errno)); - /* NOTREACHED */ - } - chkclob(tmp); - } - if ((fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) { - stderror(ERR_SYSTEM, tmp, strerror(errno)); - /* NOTREACHED */ - } - } - (void)dmove(fd, 1); - } - else if (flags & F_PIPEOUT) { - (void)close(1); - (void)dup(pipeout[1]); - } - else { - (void)close(1); - (void)dup(SHOUT); - (void)ioctl(1, FIONCLEX, NULL); - } - - (void)close(2); - if (flags & F_STDERR) { - (void)dup(1); - } - else { - (void)dup(SHERR); - (void)ioctl(2, FIONCLEX, NULL); - } - didfds = 1; -} - -void -mypipe(int *pv) -{ - if (pipe(pv) < 0) - goto oops; - pv[0] = dmove(pv[0], -1); - pv[1] = dmove(pv[1], -1); - if (pv[0] >= 0 && pv[1] >= 0) - return; -oops: - stderror(ERR_PIPE); - /* NOTREACHED */ -} - -static void -chkclob(char *cp) -{ - struct stat stb; - - if (stat(cp, &stb) < 0) - return; - if (S_ISCHR(stb.st_mode)) - return; - stderror(ERR_EXISTS, cp); - /* NOTREACHED */ -} diff --git a/bin/csh/set.c b/bin/csh/set.c deleted file mode 100644 index 9b73abd3e..000000000 --- a/bin/csh/set.c +++ /dev/null @@ -1,820 +0,0 @@ -/* $NetBSD: set.c,v 1.33 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)set.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: set.c,v 1.33 2013/07/16 17:47:43 christos Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include - -#ifndef SHORT_STRINGS -#include -#endif /* SHORT_STRINGS */ - -#include "csh.h" -#include "extern.h" - -static Char *getinx(Char *, int *); -static void asx(Char *, int, Char *); -static struct varent *getvx(Char *, int); -static Char *xset(Char *, Char ***); -static Char *operate(int, Char *, Char *); -static void putn1(int); -static struct varent *madrof(Char *, struct varent *); -static void unsetv1(struct varent *); -static void exportpath(Char **); -static void balance(struct varent *, int, int); - -/* - * C Shell - */ - -static void -update_vars(Char *vp) -{ - if (eq(vp, STRpath)) { - struct varent *pt = adrof(STRpath); - if (pt == NULL) - stderror(ERR_NAME | ERR_UNDVAR); - else { - exportpath(pt->vec); - dohash(NULL, NULL); - } - } - else if (eq(vp, STRhistchars)) { - Char *pn = value(STRhistchars); - - HIST = *pn++; - HISTSUB = *pn; - } - else if (eq(vp, STRuser)) { - Setenv(STRUSER, value(vp)); - Setenv(STRLOGNAME, value(vp)); - } - else if (eq(vp, STRwordchars)) { - word_chars = value(vp); - } - else if (eq(vp, STRterm)) - Setenv(STRTERM, value(vp)); - else if (eq(vp, STRhome)) { - Char *cp; - - cp = Strsave(value(vp)); /* get the old value back */ - - /* - * convert to canonical pathname (possibly resolving symlinks) - */ - cp = dcanon(cp, cp); - - set(vp, Strsave(cp)); /* have to save the new val */ - - /* and now mirror home with HOME */ - Setenv(STRHOME, cp); - /* fix directory stack for new tilde home */ - dtilde(); - xfree((ptr_t)cp); - } -#ifdef FILEC - else if (eq(vp, STRfilec)) - filec = 1; -#endif -#ifdef EDIT - else if (eq(vp, STRedit)) { - HistEvent ev; - editing = 1; - el = el_init_fd(getprogname(), cshin, cshout, csherr, - SHIN, SHOUT, SHERR); - el_set(el, EL_EDITOR, "emacs"); - el_set(el, EL_PROMPT, printpromptstr); - hi = history_init(); - history(hi, &ev, H_SETSIZE, getn(value(STRhistory))); - loadhist(Histlist.Hnext); - el_set(el, EL_HIST, history, hi); - } -#endif -} - -void -/*ARGSUSED*/ -doset(Char **v, struct command *t) -{ - Char op, *p, **vecp, *vp; - int subscr = 0; /* XXX: GCC */ - int hadsub; - - v++; - p = *v++; - if (p == 0) { - prvars(); - return; - } - do { - hadsub = 0; - vp = p; - if (letter(*p)) - for (; alnum(*p); p++) - continue; - if (vp == p || !letter(*vp)) - stderror(ERR_NAME | ERR_VARBEGIN); - if ((p - vp) > MAXVARLEN) - stderror(ERR_NAME | ERR_VARTOOLONG); - if (*p == '[') { - hadsub++; - p = getinx(p, &subscr); - } - if ((op = *p) != '\0') { - *p++ = 0; - if (*p == 0 && *v && **v == '(') - p = *v++; - } - else if (*v && eq(*v, STRequal)) { - op = '=', v++; - if (*v) - p = *v++; - } - if (op && op != '=') - stderror(ERR_NAME | ERR_SYNTAX); - if (eq(p, STRLparen)) { - Char **e = v; - - if (hadsub) - stderror(ERR_NAME | ERR_SYNTAX); - for (;;) { - if (!*e) - stderror(ERR_NAME | ERR_MISSING, ')'); - if (**e == ')') - break; - e++; - } - p = *e; - *e = 0; - vecp = saveblk(v); - set1(vp, vecp, &shvhed); - *e = p; - v = e + 1; - } - else if (hadsub) - asx(vp, subscr, Strsave(p)); - else - set(vp, Strsave(p)); - update_vars(vp); - } while ((p = *v++) != NULL); -} - -static Char * -getinx(Char *cp, int *ip) -{ - *ip = 0; - *cp++ = 0; - while (*cp && Isdigit(*cp)) - *ip = *ip * 10 + *cp++ - '0'; - if (*cp++ != ']') - stderror(ERR_NAME | ERR_SUBSCRIPT); - return (cp); -} - -static void -asx(Char *vp, int subscr, Char *p) -{ - struct varent *v; - - v = getvx(vp, subscr); - xfree((ptr_t) v->vec[subscr - 1]); - v->vec[subscr - 1] = globone(p, G_APPEND); -} - -static struct varent * -getvx(Char *vp, int subscr) -{ - struct varent *v; - - v = adrof(vp); - if (v == 0) - udvar(vp); - if (subscr < 1 || subscr > blklen(v->vec)) - stderror(ERR_NAME | ERR_RANGE); - return (v); -} - -void -/*ARGSUSED*/ -dolet(Char **v, struct command *t) -{ - Char c, op, *p, *vp; - int subscr = 0; /* XXX: GCC */ - int hadsub; - - v++; - p = *v++; - if (p == 0) { - prvars(); - return; - } - do { - hadsub = 0; - vp = p; - if (letter(*p)) - for (; alnum(*p); p++) - continue; - if (vp == p || !letter(*vp)) - stderror(ERR_NAME | ERR_VARBEGIN); - if ((p - vp) > MAXVARLEN) - stderror(ERR_NAME | ERR_VARTOOLONG); - if (*p == '[') { - hadsub++; - p = getinx(p, &subscr); - } - if (*p == 0 && *v) - p = *v++; - if ((op = *p) != '\0') - *p++ = 0; - else - stderror(ERR_NAME | ERR_ASSIGN); - - if (*p == '\0' && *v == NULL) - stderror(ERR_NAME | ERR_ASSIGN); - - vp = Strsave(vp); - if (op == '=') { - c = '='; - p = xset(p, &v); - } - else { - c = *p++; - if (any("+-", c)) { - if (c != op || *p) - stderror(ERR_NAME | ERR_UNKNOWNOP); - p = Strsave(STR1); - } - else { - if (any("<>", op)) { - if (c != op) - stderror(ERR_NAME | ERR_UNKNOWNOP); - c = *p++; - stderror(ERR_NAME | ERR_SYNTAX); - } - if (c != '=') - stderror(ERR_NAME | ERR_UNKNOWNOP); - p = xset(p, &v); - } - } - if (op == '=') { - if (hadsub) - asx(vp, subscr, p); - else - set(vp, p); - } else if (hadsub) { - struct varent *gv = getvx(vp, subscr); - - asx(vp, subscr, operate(op, gv->vec[subscr - 1], p)); - } - else - set(vp, operate(op, value(vp), p)); - if (eq(vp, STRpath)) { - struct varent *pt = adrof(STRpath); - if (pt == NULL) - stderror(ERR_NAME | ERR_UNDVAR); - else { - exportpath(pt->vec); - dohash(NULL, NULL); - } - } - xfree((ptr_t) vp); - if (c != '=') - xfree((ptr_t) p); - } while ((p = *v++) != NULL); -} - -static Char * -xset(Char *cp, Char ***vp) -{ - Char *dp; - - if (*cp) { - dp = Strsave(cp); - --(*vp); - xfree((ptr_t) ** vp); - **vp = dp; - } - return (putn(expr(vp))); -} - -static Char * -operate(int op, Char *vp, Char *p) -{ - Char opr[2], **v, *vec[5], **vecp; - int i; - - v = vec; - vecp = v; - if (op != '=') { - if (*vp) - *v++ = vp; - opr[0] = (Char)op; - opr[1] = 0; - *v++ = opr; - if (op == '<' || op == '>') - *v++ = opr; - } - *v++ = p; - *v++ = 0; - i = expr(&vecp); - if (*vecp) - stderror(ERR_NAME | ERR_EXPRESSION); - return (putn(i)); -} - -static Char *putp; - -Char * -putn(int n) -{ - static Char numbers[15]; - - putp = numbers; - if (n < 0) { - n = -n; - *putp++ = '-'; - } - if ((unsigned int)n == 0x80000000U) { - *putp++ = '2'; - n = 147483648; - } - putn1(n); - *putp = 0; - return (Strsave(numbers)); -} - -static void -putn1(int n) -{ - if (n > 9) - putn1(n / 10); - *putp++ = (Char)(n % 10 + '0'); -} - -int -getn(Char *cp) -{ - int n, sign; - - sign = 0; - if (cp[0] == '+' && cp[1]) - cp++; - if (*cp == '-') { - sign++; - cp++; - if (!Isdigit(*cp)) - stderror(ERR_NAME | ERR_BADNUM); - } - n = 0; - while (Isdigit(*cp)) - n = n * 10 + *cp++ - '0'; - if (*cp) - stderror(ERR_NAME | ERR_BADNUM); - return (sign ? -n : n); -} - -Char * -value1(Char *var, struct varent *head) -{ - struct varent *vp; - - vp = adrof1(var, head); - return (vp == 0 || vp->vec[0] == 0 ? STRNULL : vp->vec[0]); -} - -static struct varent * -madrof(Char *pat, struct varent *vp) -{ - struct varent *vp1; - - for (; vp; vp = vp->v_right) { - if (vp->v_left && (vp1 = madrof(pat, vp->v_left))) - return vp1; - if (Gmatch(vp->v_name, pat)) - return vp; - } - return vp; -} - -struct varent * -adrof1(Char *name, struct varent *v) -{ - int cmp; - - v = v->v_left; - while (v && ((cmp = *name - *v->v_name) || - (cmp = Strcmp(name, v->v_name)))) - if (cmp < 0) - v = v->v_left; - else - v = v->v_right; - return v; -} - -/* - * The caller is responsible for putting value in a safe place - */ -void -set(Char *var, Char *val) -{ - Char **vec; - - vec = xmalloc(2 * sizeof(*vec)); - vec[0] = val; - vec[1] = 0; - set1(var, vec, &shvhed); -} - -void -set1(Char *var, Char **vec, struct varent *head) -{ - Char **oldv; - - oldv = vec; - gflag = 0; - tglob(oldv); - if (gflag) { - vec = globall(oldv); - if (vec == 0) { - blkfree(oldv); - stderror(ERR_NAME | ERR_NOMATCH); - } - blkfree(oldv); - gargv = 0; - } - setq(var, vec, head); -} - -void -setq(Char *name, Char **vec, struct varent *p) -{ - struct varent *c; - int f; - - f = 0; /* tree hangs off the header's left link */ - while ((c = p->v_link[f]) != NULL) { - if ((f = *name - *c->v_name) == 0 && - (f = Strcmp(name, c->v_name)) == 0) { - blkfree(c->vec); - goto found; - } - p = c; - f = f > 0; - } - p->v_link[f] = c = xmalloc(sizeof(*c)); - c->v_name = Strsave(name); - c->v_bal = 0; - c->v_left = c->v_right = 0; - c->v_parent = p; - balance(p, f, 0); -found: - trim(c->vec = vec); -} - -void -/*ARGSUSED*/ -unset(Char **v, struct command *t) -{ - unset1(v, &shvhed); - if (adrof(STRhistchars) == 0) { - HIST = '!'; - HISTSUB = '^'; - } - else if (adrof(STRwordchars) == 0) - word_chars = STR_WORD_CHARS; -#ifdef FILEC - else if (adrof(STRfilec) == 0) - filec = 0; -#endif -#ifdef EDIT - else if (adrof(STRedit) == 0) { - el_end(el); - history_end(hi); - el = NULL; - hi = NULL; - editing = 0; - } -#endif -} - -void -unset1(Char *v[], struct varent *head) -{ - struct varent *vp; - int cnt; - - while (*++v) { - cnt = 0; - while ((vp = madrof(*v, head->v_left)) != NULL) - unsetv1(vp), cnt++; - if (cnt == 0) - setname(vis_str(*v)); - } -} - -void -unsetv(Char *var) -{ - struct varent *vp; - - if ((vp = adrof1(var, &shvhed)) == 0) - udvar(var); - unsetv1(vp); -} - -static void -unsetv1(struct varent *p) -{ - struct varent *c, *pp; - int f; - - /* - * Free associated memory first to avoid complications. - */ - blkfree(p->vec); - xfree((ptr_t) p->v_name); - /* - * If p is missing one child, then we can move the other into where p is. - * Otherwise, we find the predecessor of p, which is guaranteed to have no - * right child, copy it into p, and move its left child into it. - */ - if (p->v_right == 0) - c = p->v_left; - else if (p->v_left == 0) - c = p->v_right; - else { - for (c = p->v_left; c->v_right; c = c->v_right) - continue; - p->v_name = c->v_name; - p->vec = c->vec; - p = c; - c = p->v_left; - } - /* - * Move c into where p is. - */ - pp = p->v_parent; - f = pp->v_right == p; - if ((pp->v_link[f] = c) != NULL) - c->v_parent = pp; - /* - * Free the deleted node, and rebalance. - */ - xfree((ptr_t) p); - balance(pp, f, 1); -} - -void -setNS(Char *cp) -{ - set(cp, Strsave(STRNULL)); -} - -void -/*ARGSUSED*/ -shift(Char **v, struct command *t) -{ - struct varent *argv; - Char *name; - - v++; - name = *v; - if (name == 0) - name = STRargv; - else - (void) strip(name); - argv = adrof(name); - if (argv == 0) - udvar(name); - if (argv->vec[0] == 0) - stderror(ERR_NAME | ERR_NOMORE); - lshift(argv->vec, 1); - update_vars(name); -} - -static void -exportpath(Char **val) -{ - Char exppath[BUFSIZE]; - - exppath[0] = 0; - if (val) - while (*val) { - if (Strlen(*val) + Strlen(exppath) + 2 > BUFSIZE) { - (void)fprintf(csherr, - "Warning: ridiculously long PATH truncated\n"); - break; - } - (void)Strcat(exppath, *val++); - if (*val == 0 || eq(*val, STRRparen)) - break; - (void)Strcat(exppath, STRcolon); - } - Setenv(STRPATH, exppath); -} - -#ifndef lint - /* - * Lint thinks these have null effect - */ - /* macros to do single rotations on node p */ -#define rright(p) (\ - t = (p)->v_left,\ - (t)->v_parent = (p)->v_parent,\ - ((p)->v_left = t->v_right) ? (t->v_right->v_parent = (p)) : 0,\ - (t->v_right = (p))->v_parent = t,\ - (p) = t) -#define rleft(p) (\ - t = (p)->v_right,\ - (t)->v_parent = (p)->v_parent,\ - ((p)->v_right = t->v_left) ? (t->v_left->v_parent = (p)) : 0,\ - (t->v_left = (p))->v_parent = t,\ - (p) = t) -#else -struct varent * -rleft(struct varent *p) -{ - return (p); -} -struct varent * -rright(struct varent *p) -{ - return (p); -} -#endif /* ! lint */ - - -/* - * Rebalance a tree, starting at p and up. - * F == 0 means we've come from p's left child. - * D == 1 means we've just done a delete, otherwise an insert. - */ -static void -balance(struct varent *p, int f, int d) -{ - struct varent *pp; - -#ifndef lint - struct varent *t; /* used by the rotate macros */ - -#endif - int ff; - - /* - * Ok, from here on, p is the node we're operating on; pp is its parent; f - * is the branch of p from which we have come; ff is the branch of pp which - * is p. - */ - for (; (pp = p->v_parent) != NULL; p = pp, f = ff) { - ff = pp->v_right == p; - if (f ^ d) { /* right heavy */ - switch (p->v_bal) { - case -1: /* was left heavy */ - p->v_bal = 0; - break; - case 0: /* was balanced */ - p->v_bal = 1; - break; - case 1: /* was already right heavy */ - switch (p->v_right->v_bal) { - case 1: /* single rotate */ - pp->v_link[ff] = rleft(p); - p->v_left->v_bal = 0; - p->v_bal = 0; - break; - case 0: /* single rotate */ - pp->v_link[ff] = rleft(p); - p->v_left->v_bal = 1; - p->v_bal = -1; - break; - case -1: /* double rotate */ - (void) rright(p->v_right); - pp->v_link[ff] = rleft(p); - p->v_left->v_bal = - p->v_bal < 1 ? 0 : -1; - p->v_right->v_bal = - p->v_bal > -1 ? 0 : 1; - p->v_bal = 0; - break; - } - break; - } - } - else { /* left heavy */ - switch (p->v_bal) { - case 1: /* was right heavy */ - p->v_bal = 0; - break; - case 0: /* was balanced */ - p->v_bal = -1; - break; - case -1: /* was already left heavy */ - switch (p->v_left->v_bal) { - case -1: /* single rotate */ - pp->v_link[ff] = rright(p); - p->v_right->v_bal = 0; - p->v_bal = 0; - break; - case 0: /* single rotate */ - pp->v_link[ff] = rright(p); - p->v_right->v_bal = -1; - p->v_bal = 1; - break; - case 1: /* double rotate */ - (void) rleft(p->v_left); - pp->v_link[ff] = rright(p); - p->v_left->v_bal = - p->v_bal < 1 ? 0 : -1; - p->v_right->v_bal = - p->v_bal > -1 ? 0 : 1; - p->v_bal = 0; - break; - } - break; - } - } - /* - * If from insert, then we terminate when p is balanced. If from - * delete, then we terminate when p is unbalanced. - */ - if ((p->v_bal == 0) ^ d) - break; - } -} - -void -plist(struct varent *p) -{ - struct varent *c; - sigset_t nsigset; - int len; - - if (setintr) { - sigemptyset(&nsigset); - (void)sigaddset(&nsigset, SIGINT); - (void)sigprocmask(SIG_UNBLOCK, &nsigset, NULL); - } - - for (;;) { - while (p->v_left) - p = p->v_left; -x: - if (p->v_parent == 0) /* is it the header? */ - return; - len = blklen(p->vec); - (void)fprintf(cshout, "%s\t", short2str(p->v_name)); - if (len != 1) - (void)fputc('(', cshout); - blkpr(cshout, p->vec); - if (len != 1) - (void)fputc(')', cshout); - (void)fputc('\n', cshout); - if (p->v_right) { - p = p->v_right; - continue; - } - do { - c = p; - p = p->v_parent; - } while (p->v_right == c); - goto x; - } -} diff --git a/bin/csh/str.c b/bin/csh/str.c deleted file mode 100644 index e828cc42b..000000000 --- a/bin/csh/str.c +++ /dev/null @@ -1,441 +0,0 @@ -/* $NetBSD: str.c,v 1.15 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)str.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: str.c,v 1.15 2013/07/16 17:47:43 christos Exp $"); -#endif -#endif /* not lint */ - -#define MALLOC_INCR 128 - -/* - * tc.str.c: Short string package - * This has been a lesson of how to write buggy code! - */ - -#include - -#include -#include - -#include "csh.h" -#include "extern.h" - -#ifdef SHORT_STRINGS - -Char ** -blk2short(char **src) -{ - Char **dst, **sdst; - size_t n; - - /* - * Count - */ - for (n = 0; src[n] != NULL; n++) - continue; - sdst = dst = xmalloc((size_t)((n + 1) * sizeof(*dst))); - - for (; *src != NULL; src++) - *dst++ = SAVE(*src); - *dst = NULL; - return (sdst); -} - -char ** -short2blk(Char *const *src) -{ - char **dst, **sdst; - size_t n; - - /* - * Count - */ - for (n = 0; src[n] != NULL; n++) - continue; - sdst = dst = xmalloc((size_t)((n + 1) * sizeof(*dst))); - - for (; *src != NULL; src++) - *dst++ = strsave(short2str(*src)); - *dst = NULL; - return (sdst); -} - -Char * -str2short(const char *src) -{ - static Char *sdst; - Char *dst, *edst; - static size_t dstsize = 0; - - if (src == NULL) - return (NULL); - - if (sdst == (NULL)) { - dstsize = MALLOC_INCR; - sdst = xmalloc((size_t)dstsize * sizeof(*sdst)); - } - - dst = sdst; - edst = &dst[dstsize]; - while (*src) { - *dst++ = (Char) ((unsigned char) *src++); - if (dst == edst) { - dstsize += MALLOC_INCR; - sdst = xrealloc((ptr_t)sdst, - (size_t)dstsize * sizeof(*sdst)); - edst = &sdst[dstsize]; - dst = &edst[-MALLOC_INCR]; - } - } - *dst = 0; - return (sdst); -} - -char * -short2str(const Char *src) -{ - static char *sdst = NULL; - static size_t dstsize = 0; - char *dst, *edst; - - if (src == NULL) - return (NULL); - - if (sdst == NULL) { - dstsize = MALLOC_INCR; - sdst = xmalloc((size_t)dstsize * sizeof(*sdst)); - } - dst = sdst; - edst = &dst[dstsize]; - while (*src) { - *dst++ = (char) *src++; - if (dst == edst) { - dstsize += MALLOC_INCR; - sdst = xrealloc((ptr_t)sdst, - (size_t)dstsize * sizeof(*sdst)); - edst = &sdst[dstsize]; - dst = &edst[-MALLOC_INCR]; - } - } - *dst = 0; - return (sdst); -} - -Char * -s_strcpy(Char *dst, const Char *src) -{ - Char *sdst; - - sdst = dst; - while ((*dst++ = *src++) != '\0') - continue; - return (sdst); -} - -Char * -s_strncpy(Char *dst, const Char *src, size_t n) -{ - Char *sdst; - - if (n == 0) - return(dst); - - sdst = dst; - do - if ((*dst++ = *src++) == '\0') { - while (--n != 0) - *dst++ = '\0'; - return(sdst); - } - while (--n != 0); - return (sdst); -} - -Char * -s_strcat(Char *dst, const Char *src) -{ - short *sdst; - - sdst = dst; - while (*dst++) - continue; - --dst; - while ((*dst++ = *src++) != '\0') - continue; - return (sdst); -} - -#ifdef NOTUSED -Char * -s_strncat(Char *dst, Char *src, size_t n) -{ - Char *sdst; - - if (n == 0) - return (dst); - - sdst = dst; - - while (*dst++) - continue; - --dst; - - do - if ((*dst++ = *src++) == '\0') - return(sdst); - while (--n != 0) - continue; - - *dst = '\0'; - return (sdst); -} - -#endif - -Char * -s_strchr(const Char *str, int ch) -{ - do - if (*str == ch) - return __UNCONST(str); - while (*str++); - return (NULL); -} - -Char * -s_strrchr(const Char *str, int ch) -{ - const Char *rstr; - - rstr = NULL; - do - if (*str == ch) - rstr = str; - while (*str++); - return __UNCONST(rstr); -} - -size_t -s_strlen(const Char *str) -{ - size_t n; - - for (n = 0; *str++; n++) - continue; - return (n); -} - -int -s_strcmp(const Char *str1, const Char *str2) -{ - for (; *str1 && *str1 == *str2; str1++, str2++) - continue; - /* - * The following case analysis is necessary so that characters which look - * negative collate low against normal characters but high against the - * end-of-string NUL. - */ - if (*str1 == '\0' && *str2 == '\0') - return (0); - else if (*str1 == '\0') - return (-1); - else if (*str2 == '\0') - return (1); - else - return (*str1 - *str2); -} - -int -s_strncmp(const Char *str1, const Char *str2, size_t n) -{ - if (n == 0) - return (0); - do { - if (*str1 != *str2) { - /* - * The following case analysis is necessary so that characters - * which look negative collate low against normal characters - * but high against the end-of-string NUL. - */ - if (*str1 == '\0') - return (-1); - else if (*str2 == '\0') - return (1); - else - return (*str1 - *str2); - } - if (*str1 == '\0') - return(0); - str1++, str2++; - } while (--n != 0); - return(0); -} - -Char * -s_strsave(const Char *s) -{ - const Char *p; - Char *n; - - if (s == 0) - s = STRNULL; - for (p = s; *p++;) - continue; - p = n = xmalloc((size_t)(p - s) * sizeof(*n)); - while ((*n++ = *s++) != '\0') - continue; - return __UNCONST(p); -} - -Char * -s_strspl(const Char *cp, const Char *dp) -{ - Char *ep, *d; - const Char *p, *q; - - if (!cp) - cp = STRNULL; - if (!dp) - dp = STRNULL; - for (p = cp; *p++;) - continue; - for (q = dp; *q++;) - continue; - ep = xmalloc((size_t)((p - cp) + (q - dp) - 1) * sizeof(*ep)); - for (d = ep, q = cp; (*d++ = *q++) != '\0';) - continue; - for (d--, q = dp; (*d++ = *q++) != '\0';) - continue; - return (ep); -} - -Char * -s_strend(const Char *cp) -{ - if (!cp) - return __UNCONST(cp); - while (*cp) - cp++; - return __UNCONST(cp); -} - -Char * -s_strstr(const Char *s, const Char *t) -{ - do { - const Char *ss = s; - const Char *tt = t; - - do - if (*tt == '\0') - return __UNCONST(s); - while (*ss++ == *tt++); - } while (*s++ != '\0'); - return (NULL); -} -#endif /* SHORT_STRINGS */ - -char * -short2qstr(const Char *src) -{ - static char *sdst = NULL; - static size_t dstsize = 0; - char *dst, *edst; - - if (src == NULL) - return (NULL); - - if (sdst == NULL) { - dstsize = MALLOC_INCR; - sdst = xmalloc((size_t)dstsize * sizeof(*sdst)); - } - dst = sdst; - edst = &dst[dstsize]; - while (*src) { - - if (*src & QUOTE) { - *dst++ = '\\'; - if (dst == edst) { - dstsize += MALLOC_INCR; - sdst = xrealloc((ptr_t) sdst, - (size_t)dstsize * sizeof(*sdst)); - edst = &sdst[dstsize]; - dst = &edst[-MALLOC_INCR]; - } - } - *dst++ = (char) *src++; - if (dst == edst) { - dstsize += MALLOC_INCR; - sdst = xrealloc((ptr_t) sdst, - (size_t)dstsize * sizeof(*sdst)); - edst = &sdst[dstsize]; - dst = &edst[-MALLOC_INCR]; - } - } - *dst = 0; - return (sdst); -} - -/* - * XXX: Should we worry about QUOTE'd chars? - */ -char * -vis_str(const Char *cp) -{ - static char *sdst = NULL; - static size_t dstsize = 0; - const Char *dp; - size_t n; - - if (cp == NULL) - return (NULL); - - for (dp = cp; *dp++;) - continue; - n = ((size_t)(dp - cp) << 2) + 1; /* 4 times + NULL */ - if (dstsize < n) { - sdst = (dstsize ? - xrealloc(sdst, (size_t)n * sizeof(*sdst)) : - xmalloc((size_t)n * sizeof(*sdst))); - dstsize = n; - } - /* - * XXX: When we are in AsciiOnly we want all characters >= 0200 to - * be encoded, but currently there is no way in vis to do that. - */ - (void)strvis(sdst, short2str(cp), VIS_NOSLASH); - return (sdst); -} diff --git a/bin/csh/time.c b/bin/csh/time.c deleted file mode 100644 index bd8c9ad3c..000000000 --- a/bin/csh/time.c +++ /dev/null @@ -1,285 +0,0 @@ -/* $NetBSD: time.c,v 1.20 2013/07/16 17:47:43 christos Exp $ */ - -/*- - * Copyright (c) 1980, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)time.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: time.c,v 1.20 2013/07/16 17:47:43 christos Exp $"); -#endif -#endif /* not lint */ - -#ifndef NOT_CSH -#include -#include -#include "csh.h" -#include "extern.h" -#endif -#include - -/* - * C Shell - routines handling process timing and niceing - */ -static void pdeltat(FILE *, struct timeval *, struct timeval *); -static void pcsecs(FILE *, long); - -#ifndef NOT_CSH -void -settimes(void) -{ - struct rusage ruch; - - (void)clock_gettime(CLOCK_MONOTONIC, &time0); - (void)getrusage(RUSAGE_SELF, &ru0); - (void)getrusage(RUSAGE_CHILDREN, &ruch); - ruadd(&ru0, &ruch); -} - -/* - * dotime is only called if it is truly a builtin function and not a - * prefix to another command - */ -void -/*ARGSUSED*/ -dotime(Char **v, struct command *t) -{ - struct rusage ru1, ruch; - struct timespec timedol; - - (void)getrusage(RUSAGE_SELF, &ru1); - (void)getrusage(RUSAGE_CHILDREN, &ruch); - ruadd(&ru1, &ruch); - (void)clock_gettime(CLOCK_MONOTONIC, &timedol); - prusage(cshout, &ru0, &ru1, &timedol, &time0); -} - -/* - * donice is only called when it on the line by itself or with a +- value - */ -void -/*ARGSUSED*/ -donice(Char **v, struct command *t) -{ - Char *cp; - int nval; - - nval = 0; - v++; - cp = *v++; - if (cp == 0) - nval = 4; - else if (*v == 0 && any("+-", cp[0])) - nval = getn(cp); - (void)setpriority(PRIO_PROCESS, 0, nval); -} - -void -ruadd(struct rusage *ru, struct rusage *ru2) -{ - timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime); - timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime); - if (ru2->ru_maxrss > ru->ru_maxrss) - ru->ru_maxrss = ru2->ru_maxrss; - - ru->ru_ixrss += ru2->ru_ixrss; - ru->ru_idrss += ru2->ru_idrss; - ru->ru_isrss += ru2->ru_isrss; - ru->ru_minflt += ru2->ru_minflt; - ru->ru_majflt += ru2->ru_majflt; - ru->ru_nswap += ru2->ru_nswap; - ru->ru_inblock += ru2->ru_inblock; - ru->ru_oublock += ru2->ru_oublock; - ru->ru_msgsnd += ru2->ru_msgsnd; - ru->ru_msgrcv += ru2->ru_msgrcv; - ru->ru_nsignals += ru2->ru_nsignals; - ru->ru_nvcsw += ru2->ru_nvcsw; - ru->ru_nivcsw += ru2->ru_nivcsw; -} -#endif /* NOT_CSH */ - -void -prusage(FILE *fp, struct rusage *r0, struct rusage *r1, struct timespec *e, - struct timespec *b) -{ -#ifndef NOT_CSH - struct varent *vp; -#endif - const char *cp; - long i; - time_t t; - time_t ms; - - cp = "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww"; - ms = (e->tv_sec - b->tv_sec) * 100 + (e->tv_nsec - b->tv_nsec) / 10000000; - t = (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec) * 100 + - (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 + - (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec) * 100 + - (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000; -#ifndef NOT_CSH - vp = adrof(STRtime); - - if (vp && vp->vec[0] && vp->vec[1]) - cp = short2str(vp->vec[1]); -#endif - - for (; *cp; cp++) - if (*cp != '%') - (void) fputc(*cp, fp); - else if (cp[1]) - switch (*++cp) { - case 'D': /* (average) unshared data size */ - (void)fprintf(fp, "%ld", t == 0 ? 0L : - (long)((r1->ru_idrss + r1->ru_isrss - - (r0->ru_idrss + r0->ru_isrss)) / t)); - break; - case 'E': /* elapsed (wall-clock) time */ - pcsecs(fp, (long) ms); - break; - case 'F': /* page faults */ - (void)fprintf(fp, "%ld", r1->ru_majflt - r0->ru_majflt); - break; - case 'I': /* FS blocks in */ - (void)fprintf(fp, "%ld", r1->ru_inblock - r0->ru_inblock); - break; - case 'K': /* (average) total data memory used */ - (void)fprintf(fp, "%ld", t == 0 ? 0L : - (long)(((r1->ru_ixrss + r1->ru_isrss + r1->ru_idrss) - - (r0->ru_ixrss + r0->ru_idrss + r0->ru_isrss)) / t)); - break; - case 'M': /* max. Resident Set Size */ - (void)fprintf(fp, "%ld", r1->ru_maxrss / 2L); - break; - case 'O': /* FS blocks out */ - (void)fprintf(fp, "%ld", r1->ru_oublock - r0->ru_oublock); - break; - case 'P': /* percent time spent running */ - /* check if it did not run at all */ - if (ms == 0) { - (void)fputs("0.0%", fp); - } else { - char pb[32]; - (void)fputs(strpct(pb, sizeof(pb), - (uintmax_t)t, (uintmax_t)ms, 1), fp); - (void)fputc('%', fp); - } - break; - case 'R': /* page reclaims */ - (void)fprintf(fp, "%ld", r1->ru_minflt - r0->ru_minflt); - break; - case 'S': /* system CPU time used */ - pdeltat(fp, &r1->ru_stime, &r0->ru_stime); - break; - case 'U': /* user CPU time used */ - pdeltat(fp, &r1->ru_utime, &r0->ru_utime); - break; - case 'W': /* number of swaps */ - i = r1->ru_nswap - r0->ru_nswap; - (void)fprintf(fp, "%ld", i); - break; - case 'X': /* (average) shared text size */ - (void)fprintf(fp, "%ld", t == 0 ? 0L : - (long)((r1->ru_ixrss - r0->ru_ixrss) / t)); - break; - case 'c': /* num. involuntary context switches */ - (void)fprintf(fp, "%ld", r1->ru_nivcsw - r0->ru_nivcsw); - break; - case 'k': /* number of signals received */ - (void)fprintf(fp, "%ld", r1->ru_nsignals-r0->ru_nsignals); - break; - case 'r': /* socket messages received */ - (void)fprintf(fp, "%ld", r1->ru_msgrcv - r0->ru_msgrcv); - break; - case 's': /* socket messages sent */ - (void)fprintf(fp, "%ld", r1->ru_msgsnd - r0->ru_msgsnd); - break; - case 'w': /* num. voluntary context switches (waits) */ - (void)fprintf(fp, "%ld", r1->ru_nvcsw - r0->ru_nvcsw); - break; - } - (void)fputc('\n', fp); -} - -static void -pdeltat(FILE *fp, struct timeval *t1, struct timeval *t0) -{ - struct timeval td; - - timersub(t1, t0, &td); - (void)fprintf(fp, "%ld.%01ld", (long)td.tv_sec, - (long)(td.tv_usec / 100000)); -} - -#define P2DIG(fp, i) (void)fprintf(fp, "%ld%ld", (i) / 10, (i) % 10) - -#ifndef NOT_CSH -void -psecs(long l) -{ - long i; - - i = l / 3600; - if (i) { - (void)fprintf(cshout, "%ld:", i); - i = l % 3600; - P2DIG(cshout, i / 60); - goto minsec; - } - i = l; - (void)fprintf(cshout, "%ld", i / 60); -minsec: - i %= 60; - (void)fputc(':', cshout); - P2DIG(cshout, i); -} -#endif - -static void -pcsecs(FILE *fp, long l) /* PWP: print mm:ss.dd, l is in sec*100 */ -{ - long i; - - i = l / 360000; - if (i) { - (void)fprintf(fp, "%ld:", i); - i = (l % 360000) / 100; - P2DIG(fp, i / 60); - goto minsec; - } - i = l / 100; - (void)fprintf(fp, "%ld", i / 60); -minsec: - i %= 60; - (void)fputc(':', fp); - P2DIG(fp, i); - (void)fputc('.', fp); - P2DIG(fp, (l % 100)); -} diff --git a/bin/dd/Makefile b/bin/dd/Makefile deleted file mode 100644 index 989867500..000000000 --- a/bin/dd/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# $NetBSD: Makefile,v 1.18 2015/03/18 13:23:49 manu Exp $ -# @(#)Makefile 8.1 (Berkeley) 5/31/93 - -.include - -RUMPPRG=dd -SRCS= args.c conv.c dd.c misc.c position.c - -DPADD+= ${LIBUTIL} -LDADD+= -lutil - -.ifdef SMALLPROG -CPPFLAGS+= -DNO_CONV -DNO_MSGFMT -DNO_IOFLAG -DSMALL -.else -CPPFLAGS+= -D_NETBSD_SOURCE -D_INCOMPLETE_XOPEN_C063 -SRCS+= conv_tab.c -.ifdef CRUNCHEDPROG -CPPFLAGS+= -DSMALL -.endif -.endif - -.include diff --git a/bin/dd/conv.c b/bin/dd/conv.c deleted file mode 100644 index d4a8a0952..000000000 --- a/bin/dd/conv.c +++ /dev/null @@ -1,283 +0,0 @@ -/* $NetBSD: conv.c,v 1.17 2003/08/07 09:05:10 agc Exp $ */ - -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Keith Muller of the University of California, San Diego and Lance - * Visser of Convex Computer Corporation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)conv.c 8.3 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: conv.c,v 1.17 2003/08/07 09:05:10 agc Exp $"); -#endif -#endif /* not lint */ - -#include -#include - -#include -#include -#include - -#include "dd.h" -#include "extern.h" - -/* - * def -- - * Copy input to output. Input is buffered until reaches obs, and then - * output until less than obs remains. Only a single buffer is used. - * Worst case buffer calculation is (ibs + obs - 1). - */ -void -def(void) -{ - uint64_t cnt; - u_char *inp; - const u_char *t; - - if ((t = ctab) != NULL) - for (inp = in.dbp - (cnt = in.dbrcnt); cnt--; ++inp) - *inp = t[*inp]; - - /* Make the output buffer look right. */ - out.dbp = in.dbp; - out.dbcnt = in.dbcnt; - - if (in.dbcnt >= out.dbsz) { - /* If the output buffer is full, write it. */ - dd_out(0); - - /* - * Ddout copies the leftover output to the beginning of - * the buffer and resets the output buffer. Reset the - * input buffer to match it. - */ - in.dbp = out.dbp; - in.dbcnt = out.dbcnt; - } -} - -void -def_close(void) -{ - - /* Just update the count, everything is already in the buffer. */ - if (in.dbcnt) - out.dbcnt = in.dbcnt; -} - -#ifdef NO_CONV -/* Build a smaller version (i.e. for a miniroot) */ -/* These can not be called, but just in case... */ -static const char no_block[] = "unblock and -DNO_CONV?"; -void block(void) { errx(EXIT_FAILURE, "%s", no_block + 2); } -void block_close(void) { errx(EXIT_FAILURE, "%s", no_block + 2); } -void unblock(void) { errx(EXIT_FAILURE, "%s", no_block); } -void unblock_close(void) { errx(EXIT_FAILURE, "%s", no_block); } -#else /* NO_CONV */ - -/* - * Copy variable length newline terminated records with a max size cbsz - * bytes to output. Records less than cbs are padded with spaces. - * - * max in buffer: MAX(ibs, cbsz) - * max out buffer: obs + cbsz - */ -void -block(void) -{ - static int intrunc; - int ch = 0; /* pacify gcc */ - uint64_t cnt, maxlen; - u_char *inp, *outp; - const u_char *t; - - /* - * Record truncation can cross block boundaries. If currently in a - * truncation state, keep tossing characters until reach a newline. - * Start at the beginning of the buffer, as the input buffer is always - * left empty. - */ - if (intrunc) { - for (inp = in.db, cnt = in.dbrcnt; - cnt && *inp++ != '\n'; --cnt); - if (!cnt) { - in.dbcnt = 0; - in.dbp = in.db; - return; - } - intrunc = 0; - /* Adjust the input buffer numbers. */ - in.dbcnt = cnt - 1; - in.dbp = inp + cnt - 1; - } - - /* - * Copy records (max cbsz size chunks) into the output buffer. The - * translation is done as we copy into the output buffer. - */ - for (inp = in.dbp - in.dbcnt, outp = out.dbp; in.dbcnt;) { - maxlen = MIN(cbsz, in.dbcnt); - if ((t = ctab) != NULL) - for (cnt = 0; - cnt < maxlen && (ch = *inp++) != '\n'; ++cnt) - *outp++ = t[ch]; - else - for (cnt = 0; - cnt < maxlen && (ch = *inp++) != '\n'; ++cnt) - *outp++ = ch; - /* - * Check for short record without a newline. Reassemble the - * input block. - */ - if (ch != '\n' && in.dbcnt < cbsz) { - (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt); - break; - } - - /* Adjust the input buffer numbers. */ - in.dbcnt -= cnt; - if (ch == '\n') - --in.dbcnt; - - /* Pad short records with spaces. */ - if (cnt < cbsz) - (void)memset(outp, ctab ? ctab[' '] : ' ', cbsz - cnt); - else { - /* - * If the next character wouldn't have ended the - * block, it's a truncation. - */ - if (!in.dbcnt || *inp != '\n') - ++st.trunc; - - /* Toss characters to a newline. */ - for (; in.dbcnt && *inp++ != '\n'; --in.dbcnt); - if (!in.dbcnt) - intrunc = 1; - else - --in.dbcnt; - } - - /* Adjust output buffer numbers. */ - out.dbp += cbsz; - if ((out.dbcnt += cbsz) >= out.dbsz) - dd_out(0); - outp = out.dbp; - } - in.dbp = in.db + in.dbcnt; -} - -void -block_close(void) -{ - - /* - * Copy any remaining data into the output buffer and pad to a record. - * Don't worry about truncation or translation, the input buffer is - * always empty when truncating, and no characters have been added for - * translation. The bottom line is that anything left in the input - * buffer is a truncated record. Anything left in the output buffer - * just wasn't big enough. - */ - if (in.dbcnt) { - ++st.trunc; - (void)memmove(out.dbp, in.dbp - in.dbcnt, in.dbcnt); - (void)memset(out.dbp + in.dbcnt, - ctab ? ctab[' '] : ' ', cbsz - in.dbcnt); - out.dbcnt += cbsz; - } -} - -/* - * Convert fixed length (cbsz) records to variable length. Deletes any - * trailing blanks and appends a newline. - * - * max in buffer: MAX(ibs, cbsz) + cbsz - * max out buffer: obs + cbsz - */ -void -unblock(void) -{ - uint64_t cnt; - u_char *inp; - const u_char *t; - - /* Translation and case conversion. */ - if ((t = ctab) != NULL) - for (cnt = in.dbrcnt, inp = in.dbp - 1; cnt--; inp--) - *inp = t[*inp]; - /* - * Copy records (max cbsz size chunks) into the output buffer. The - * translation has to already be done or we might not recognize the - * spaces. - */ - for (inp = in.db; in.dbcnt >= cbsz; inp += cbsz, in.dbcnt -= cbsz) { - for (t = inp + cbsz - 1; t >= inp && *t == ' '; --t); - if (t >= inp) { - cnt = t - inp + 1; - (void)memmove(out.dbp, inp, cnt); - out.dbp += cnt; - out.dbcnt += cnt; - } - ++out.dbcnt; - *out.dbp++ = '\n'; - if (out.dbcnt >= out.dbsz) - dd_out(0); - } - if (in.dbcnt) - (void)memmove(in.db, in.dbp - in.dbcnt, in.dbcnt); - in.dbp = in.db + in.dbcnt; -} - -void -unblock_close(void) -{ - uint64_t cnt; - u_char *t; - - if (in.dbcnt) { - warnx("%s: short input record", in.name); - for (t = in.db + in.dbcnt - 1; t >= in.db && *t == ' '; --t); - if (t >= in.db) { - cnt = t - in.db + 1; - (void)memmove(out.dbp, in.db, cnt); - out.dbp += cnt; - out.dbcnt += cnt; - } - ++out.dbcnt; - *out.dbp++ = '\n'; - } -} - -#endif /* NO_CONV */ diff --git a/bin/dd/conv_tab.c b/bin/dd/conv_tab.c deleted file mode 100644 index 89d32da58..000000000 --- a/bin/dd/conv_tab.c +++ /dev/null @@ -1,287 +0,0 @@ -/* $NetBSD: conv_tab.c,v 1.9 2003/08/07 09:05:10 agc Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Keith Muller of the University of California, San Diego and Lance - * Visser of Convex Computer Corporation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)conv_tab.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: conv_tab.c,v 1.9 2003/08/07 09:05:10 agc Exp $"); -#endif -#endif /* not lint */ - -#include - -/* - * There are currently six tables: - * - * ebcdic -> ascii 32V conv=oldascii - * ascii -> ebcdic 32V conv=oldebcdic - * ascii -> ibm ebcdic 32V conv=oldibm - * - * ebcdic -> ascii POSIX/S5 conv=ascii - * ascii -> ebcdic POSIX/S5 conv=ebcdic - * ascii -> ibm ebcdic POSIX/S5 conv=ibm - * - * Other tables are built from these if multiple conversions are being - * done. - * - * Tables used for conversions to/from IBM and EBCDIC to support an extension - * to POSIX P1003.2/D11. The tables referencing POSIX contain data extracted - * from tables 4-3 and 4-4 in P1003.2/Draft 11. The historic tables were - * constructed by running against a file with all possible byte values. - * - * More information can be obtained in "Correspondences of 8-Bit and Hollerith - * Codes for Computer Environments-A USASI Tutorial", Communications of the - * ACM, Volume 11, Number 11, November 1968, pp. 783-789. - */ - -u_char casetab[256]; - -/* EBCDIC to ASCII -- 32V compatible. */ -const u_char e2a_32V[] = { - 0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177, /* 0000 */ - 0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017, /* 0010 */ - 0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207, /* 0020 */ - 0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037, /* 0030 */ - 0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033, /* 0040 */ - 0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007, /* 0050 */ - 0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004, /* 0060 */ - 0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032, /* 0070 */ - 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246, /* 0100 */ - 0247, 0250, 0133, 0056, 0074, 0050, 0053, 0041, /* 0110 */ - 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257, /* 0120 */ - 0260, 0261, 0135, 0044, 0052, 0051, 0073, 0136, /* 0130 */ - 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267, /* 0140 */ - 0270, 0271, 0174, 0054, 0045, 0137, 0076, 0077, /* 0150 */ - 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, /* 0160 */ - 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042, /* 0170 */ - 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147, /* 0200 */ - 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311, /* 0210 */ - 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160, /* 0220 */ - 0161, 0162, 0313, 0314, 0315, 0316, 0317, 0320, /* 0230 */ - 0321, 0176, 0163, 0164, 0165, 0166, 0167, 0170, /* 0240 */ - 0171, 0172, 0322, 0323, 0324, 0325, 0326, 0327, /* 0250 */ - 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, /* 0260 */ - 0340, 0341, 0342, 0343, 0344, 0345, 0346, 0347, /* 0270 */ - 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107, /* 0300 */ - 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355, /* 0310 */ - 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120, /* 0320 */ - 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363, /* 0330 */ - 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130, /* 0340 */ - 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371, /* 0350 */ - 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, /* 0360 */ - 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ -}; - -/* ASCII to EBCDIC -- 32V compatible. */ -const u_char a2e_32V[] = { - 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */ - 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */ - 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */ - 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */ - 0100, 0117, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */ - 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */ - 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */ - 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */ - 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */ - 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */ - 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */ - 0347, 0350, 0351, 0112, 0340, 0132, 0137, 0155, /* 0130 */ - 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */ - 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */ - 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */ - 0247, 0250, 0251, 0300, 0152, 0320, 0241, 0007, /* 0170 */ - 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */ - 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */ - 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */ - 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */ - 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */ - 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */ - 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */ - 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */ - 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */ - 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */ - 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */ - 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */ - 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */ - 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */ - 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */ - 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ -}; - -/* ASCII to IBM EBCDIC -- 32V compatible. */ -const u_char a2ibm_32V[] = { - 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */ - 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */ - 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */ - 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */ - 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */ - 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */ - 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */ - 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */ - 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */ - 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */ - 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */ - 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155, /* 0130 */ - 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */ - 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */ - 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */ - 0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007, /* 0170 */ - 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */ - 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */ - 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */ - 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */ - 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */ - 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */ - 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */ - 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */ - 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */ - 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */ - 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */ - 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */ - 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */ - 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */ - 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */ - 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ -}; - -/* EBCDIC to ASCII -- POSIX and System V compatible. */ -const u_char e2a_POSIX[] = { - 0000, 0001, 0002, 0003, 0234, 0011, 0206, 0177, /* 0000 */ - 0227, 0215, 0216, 0013, 0014, 0015, 0016, 0017, /* 0010 */ - 0020, 0021, 0022, 0023, 0235, 0205, 0010, 0207, /* 0020 */ - 0030, 0031, 0222, 0217, 0034, 0035, 0036, 0037, /* 0030 */ - 0200, 0201, 0202, 0203, 0204, 0012, 0027, 0033, /* 0040 */ - 0210, 0211, 0212, 0213, 0214, 0005, 0006, 0007, /* 0050 */ - 0220, 0221, 0026, 0223, 0224, 0225, 0226, 0004, /* 0060 */ - 0230, 0231, 0232, 0233, 0024, 0025, 0236, 0032, /* 0070 */ - 0040, 0240, 0241, 0242, 0243, 0244, 0245, 0246, /* 0100 */ - 0247, 0250, 0325, 0056, 0074, 0050, 0053, 0174, /* 0110 */ - 0046, 0251, 0252, 0253, 0254, 0255, 0256, 0257, /* 0120 */ - 0260, 0261, 0041, 0044, 0052, 0051, 0073, 0176, /* 0130 */ - 0055, 0057, 0262, 0263, 0264, 0265, 0266, 0267, /* 0140 */ - 0270, 0271, 0313, 0054, 0045, 0137, 0076, 0077, /* 0150 */ - 0272, 0273, 0274, 0275, 0276, 0277, 0300, 0301, /* 0160 */ - 0302, 0140, 0072, 0043, 0100, 0047, 0075, 0042, /* 0170 */ - 0303, 0141, 0142, 0143, 0144, 0145, 0146, 0147, /* 0200 */ - 0150, 0151, 0304, 0305, 0306, 0307, 0310, 0311, /* 0210 */ - 0312, 0152, 0153, 0154, 0155, 0156, 0157, 0160, /* 0220 */ - 0161, 0162, 0136, 0314, 0315, 0316, 0317, 0320, /* 0230 */ - 0321, 0345, 0163, 0164, 0165, 0166, 0167, 0170, /* 0240 */ - 0171, 0172, 0322, 0323, 0324, 0133, 0326, 0327, /* 0250 */ - 0330, 0331, 0332, 0333, 0334, 0335, 0336, 0337, /* 0260 */ - 0340, 0341, 0342, 0343, 0344, 0135, 0346, 0347, /* 0270 */ - 0173, 0101, 0102, 0103, 0104, 0105, 0106, 0107, /* 0300 */ - 0110, 0111, 0350, 0351, 0352, 0353, 0354, 0355, /* 0310 */ - 0175, 0112, 0113, 0114, 0115, 0116, 0117, 0120, /* 0320 */ - 0121, 0122, 0356, 0357, 0360, 0361, 0362, 0363, /* 0330 */ - 0134, 0237, 0123, 0124, 0125, 0126, 0127, 0130, /* 0340 */ - 0131, 0132, 0364, 0365, 0366, 0367, 0370, 0371, /* 0350 */ - 0060, 0061, 0062, 0063, 0064, 0065, 0066, 0067, /* 0360 */ - 0070, 0071, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ -}; - -/* ASCII to EBCDIC -- POSIX and System V compatible. */ -const u_char a2e_POSIX[] = { - 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */ - 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */ - 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */ - 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */ - 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */ - 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */ - 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */ - 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */ - 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */ - 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */ - 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */ - 0347, 0350, 0351, 0255, 0340, 0275, 0232, 0155, /* 0130 */ - 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */ - 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */ - 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */ - 0247, 0250, 0251, 0300, 0117, 0320, 0137, 0007, /* 0170 */ - 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */ - 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */ - 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */ - 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */ - 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */ - 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */ - 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */ - 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */ - 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */ - 0216, 0217, 0220, 0152, 0233, 0234, 0235, 0236, /* 0310 */ - 0237, 0240, 0252, 0253, 0254, 0112, 0256, 0257, /* 0320 */ - 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */ - 0270, 0271, 0272, 0273, 0274, 0241, 0276, 0277, /* 0340 */ - 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */ - 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */ - 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ -}; - -/* ASCII to IBM EBCDIC -- POSIX and System V compatible. */ -const u_char a2ibm_POSIX[] = { - 0000, 0001, 0002, 0003, 0067, 0055, 0056, 0057, /* 0000 */ - 0026, 0005, 0045, 0013, 0014, 0015, 0016, 0017, /* 0010 */ - 0020, 0021, 0022, 0023, 0074, 0075, 0062, 0046, /* 0020 */ - 0030, 0031, 0077, 0047, 0034, 0035, 0036, 0037, /* 0030 */ - 0100, 0132, 0177, 0173, 0133, 0154, 0120, 0175, /* 0040 */ - 0115, 0135, 0134, 0116, 0153, 0140, 0113, 0141, /* 0050 */ - 0360, 0361, 0362, 0363, 0364, 0365, 0366, 0367, /* 0060 */ - 0370, 0371, 0172, 0136, 0114, 0176, 0156, 0157, /* 0070 */ - 0174, 0301, 0302, 0303, 0304, 0305, 0306, 0307, /* 0100 */ - 0310, 0311, 0321, 0322, 0323, 0324, 0325, 0326, /* 0110 */ - 0327, 0330, 0331, 0342, 0343, 0344, 0345, 0346, /* 0120 */ - 0347, 0350, 0351, 0255, 0340, 0275, 0137, 0155, /* 0130 */ - 0171, 0201, 0202, 0203, 0204, 0205, 0206, 0207, /* 0140 */ - 0210, 0211, 0221, 0222, 0223, 0224, 0225, 0226, /* 0150 */ - 0227, 0230, 0231, 0242, 0243, 0244, 0245, 0246, /* 0160 */ - 0247, 0250, 0251, 0300, 0117, 0320, 0241, 0007, /* 0170 */ - 0040, 0041, 0042, 0043, 0044, 0025, 0006, 0027, /* 0200 */ - 0050, 0051, 0052, 0053, 0054, 0011, 0012, 0033, /* 0210 */ - 0060, 0061, 0032, 0063, 0064, 0065, 0066, 0010, /* 0220 */ - 0070, 0071, 0072, 0073, 0004, 0024, 0076, 0341, /* 0230 */ - 0101, 0102, 0103, 0104, 0105, 0106, 0107, 0110, /* 0240 */ - 0111, 0121, 0122, 0123, 0124, 0125, 0126, 0127, /* 0250 */ - 0130, 0131, 0142, 0143, 0144, 0145, 0146, 0147, /* 0260 */ - 0150, 0151, 0160, 0161, 0162, 0163, 0164, 0165, /* 0270 */ - 0166, 0167, 0170, 0200, 0212, 0213, 0214, 0215, /* 0300 */ - 0216, 0217, 0220, 0232, 0233, 0234, 0235, 0236, /* 0310 */ - 0237, 0240, 0252, 0253, 0254, 0255, 0256, 0257, /* 0320 */ - 0260, 0261, 0262, 0263, 0264, 0265, 0266, 0267, /* 0330 */ - 0270, 0271, 0272, 0273, 0274, 0275, 0276, 0277, /* 0340 */ - 0312, 0313, 0314, 0315, 0316, 0317, 0332, 0333, /* 0350 */ - 0334, 0335, 0336, 0337, 0352, 0353, 0354, 0355, /* 0360 */ - 0356, 0357, 0372, 0373, 0374, 0375, 0376, 0377, /* 0370 */ -}; diff --git a/bin/dd/dd.1 b/bin/dd/dd.1 deleted file mode 100644 index 0cb69a8cb..000000000 --- a/bin/dd/dd.1 +++ /dev/null @@ -1,522 +0,0 @@ -.\" $NetBSD: dd.1,v 1.32 2016/08/18 22:43:49 sevan Exp $ -.\" -.\" Copyright (c) 1990, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" Keith Muller of the University of California, San Diego. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)dd.1 8.2 (Berkeley) 1/13/94 -.\" -.Dd August 18, 2016 -.Dt DD 1 -.Os -.Sh NAME -.Nm dd -.Nd convert and copy a file -.Sh SYNOPSIS -.Nm -.Op operand ... -.Sh DESCRIPTION -The -.Nm -utility copies the standard input to the standard output. -Input data is read and written in 512-byte blocks. -If input reads are short, input from multiple reads are aggregated -to form the output block. -When finished, -.Nm -displays the number of complete and partial input and output blocks -and truncated input records to the standard error output. -.Pp -The following operands are available: -.Bl -tag -width of=file -.It Cm bs= Ns Ar n -Set both input and output block size, superseding the -.Cm ibs -and -.Cm obs -operands. -If no conversion values other than -.Cm noerror , -.Cm notrunc -or -.Cm sync -are specified, then each input block is copied to the output as a -single block without any aggregation of short blocks. -.It Cm cbs= Ns Ar n -Set the conversion record size to -.Va n -bytes. -The conversion record size is required by the record oriented conversion -values. -.It Cm count= Ns Ar n -Copy only -.Va n -input blocks. -.It Cm files= Ns Ar n -Copy -.Va n -input files before terminating. -This operand is only applicable when the input device is a tape. -.It Cm ibs= Ns Ar n -Set the input block size to -.Va n -bytes instead of the default 512. -.It Cm if= Ns Ar file -Read input from -.Ar file -instead of the standard input. -.It Cm iflag= Ns Ar flags -Use comma-separated -.Ar flags -when calling -.Xr open 2 -for the input file. -The possible values are -.Va O_ -flags documented in -.Xr open 2 , -specified as lowercase and with the leading -.Va O_ -removed. -Default value is -.Va rdonly . -.It Cm iseek= Ns Ar n -Seek on the input file -.Ar n -blocks. -This is synonymous with -.Cm skip= Ns Ar n . -.It Cm msgfmt= Ns Ar fmt -Specify the message format -.Ar fmt -to be used when writing information to standard output. -Possible values are: -.Bl -tag -width xxxxx -offset indent -compact -.It quiet -turns off information summary report except for errors and -.Cm progress . -.It posix -default information summary report as specified by POSIX. -.It human -default information summary report extended with human-readable -values. -.El -.Pp -When -.Ar fmt -does not correspond to any value given above, -it contains a string that will be used as format specifier -for the information summary output. -Each conversion specification is introduced by the character -.Cm % . -The following ones are available: -.Bl -tag -width xx -offset indent -compact -.It b -total number of bytes transferred -.It B -total number of bytes transferred in -.Xr humanize_number 3 -format -.It e -speed transfer -.It E -speed transfer in -.Xr humanize_number 3 -format -.It i -number of partial input block(s) -.It I -number of full input block(s) -.It o -number of partial output block(s) -.It O -number of full output block(s) -.It s -time elapsed since the beginning in -.Do seconds.ms Dc -format -.It p -number of sparse output blocks -.It t -number of truncated blocks -.It w -number of odd-length swab blocks -.It P -singular/plural of -.Do block Dc -depending on number of sparse blocks -.It T -singular/plural of -.Do block Dc -depending on number of truncated blocks -.It W -singular/plural of -.Do block Dc -depending on number of swab blocks -.El -.It Cm obs= Ns Ar n -Set the output block size to -.Va n -bytes instead of the default 512. -.It Cm of= Ns Ar file -Write output to -.Ar file -instead of the standard output. -Any regular output file is truncated unless the -.Cm notrunc -conversion value is specified. -If an initial portion of the output file is skipped (see the -.Cm seek -operand) -the output file is truncated at that point. -.It Cm oflag= Ns Ar flags -Same as -.Cm iflag -but for the call to -.Xr open 2 -on the output file. -The default value is -.Va creat , -which should be explicitly added in -.Cm oflag -in order to output to a nonexistent file. -The default or specified value is or'ed with -.Va rdwr -for a first -.Xr open 2 -attempt, then on failure with -.Va wronly -on a second attempt. -In both cases, -.Va trunc -is automatically added if none of -.Cm oseek , -.Cm seek , -or -.Cm conv=notrunc -operands are used, -.It Cm oseek= Ns Ar n -Seek on the output file -.Ar n -blocks. -This is synonymous with -.Cm seek= Ns Ar n . -.It Cm seek= Ns Ar n -Seek -.Va n -blocks from the beginning of the output before copying. -On non-tape devices, an -.Xr lseek 2 -operation is used. -Otherwise, existing blocks are read and the data discarded. -If the user does not have read permission for the tape, it is positioned -using the tape -.Xr ioctl 2 -function calls. -If the seek operation is past the end of file, space from the current -end of file to the specified offset is filled with blocks of -.Tn NUL -bytes. -.It Cm skip= Ns Ar n -Skip -.Va n -blocks from the beginning of the input before copying. -On input which supports seeks, an -.Xr lseek 2 -operation is used. -Otherwise, input data is read and discarded. -For pipes, the correct number of bytes is read. -For all other devices, the correct number of blocks is read without -distinguishing between a partial or complete block being read. -.It Cm progress= Ns Ar n -Switch on display of progress if -.Va n -is set to any non-zero value. -This will cause a -.Dq \&. -to be printed (to the standard error output) for every -.Va n -full or partial blocks written to the output file. -.Sm off -.It Cm conv= Cm value Op \&, Cm value \&... -.Sm on -Where -.Cm value -is one of the symbols from the following list. -.Bl -tag -width unblock -.It Cm ascii , oldascii -The same as the -.Cm unblock -value except that characters are translated from -.Tn EBCDIC -to -.Tn ASCII -before the -records are converted. -(These values imply -.Cm unblock -if the operand -.Cm cbs -is also specified.) -There are two conversion maps for -.Tn ASCII . -The value -.Cm ascii -specifies the recommended one which is compatible with -.At V . -The value -.Cm oldascii -specifies the one used in historic -.Tn AT\*[Am]T -and pre- -.Bx 4.3 Reno -systems. -.It Cm block -Treats the input as a sequence of newline or end-of-file terminated variable -length records independent of input and output block boundaries. -Any trailing newline character is discarded. -Each input record is converted to a fixed length output record where the -length is specified by the -.Cm cbs -operand. -Input records shorter than the conversion record size are padded with spaces. -Input records longer than the conversion record size are truncated. -The number of truncated input records, if any, are reported to the standard -error output at the completion of the copy. -.It Cm ebcdic , ibm , oldebcdic , oldibm -The same as the -.Cm block -value except that characters are translated from -.Tn ASCII -to -.Tn EBCDIC -after the -records are converted. -(These values imply -.Cm block -if the operand -.Cm cbs -is also specified.) -There are four conversion maps for -.Tn EBCDIC . -The value -.Cm ebcdic -specifies the recommended one which is compatible with -.At V . -The value -.Cm ibm -is a slightly different mapping, which is compatible with the -.At V -.Cm ibm -value. -The values -.Cm oldebcdic -and -.Cm oldibm -are maps used in historic -.Tn AT\*[Am]T -and pre -.Bx 4.3 Reno -systems. -.It Cm lcase -Transform uppercase characters into lowercase characters. -.It Cm noerror -Do not stop processing on an input error. -When an input error occurs, a diagnostic message followed by the current -input and output block counts will be written to the standard error output -in the same format as the standard completion message. -If the -.Cm sync -conversion is also specified, any missing input data will be replaced -with -.Tn NUL -bytes (or with spaces if a block oriented conversion value was -specified) and processed as a normal input buffer. -If the -.Cm sync -conversion is not specified, the input block is omitted from the output. -On input files which are not tapes or pipes, the file offset -will be positioned past the block in which the error occurred using -.Xr lseek 2 . -.It Cm notrunc -Do not truncate the output file. -This will preserve any blocks in the output file not explicitly written -by -.Nm . -The -.Cm notrunc -value is not supported for tapes. -.It Cm osync -Pad the final output block to the full output block size. -If the input file is not a multiple of the output block size -after conversion, this conversion forces the final output block -to be the same size as preceding blocks for use on devices that require -regularly sized blocks to be written. -This option is incompatible with use of the -.Cm bs= Ns Ar n -block size specification. -.It Cm sparse -If one or more non-final output blocks would consist solely of -.Dv NUL -bytes, try to seek the output file by the required space instead of -filling them with -.Dv NUL Ns s . -This results in a sparse file on some file systems. -.It Cm swab -Swap every pair of input bytes. -If an input buffer has an odd number of bytes, the last byte will be -ignored during swapping. -.It Cm sync -Pad every input block to the input buffer size. -Spaces are used for pad bytes if a block oriented conversion value is -specified, otherwise -.Tn NUL -bytes are used. -.It Cm ucase -Transform lowercase characters into uppercase characters. -.It Cm unblock -Treats the input as a sequence of fixed length records independent of input -and output block boundaries. -The length of the input records is specified by the -.Cm cbs -operand. -Any trailing space characters are discarded and a newline character is -appended. -.El -.El -.Pp -Where sizes are specified, a decimal number of bytes is expected. -Two or more numbers may be separated by an -.Dq x -to indicate a product. -Each number may have one of the following optional suffixes: -.Bl -tag -width 3n -offset indent -compact -.It b -Block; multiply by 512 -.It k -Kibi; multiply by 1024 (1 KiB) -.It m -Mebi; multiply by 1048576 (1 MiB) -.It g -Gibi; multiply by 1073741824 (1 GiB) -.It t -Tebi; multiply by 1099511627776 (1 TiB) -.It w -Word; multiply by the number of bytes in an integer -.El -.Pp -When finished, -.Nm -displays the number of complete and partial input and output blocks, -truncated input records and odd-length byte-swapping blocks to the -standard error output. -A partial input block is one where less than the input block size -was read. -A partial output block is one where less than the output block size -was written. -Partial output blocks to tape devices are considered fatal errors. -Otherwise, the rest of the block will be written. -Partial output blocks to character devices will produce a warning message. -A truncated input block is one where a variable length record oriented -conversion value was specified and the input line was too long to -fit in the conversion record or was not newline terminated. -.Pp -Normally, data resulting from input or conversion or both are aggregated -into output blocks of the specified size. -After the end of input is reached, any remaining output is written as -a block. -This means that the final output block may be shorter than the output -block size. -.Pp -If -.Nm -receives a -.Dv SIGINFO -signal -(see the -.Ic status -argument for -.Xr stty 1 ) , -the current input and output block counts will -be written to the standard error output -in the same format as the standard completion message. -If -.Nm -receives a -.Dv SIGINT -signal, the current input and output block counts will -be written to the standard error output -in the same format as the standard completion message and -.Nm -will exit. -.Sh EXIT STATUS -The -.Nm -utility exits 0 on success and \*[Gt]0 if an error occurred. -.Sh EXAMPLES -To print summary information in human-readable form: -.Pp -.Dl dd if=/dev/zero of=/dev/null count=1 msgfmt=human -.Pp -To customize the information summary output and print it through -.Xr unvis 3 : -.Bd -literal -offset indent -dd if=/dev/zero of=/dev/null count=1 \e - msgfmt='speed:%E, in %s seconds\en' 2\*[Gt]\*[Am]1 | unvis -.Ed -.Sh SEE ALSO -.Xr cp 1 , -.Xr mt 1 , -.Xr tr 1 -.Sh STANDARDS -The -.Nm -utility is expected to be a superset of the -.St -p1003.2 -standard. -The -.Cm files -and -.Cm msgfmt -operands and the -.Cm ascii , -.Cm ebcdic , -.Cm ibm , -.Cm oldascii , -.Cm oldebcdic -and -.Cm oldibm -values are extensions to the -.Tn POSIX -standard. -.Sh HISTORY -A -.Nm -utility appeared in -.At v5 . diff --git a/bin/dd/dd.c b/bin/dd/dd.c deleted file mode 100644 index c4fb1e87b..000000000 --- a/bin/dd/dd.c +++ /dev/null @@ -1,616 +0,0 @@ -/* $NetBSD: dd.c,v 1.51 2016/09/05 01:00:07 sevan Exp $ */ - -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Keith Muller of the University of California, San Diego and Lance - * Visser of Convex Computer Corporation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1991, 1993, 1994\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)dd.c 8.5 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: dd.c,v 1.51 2016/09/05 01:00:07 sevan Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dd.h" -#include "extern.h" - -static void dd_close(void); -static void dd_in(void); -static void getfdtype(IO *); -static void redup_clean_fd(IO *); -static void setup(void); - -IO in, out; /* input/output state */ -STAT st; /* statistics */ -void (*cfunc)(void); /* conversion function */ -uint64_t cpy_cnt; /* # of blocks to copy */ -static off_t pending = 0; /* pending seek if sparse */ -u_int ddflags; /* conversion options */ -#ifdef NO_IOFLAG -#define iflag O_RDONLY -#define oflag O_CREAT -#else -u_int iflag = O_RDONLY; /* open(2) flags for input file */ -u_int oflag = O_CREAT; /* open(2) flags for output file */ -#endif /* NO_IOFLAG */ -uint64_t cbsz; /* conversion block size */ -u_int files_cnt = 1; /* # of files to copy */ -uint64_t progress = 0; /* display sign of life */ -const u_char *ctab; /* conversion table */ -sigset_t infoset; /* a set blocking SIGINFO */ -const char *msgfmt = "posix"; /* default summary() message format */ - -/* - * Ops for stdin/stdout and crunch'd dd. These are always host ops. - */ -static const struct ddfops ddfops_stdfd = { - .op_open = open, - .op_close = close, - .op_fcntl = fcntl, - .op_ioctl = ioctl, - .op_fstat = fstat, - .op_fsync = fsync, - .op_ftruncate = ftruncate, - .op_lseek = lseek, - .op_read = read, - .op_write = write, -}; -extern const struct ddfops ddfops_prog; - -int -main(int argc, char *argv[]) -{ - int ch; - - setprogname(argv[0]); - (void)setlocale(LC_ALL, ""); - - while ((ch = getopt(argc, argv, "")) != -1) { - switch (ch) { - default: - errx(EXIT_FAILURE, "usage: dd [operand ...]"); - /* NOTREACHED */ - } - } - argc -= (optind - 1); - argv += (optind - 1); - - jcl(argv); -#ifndef CRUNCHOPS - if (ddfops_prog.op_init && ddfops_prog.op_init() == -1) - err(1, "prog init"); -#endif - setup(); - - (void)signal(SIGINFO, summaryx); - (void)signal(SIGINT, terminate); - (void)sigemptyset(&infoset); - (void)sigaddset(&infoset, SIGINFO); - - (void)atexit(summary); - - while (files_cnt--) - dd_in(); - - dd_close(); - exit(0); - /* NOTREACHED */ -} - -static void -setup(void) -{ -#ifdef CRUNCHOPS - const struct ddfops *prog_ops = &ddfops_stdfd; -#else - const struct ddfops *prog_ops = &ddfops_prog; -#endif - - if (in.name == NULL) { - in.name = "stdin"; - in.fd = STDIN_FILENO; - in.ops = &ddfops_stdfd; - } else { - in.ops = prog_ops; - in.fd = ddop_open(in, in.name, iflag, 0); - if (in.fd < 0) - err(EXIT_FAILURE, "%s", in.name); - /* NOTREACHED */ - - /* Ensure in.fd is outside the stdio descriptor range */ - redup_clean_fd(&in); - } - - getfdtype(&in); - - if (files_cnt > 1 && !(in.flags & ISTAPE)) { - errx(EXIT_FAILURE, "files is not supported for non-tape devices"); - /* NOTREACHED */ - } - - if (out.name == NULL) { - /* No way to check for read access here. */ - out.fd = STDOUT_FILENO; - out.name = "stdout"; - out.ops = &ddfops_stdfd; - } else { - out.ops = prog_ops; - -#ifndef NO_IOFLAG - if ((oflag & O_TRUNC) && (ddflags & C_SEEK)) { - errx(EXIT_FAILURE, "oflag=trunc is incompatible " - "with seek or oseek operands, giving up."); - /* NOTREACHED */ - } - if ((oflag & O_TRUNC) && (ddflags & C_NOTRUNC)) { - errx(EXIT_FAILURE, "oflag=trunc is incompatible " - "with conv=notrunc operand, giving up."); - /* NOTREACHED */ - } -#endif /* NO_IOFLAG */ -#define OFLAGS \ - (oflag | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC)) - out.fd = ddop_open(out, out.name, O_RDWR | OFLAGS, DEFFILEMODE); - /* - * May not have read access, so try again with write only. - * Without read we may have a problem if output also does - * not support seeks. - */ - if (out.fd < 0) { - out.fd = ddop_open(out, out.name, O_WRONLY | OFLAGS, - DEFFILEMODE); - out.flags |= NOREAD; - } - if (out.fd < 0) { - err(EXIT_FAILURE, "%s", out.name); - /* NOTREACHED */ - } - - /* Ensure out.fd is outside the stdio descriptor range */ - redup_clean_fd(&out); - } - - getfdtype(&out); - - /* - * Allocate space for the input and output buffers. If not doing - * record oriented I/O, only need a single buffer. - */ - if (!(ddflags & (C_BLOCK|C_UNBLOCK))) { - size_t dbsz = out.dbsz; - if (!(ddflags & C_BS)) - dbsz += in.dbsz - 1; - if ((in.db = malloc(dbsz)) == NULL) { - err(EXIT_FAILURE, NULL); - /* NOTREACHED */ - } - out.db = in.db; - } else if ((in.db = - malloc((u_int)(MAX(in.dbsz, cbsz) + cbsz))) == NULL || - (out.db = malloc((u_int)(out.dbsz + cbsz))) == NULL) { - err(EXIT_FAILURE, NULL); - /* NOTREACHED */ - } - in.dbp = in.db; - out.dbp = out.db; - - /* Position the input/output streams. */ - if (in.offset) - pos_in(); - if (out.offset) - pos_out(); - - /* - * Truncate the output file; ignore errors because it fails on some - * kinds of output files, tapes, for example. - */ - if ((ddflags & (C_OF | C_SEEK | C_NOTRUNC)) == (C_OF | C_SEEK)) - (void)ddop_ftruncate(out, out.fd, (off_t)out.offset * out.dbsz); - - /* - * If converting case at the same time as another conversion, build a - * table that does both at once. If just converting case, use the - * built-in tables. - */ - if (ddflags & (C_LCASE|C_UCASE)) { -#ifdef NO_CONV - /* Should not get here, but just in case... */ - errx(EXIT_FAILURE, "case conv and -DNO_CONV"); - /* NOTREACHED */ -#else /* NO_CONV */ - u_int cnt; - - if (ddflags & C_ASCII || ddflags & C_EBCDIC) { - if (ddflags & C_LCASE) { - for (cnt = 0; cnt < 256; ++cnt) - casetab[cnt] = tolower(ctab[cnt]); - } else { - for (cnt = 0; cnt < 256; ++cnt) - casetab[cnt] = toupper(ctab[cnt]); - } - } else { - if (ddflags & C_LCASE) { - for (cnt = 0; cnt < 256; ++cnt) - casetab[cnt] = tolower(cnt); - } else { - for (cnt = 0; cnt < 256; ++cnt) - casetab[cnt] = toupper(cnt); - } - } - - ctab = casetab; -#endif /* NO_CONV */ - } - - (void)gettimeofday(&st.start, NULL); /* Statistics timestamp. */ -} - -static void -getfdtype(IO *io) -{ - struct mtget mt; - struct stat sb; - - if (io->ops->op_fstat(io->fd, &sb)) { - err(EXIT_FAILURE, "%s", io->name); - /* NOTREACHED */ - } - if (S_ISCHR(sb.st_mode)) - io->flags |= io->ops->op_ioctl(io->fd, MTIOCGET, &mt) - ? ISCHR : ISTAPE; - else if (io->ops->op_lseek(io->fd, (off_t)0, SEEK_CUR) == -1 - && errno == ESPIPE) - io->flags |= ISPIPE; /* XXX fixed in 4.4BSD */ -} - -/* - * Move the parameter file descriptor to a descriptor that is outside the - * stdio descriptor range, if necessary. This is required to avoid - * accidentally outputting completion or error messages into the - * output file that were intended for the tty. - */ -static void -redup_clean_fd(IO *io) -{ - int fd = io->fd; - int newfd; - - if (fd != STDIN_FILENO && fd != STDOUT_FILENO && - fd != STDERR_FILENO) - /* File descriptor is ok, return immediately. */ - return; - - /* - * 3 is the first descriptor greater than STD*_FILENO. Any - * free descriptor valued 3 or above is acceptable... - */ - newfd = io->ops->op_fcntl(fd, F_DUPFD, 3); - if (newfd < 0) { - err(EXIT_FAILURE, "dupfd IO"); - /* NOTREACHED */ - } - - io->ops->op_close(fd); - io->fd = newfd; -} - -static void -dd_in(void) -{ - int flags; - int64_t n; - - for (flags = ddflags;;) { - if (cpy_cnt && (st.in_full + st.in_part) >= cpy_cnt) - return; - - /* - * Clear the buffer first if doing "sync" on input. - * If doing block operations use spaces. This will - * affect not only the C_NOERROR case, but also the - * last partial input block which should be padded - * with zero and not garbage. - */ - if (flags & C_SYNC) { - if (flags & (C_BLOCK|C_UNBLOCK)) - (void)memset(in.dbp, ' ', in.dbsz); - else - (void)memset(in.dbp, 0, in.dbsz); - } - - n = ddop_read(in, in.fd, in.dbp, in.dbsz); - if (n == 0) { - in.dbrcnt = 0; - return; - } - - /* Read error. */ - if (n < 0) { - - /* - * If noerror not specified, die. POSIX requires that - * the warning message be followed by an I/O display. - */ - if (!(flags & C_NOERROR)) { - err(EXIT_FAILURE, "%s", in.name); - /* NOTREACHED */ - } - warn("%s", in.name); - summary(); - - /* - * If it's not a tape drive or a pipe, seek past the - * error. If your OS doesn't do the right thing for - * raw disks this section should be modified to re-read - * in sector size chunks. - */ - if (!(in.flags & (ISPIPE|ISTAPE)) && - ddop_lseek(in, in.fd, (off_t)in.dbsz, SEEK_CUR)) - warn("%s", in.name); - - /* If sync not specified, omit block and continue. */ - if (!(ddflags & C_SYNC)) - continue; - - /* Read errors count as full blocks. */ - in.dbcnt += in.dbrcnt = in.dbsz; - ++st.in_full; - - /* Handle full input blocks. */ - } else if ((uint64_t)n == in.dbsz) { - in.dbcnt += in.dbrcnt = n; - ++st.in_full; - - /* Handle partial input blocks. */ - } else { - /* If sync, use the entire block. */ - if (ddflags & C_SYNC) - in.dbcnt += in.dbrcnt = in.dbsz; - else - in.dbcnt += in.dbrcnt = n; - ++st.in_part; - } - - /* - * POSIX states that if bs is set and no other conversions - * than noerror, notrunc or sync are specified, the block - * is output without buffering as it is read. - */ - if (ddflags & C_BS) { - out.dbcnt = in.dbcnt; - dd_out(1); - in.dbcnt = 0; - continue; - } - - if (ddflags & C_SWAB) { - if ((n = in.dbrcnt) & 1) { - ++st.swab; - --n; - } - swab(in.dbp, in.dbp, n); - } - - in.dbp += in.dbrcnt; - (*cfunc)(); - } -} - -/* - * Cleanup any remaining I/O and flush output. If necessary, output file - * is truncated. - */ -static void -dd_close(void) -{ - - if (cfunc == def) - def_close(); - else if (cfunc == block) - block_close(); - else if (cfunc == unblock) - unblock_close(); - if (ddflags & C_OSYNC && out.dbcnt < out.dbsz) { - (void)memset(out.dbp, 0, out.dbsz - out.dbcnt); - out.dbcnt = out.dbsz; - } - /* If there are pending sparse blocks, make sure - * to write out the final block un-sparse - */ - if ((out.dbcnt == 0) && pending) { - memset(out.db, 0, out.dbsz); - out.dbcnt = out.dbsz; - out.dbp = out.db + out.dbcnt; - pending -= out.dbsz; - } - if (out.dbcnt) - dd_out(1); - - /* - * Reporting nfs write error may be deferred until next - * write(2) or close(2) system call. So, we need to do an - * extra check. If an output is stdout, the file structure - * may be shared with other processes and close(2) just - * decreases the reference count. - */ - if (out.fd == STDOUT_FILENO && ddop_fsync(out, out.fd) == -1 - && errno != EINVAL) { - err(EXIT_FAILURE, "fsync stdout"); - /* NOTREACHED */ - } - if (ddop_close(out, out.fd) == -1) { - err(EXIT_FAILURE, "close"); - /* NOTREACHED */ - } -} - -void -dd_out(int force) -{ - static int warned; - int64_t cnt, n, nw; - u_char *outp; - - /* - * Write one or more blocks out. The common case is writing a full - * output block in a single write; increment the full block stats. - * Otherwise, we're into partial block writes. If a partial write, - * and it's a character device, just warn. If a tape device, quit. - * - * The partial writes represent two cases. 1: Where the input block - * was less than expected so the output block was less than expected. - * 2: Where the input block was the right size but we were forced to - * write the block in multiple chunks. The original versions of dd(1) - * never wrote a block in more than a single write, so the latter case - * never happened. - * - * One special case is if we're forced to do the write -- in that case - * we play games with the buffer size, and it's usually a partial write. - */ - outp = out.db; - for (n = force ? out.dbcnt : out.dbsz;; n = out.dbsz) { - for (cnt = n;; cnt -= nw) { - - if (!force && ddflags & C_SPARSE) { - int sparse, i; - sparse = 1; /* Is buffer sparse? */ - for (i = 0; i < cnt; i++) - if (outp[i] != 0) { - sparse = 0; - break; - } - if (sparse) { - pending += cnt; - outp += cnt; - nw = 0; - break; - } - } - if (pending != 0) { - if (ddop_lseek(out, - out.fd, pending, SEEK_CUR) == -1) - err(EXIT_FAILURE, "%s: seek error creating sparse file", - out.name); - } - nw = bwrite(&out, outp, cnt); - if (nw <= 0) { - if (nw == 0) - errx(EXIT_FAILURE, - "%s: end of device", out.name); - /* NOTREACHED */ - if (errno != EINTR) - err(EXIT_FAILURE, "%s", out.name); - /* NOTREACHED */ - nw = 0; - } - if (pending) { - st.bytes += pending; - st.sparse += pending/out.dbsz; - st.out_full += pending/out.dbsz; - pending = 0; - } - outp += nw; - st.bytes += nw; - if (nw == n) { - if ((uint64_t)n != out.dbsz) - ++st.out_part; - else - ++st.out_full; - break; - } - ++st.out_part; - if (nw == cnt) - break; - if (out.flags & ISCHR && !warned) { - warned = 1; - warnx("%s: short write on character device", out.name); - } - if (out.flags & ISTAPE) - errx(EXIT_FAILURE, - "%s: short write on tape device", out.name); - /* NOTREACHED */ - - } - if ((out.dbcnt -= n) < out.dbsz) - break; - } - - /* Reassemble the output block. */ - if (out.dbcnt) - (void)memmove(out.db, out.dbp - out.dbcnt, out.dbcnt); - out.dbp = out.db + out.dbcnt; - - if (progress && (st.out_full + st.out_part) % progress == 0) - (void)write(STDERR_FILENO, ".", 1); -} - -/* - * A protected against SIGINFO write - */ -ssize_t -bwrite(IO *io, const void *buf, size_t len) -{ - sigset_t oset; - ssize_t rv; - int oerrno; - - (void)sigprocmask(SIG_BLOCK, &infoset, &oset); - rv = io->ops->op_write(io->fd, buf, len); - oerrno = errno; - (void)sigprocmask(SIG_SETMASK, &oset, NULL); - errno = oerrno; - return (rv); -} diff --git a/bin/dd/dd.h b/bin/dd/dd.h deleted file mode 100644 index 2b2712d82..000000000 --- a/bin/dd/dd.h +++ /dev/null @@ -1,126 +0,0 @@ -/* $NetBSD: dd.h,v 1.16 2015/03/18 13:23:49 manu Exp $ */ - -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Keith Muller of the University of California, San Diego and Lance - * Visser of Convex Computer Corporation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)dd.h 8.3 (Berkeley) 4/2/94 - */ - -#include - -struct ddfops { - int (*op_init)(void); - - int (*op_open)(const char *, int, ...); - int (*op_close)(int); - - int (*op_fcntl)(int, int, ...); - int (*op_ioctl)(int, unsigned long, ...); - - int (*op_fstat)(int, struct stat *); - int (*op_fsync)(int); - int (*op_ftruncate)(int, off_t); - - off_t (*op_lseek)(int, off_t, int); - - ssize_t (*op_read)(int, void *, size_t); - ssize_t (*op_write)(int, const void *, size_t); -}; - -#define ddop_open(dir, a1, a2, ...) dir.ops->op_open(a1, a2, __VA_ARGS__) -#define ddop_close(dir, a1) dir.ops->op_close(a1) -#define ddop_fcntl(dir, a1, a2, ...) dir.ops->op_fcntl(a1, a2, __VA_ARGS__) -#define ddop_ioctl(dir, a1, a2, ...) dir.ops->op_ioctl(a1, a2, __VA_ARGS__) -#define ddop_fsync(dir, a1) dir.ops->op_fsync(a1) -#define ddop_ftruncate(dir, a1, a2) dir.ops->op_ftruncate(a1, a2) -#define ddop_lseek(dir, a1, a2, a3) dir.ops->op_lseek(a1, a2, a3) -#define ddop_read(dir, a1, a2, a3) dir.ops->op_read(a1, a2, a3) -#define ddop_write(dir, a1, a2, a3) dir.ops->op_write(a1, a2, a3) - -/* Input/output stream state. */ -typedef struct { - u_char *db; /* buffer address */ - u_char *dbp; /* current buffer I/O address */ - uint64_t dbcnt; /* current buffer byte count */ - int64_t dbrcnt; /* last read byte count */ - uint64_t dbsz; /* buffer size */ - -#define ISCHR 0x01 /* character device (warn on short) */ -#define ISPIPE 0x02 /* pipe (not truncatable) */ -#define ISTAPE 0x04 /* tape (not seekable) */ -#define NOREAD 0x08 /* not readable */ - u_int flags; - - const char *name; /* name */ - int fd; /* file descriptor */ - uint64_t offset; /* # of blocks to skip */ - struct ddfops const *ops; /* ops to use with fd */ -} IO; - -typedef struct { - uint64_t in_full; /* # of full input blocks */ - uint64_t in_part; /* # of partial input blocks */ - uint64_t out_full; /* # of full output blocks */ - uint64_t out_part; /* # of partial output blocks */ - uint64_t trunc; /* # of truncated records */ - uint64_t swab; /* # of odd-length swab blocks */ - uint64_t sparse; /* # of sparse output blocks */ - uint64_t bytes; /* # of bytes written */ - struct timeval start; /* start time of dd */ -} STAT; - -/* Flags (in ddflags, iflag and oflag). */ -#define C_NONE 0x00000 -#define C_ASCII 0x00001 -#define C_BLOCK 0x00002 -#define C_BS 0x00004 -#define C_CBS 0x00008 -#define C_COUNT 0x00010 -#define C_EBCDIC 0x00020 -#define C_FILES 0x00040 -#define C_IBS 0x00080 -#define C_IF 0x00100 -#define C_LCASE 0x00200 -#define C_NOERROR 0x00400 -#define C_NOTRUNC 0x00800 -#define C_OBS 0x01000 -#define C_OF 0x02000 -#define C_SEEK 0x04000 -#define C_SKIP 0x08000 -#define C_SWAB 0x10000 -#define C_SYNC 0x20000 -#define C_UCASE 0x40000 -#define C_UNBLOCK 0x80000 -#define C_OSYNC 0x100000 -#define C_SPARSE 0x200000 -#define C_IFLAG 0x400000 -#define C_OFLAG 0x800000 diff --git a/bin/dd/dd_hostops.c b/bin/dd/dd_hostops.c deleted file mode 100644 index d6e7a89e7..000000000 --- a/bin/dd/dd_hostops.c +++ /dev/null @@ -1,53 +0,0 @@ -/* $NetBSD: dd_hostops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $ */ - -/*- - * Copyright (c) 2010 The NetBSD Foundation, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#ifndef lint -__RCSID("$NetBSD: dd_hostops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $"); -#endif /* !lint */ - -#include -#include - -#include -#include - -#include "dd.h" - -const struct ddfops ddfops_prog = { - .op_open = open, - .op_close = close, - .op_fcntl = fcntl, - .op_ioctl = ioctl, - .op_fstat = fstat, - .op_fsync = fsync, - .op_ftruncate = ftruncate, - .op_lseek = lseek, - .op_read = read, - .op_write = write, -}; diff --git a/bin/dd/dd_rumpops.c b/bin/dd/dd_rumpops.c deleted file mode 100644 index 71f7db470..000000000 --- a/bin/dd/dd_rumpops.c +++ /dev/null @@ -1,52 +0,0 @@ -/* $NetBSD: dd_rumpops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $ */ - -/*- - * Copyright (c) 2010 The NetBSD Foundation, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#ifndef lint -__RCSID("$NetBSD: dd_rumpops.c,v 1.1 2011/02/04 19:42:12 pooka Exp $"); -#endif /* !lint */ - -#include -#include - -#include "dd.h" - -const struct ddfops ddfops_prog = { - .op_init = rumpclient_init, - - .op_open = rump_sys_open, - .op_close = rump_sys_close, - .op_fcntl = rump_sys_fcntl, - .op_ioctl = rump_sys_ioctl, - .op_fstat = rump_sys_fstat, - .op_fsync = rump_sys_fsync, - .op_ftruncate = rump_sys_ftruncate, - .op_lseek = rump_sys_lseek, - .op_read = rump_sys_read, - .op_write = rump_sys_write, -}; diff --git a/bin/dd/extern.h b/bin/dd/extern.h deleted file mode 100644 index 27b51a072..000000000 --- a/bin/dd/extern.h +++ /dev/null @@ -1,86 +0,0 @@ -/* $NetBSD: extern.h,v 1.23 2015/03/18 13:23:49 manu Exp $ */ - -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Keith Muller of the University of California, San Diego and Lance - * Visser of Convex Computer Corporation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)extern.h 8.3 (Berkeley) 4/2/94 - */ - -#include - -#ifdef NO_CONV -__dead void block(void); -__dead void block_close(void); -__dead void unblock(void); -__dead void unblock_close(void); -#else -void block(void); -void block_close(void); -void unblock(void); -void unblock_close(void); -#endif - -#ifndef NO_MSGFMT -int dd_write_msg(const char *, int); -#endif - -void dd_out(int); -void def(void); -void def_close(void); -void jcl(char **); -void pos_in(void); -void pos_out(void); -void summary(void); -void summaryx(int); -__dead void terminate(int); -void unblock(void); -void unblock_close(void); -ssize_t bwrite(IO *, const void *, size_t); - -extern IO in, out; -extern STAT st; -extern void (*cfunc)(void); -extern uint64_t cpy_cnt; -extern uint64_t cbsz; -extern u_int ddflags; -#ifndef NO_IOFLAG -extern u_int iflag; -extern u_int oflag; -#endif /* NO_IOFLAG */ -extern u_int files_cnt; -extern uint64_t progress; -extern const u_char *ctab; -extern const u_char a2e_32V[], a2e_POSIX[]; -extern const u_char e2a_32V[], e2a_POSIX[]; -extern const u_char a2ibm_32V[], a2ibm_POSIX[]; -extern u_char casetab[]; -extern const char *msgfmt; diff --git a/bin/dd/misc.c b/bin/dd/misc.c deleted file mode 100644 index 0fac98bed..000000000 --- a/bin/dd/misc.c +++ /dev/null @@ -1,342 +0,0 @@ -/* $NetBSD: misc.c,v 1.23 2011/11/07 22:24:23 jym Exp $ */ - -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Keith Muller of the University of California, San Diego and Lance - * Visser of Convex Computer Corporation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)misc.c 8.3 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: misc.c,v 1.23 2011/11/07 22:24:23 jym Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "dd.h" -#include "extern.h" - -#define tv2mS(tv) ((tv).tv_sec * 1000LL + ((tv).tv_usec + 500) / 1000) - -static void posix_summary(void); -#ifndef NO_MSGFMT -static void custom_summary(void); -static void human_summary(void); -static void quiet_summary(void); - -static void buffer_write(const char *, size_t, int); -#endif /* NO_MSGFMT */ - -void -summary(void) -{ - - if (progress) - (void)write(STDERR_FILENO, "\n", 1); - -#ifdef NO_MSGFMT - return posix_summary(); -#else /* NO_MSGFMT */ - if (strncmp(msgfmt, "human", sizeof("human")) == 0) - return human_summary(); - - if (strncmp(msgfmt, "posix", sizeof("posix")) == 0) - return posix_summary(); - - if (strncmp(msgfmt, "quiet", sizeof("quiet")) == 0) - return quiet_summary(); - - return custom_summary(); -#endif /* NO_MSGFMT */ -} - -static void -posix_summary(void) -{ - char buf[100]; - int64_t mS; - struct timeval tv; - - if (progress) - (void)write(STDERR_FILENO, "\n", 1); - - (void)gettimeofday(&tv, NULL); - mS = tv2mS(tv) - tv2mS(st.start); - if (mS == 0) - mS = 1; - - /* Use snprintf(3) so that we don't reenter stdio(3). */ - (void)snprintf(buf, sizeof(buf), - "%llu+%llu records in\n%llu+%llu records out\n", - (unsigned long long)st.in_full, (unsigned long long)st.in_part, - (unsigned long long)st.out_full, (unsigned long long)st.out_part); - (void)write(STDERR_FILENO, buf, strlen(buf)); - if (st.swab) { - (void)snprintf(buf, sizeof(buf), "%llu odd length swab %s\n", - (unsigned long long)st.swab, - (st.swab == 1) ? "block" : "blocks"); - (void)write(STDERR_FILENO, buf, strlen(buf)); - } - if (st.trunc) { - (void)snprintf(buf, sizeof(buf), "%llu truncated %s\n", - (unsigned long long)st.trunc, - (st.trunc == 1) ? "block" : "blocks"); - (void)write(STDERR_FILENO, buf, strlen(buf)); - } - if (st.sparse) { - (void)snprintf(buf, sizeof(buf), "%llu sparse output %s\n", - (unsigned long long)st.sparse, - (st.sparse == 1) ? "block" : "blocks"); - (void)write(STDERR_FILENO, buf, strlen(buf)); - } - (void)snprintf(buf, sizeof(buf), - "%llu bytes transferred in %lu.%03d secs (%llu bytes/sec)\n", - (unsigned long long) st.bytes, - (long) (mS / 1000), - (int) (mS % 1000), - (unsigned long long) (st.bytes * 1000LL / mS)); - (void)write(STDERR_FILENO, buf, strlen(buf)); -} - -/* ARGSUSED */ -void -summaryx(int notused) -{ - - summary(); -} - -/* ARGSUSED */ -void -terminate(int signo) -{ - - summary(); - (void)raise_default_signal(signo); - _exit(127); -} - -#ifndef NO_MSGFMT -/* - * Buffer write(2) calls - */ -static void -buffer_write(const char *str, size_t size, int flush) -{ - static char wbuf[128]; - static size_t cnt = 0; /* Internal counter to allow wbuf to wrap */ - - unsigned int i; - - for (i = 0; i < size; i++) { - if (str != NULL) { - wbuf[cnt++] = str[i]; - } - if (cnt >= sizeof(wbuf)) { - (void)write(STDERR_FILENO, wbuf, cnt); - cnt = 0; - } - } - - if (flush != 0) { - (void)write(STDERR_FILENO, wbuf, cnt); - cnt = 0; - } -} - -/* - * Write summary to stderr according to format 'fmt'. If 'enable' is 0, it - * will not attempt to write anything. Can be used to validate the - * correctness of the 'fmt' string. - */ -int -dd_write_msg(const char *fmt, int enable) -{ - char hbuf[7], nbuf[32]; - const char *ptr; - int64_t mS; - struct timeval tv; - - (void)gettimeofday(&tv, NULL); - mS = tv2mS(tv) - tv2mS(st.start); - if (mS == 0) - mS = 1; - -#define ADDC(c) do { if (enable != 0) buffer_write(&c, 1, 0); } \ - while (/*CONSTCOND*/0) -#define ADDS(p) do { if (enable != 0) buffer_write(p, strlen(p), 0); } \ - while (/*CONSTCOND*/0) - - for (ptr = fmt; *ptr; ptr++) { - if (*ptr != '%') { - ADDC(*ptr); - continue; - } - - switch (*++ptr) { - case 'b': - (void)snprintf(nbuf, sizeof(nbuf), "%llu", - (unsigned long long)st.bytes); - ADDS(nbuf); - break; - case 'B': - if (humanize_number(hbuf, sizeof(hbuf), - st.bytes, "B", - HN_AUTOSCALE, HN_DECIMAL) == -1) - warnx("humanize_number (bytes transferred)"); - ADDS(hbuf); - break; - case 'e': - (void)snprintf(nbuf, sizeof(nbuf), "%llu", - (unsigned long long) (st.bytes * 1000LL / mS)); - ADDS(nbuf); - break; - case 'E': - if (humanize_number(hbuf, sizeof(hbuf), - st.bytes * 1000LL / mS, "B", - HN_AUTOSCALE, HN_DECIMAL) == -1) - warnx("humanize_number (bytes per second)"); - ADDS(hbuf); ADDS("/sec"); - break; - case 'i': - (void)snprintf(nbuf, sizeof(nbuf), "%llu", - (unsigned long long)st.in_part); - ADDS(nbuf); - break; - case 'I': - (void)snprintf(nbuf, sizeof(nbuf), "%llu", - (unsigned long long)st.in_full); - ADDS(nbuf); - break; - case 'o': - (void)snprintf(nbuf, sizeof(nbuf), "%llu", - (unsigned long long)st.out_part); - ADDS(nbuf); - break; - case 'O': - (void)snprintf(nbuf, sizeof(nbuf), "%llu", - (unsigned long long)st.out_full); - ADDS(nbuf); - break; - case 's': - (void)snprintf(nbuf, sizeof(nbuf), "%li.%03d", - (long) (mS / 1000), (int) (mS % 1000)); - ADDS(nbuf); - break; - case 'p': - (void)snprintf(nbuf, sizeof(nbuf), "%llu", - (unsigned long long)st.sparse); - ADDS(nbuf); - break; - case 't': - (void)snprintf(nbuf, sizeof(nbuf), "%llu", - (unsigned long long)st.trunc); - ADDS(nbuf); - break; - case 'w': - (void)snprintf(nbuf, sizeof(nbuf), "%llu", - (unsigned long long)st.swab); - ADDS(nbuf); - break; - case 'P': - ADDS("block"); - if (st.sparse != 1) ADDS("s"); - break; - case 'T': - ADDS("block"); - if (st.trunc != 1) ADDS("s"); - break; - case 'W': - ADDS("block"); - if (st.swab != 1) ADDS("s"); - break; - case '%': - ADDC(*ptr); - break; - default: - if (*ptr == '\0') - goto done; - errx(EXIT_FAILURE, "unknown specifier '%c' in " - "msgfmt string", *ptr); - /* NOTREACHED */ - } - } - -done: - /* flush buffer */ - buffer_write(NULL, 0, 1); - return 0; -} - -static void -custom_summary(void) -{ - - dd_write_msg(msgfmt, 1); -} - -static void -human_summary(void) -{ - (void)dd_write_msg("%I+%i records in\n%O+%o records out\n", 1); - if (st.swab) { - (void)dd_write_msg("%w odd length swab %W\n", 1); - } - if (st.trunc) { - (void)dd_write_msg("%t truncated %T\n", 1); - } - if (st.sparse) { - (void)dd_write_msg("%p sparse output %P\n", 1); - } - (void)dd_write_msg("%b bytes (%B) transferred in %s secs " - "(%e bytes/sec - %E)\n", 1); -} - -static void -quiet_summary(void) -{ - - /* stay quiet */ -} -#endif /* NO_MSGFMT */ diff --git a/bin/dd/position.c b/bin/dd/position.c deleted file mode 100644 index 36dd580a3..000000000 --- a/bin/dd/position.c +++ /dev/null @@ -1,185 +0,0 @@ -/* $NetBSD: position.c,v 1.18 2010/11/22 21:04:28 pooka Exp $ */ - -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Keith Muller of the University of California, San Diego and Lance - * Visser of Convex Computer Corporation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)position.c 8.3 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: position.c,v 1.18 2010/11/22 21:04:28 pooka Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "dd.h" -#include "extern.h" - -/* - * Position input/output data streams before starting the copy. Device type - * dependent. Seekable devices use lseek, and the rest position by reading. - * Seeking past the end of file can cause null blocks to be written to the - * output. - */ -void -pos_in(void) -{ - int bcnt, cnt, nr, warned; - - /* If not a pipe or tape device, try to seek on it. */ - if (!(in.flags & (ISPIPE|ISTAPE))) { - if (ddop_lseek(in, in.fd, - (off_t)in.offset * (off_t)in.dbsz, SEEK_CUR) == -1) { - err(EXIT_FAILURE, "%s", in.name); - /* NOTREACHED */ - } - return; - /* NOTREACHED */ - } - - /* - * Read the data. If a pipe, read until satisfy the number of bytes - * being skipped. No differentiation for reading complete and partial - * blocks for other devices. - */ - for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) { - if ((nr = ddop_read(in, in.fd, in.db, bcnt)) > 0) { - if (in.flags & ISPIPE) { - if (!(bcnt -= nr)) { - bcnt = in.dbsz; - --cnt; - } - } else - --cnt; - continue; - } - - if (nr == 0) { - if (files_cnt > 1) { - --files_cnt; - continue; - } - errx(EXIT_FAILURE, "skip reached end of input"); - /* NOTREACHED */ - } - - /* - * Input error -- either EOF with no more files, or I/O error. - * If noerror not set die. POSIX requires that the warning - * message be followed by an I/O display. - */ - if (ddflags & C_NOERROR) { - if (!warned) { - - warn("%s", in.name); - warned = 1; - summary(); - } - continue; - } - err(EXIT_FAILURE, "%s", in.name); - /* NOTREACHED */ - } -} - -void -pos_out(void) -{ - struct mtop t_op; - int n; - uint64_t cnt; - - /* - * If not a tape, try seeking on the file. Seeking on a pipe is - * going to fail, but don't protect the user -- they shouldn't - * have specified the seek operand. - */ - if (!(out.flags & ISTAPE)) { - if (ddop_lseek(out, out.fd, - (off_t)out.offset * (off_t)out.dbsz, SEEK_SET) == -1) - err(EXIT_FAILURE, "%s", out.name); - /* NOTREACHED */ - return; - } - - /* If no read access, try using mtio. */ - if (out.flags & NOREAD) { - t_op.mt_op = MTFSR; - t_op.mt_count = out.offset; - - if (ddop_ioctl(out, out.fd, MTIOCTOP, &t_op) < 0) - err(EXIT_FAILURE, "%s", out.name); - /* NOTREACHED */ - return; - } - - /* Read it. */ - for (cnt = 0; cnt < out.offset; ++cnt) { - if ((n = ddop_read(out, out.fd, out.db, out.dbsz)) > 0) - continue; - - if (n < 0) - err(EXIT_FAILURE, "%s", out.name); - /* NOTREACHED */ - - /* - * If reach EOF, fill with NUL characters; first, back up over - * the EOF mark. Note, cnt has not yet been incremented, so - * the EOF read does not count as a seek'd block. - */ - t_op.mt_op = MTBSR; - t_op.mt_count = 1; - if (ddop_ioctl(out, out.fd, MTIOCTOP, &t_op) == -1) - err(EXIT_FAILURE, "%s", out.name); - /* NOTREACHED */ - - while (cnt++ < out.offset) - if ((uint64_t)(n = bwrite(&out, - out.db, out.dbsz)) != out.dbsz) - err(EXIT_FAILURE, "%s", out.name); - /* NOTREACHED */ - break; - } -} diff --git a/bin/df/Makefile b/bin/df/Makefile deleted file mode 100644 index e3c5edb60..000000000 --- a/bin/df/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# $NetBSD: Makefile,v 1.19 2011/08/28 08:20:58 christos Exp $ -# @(#)Makefile 8.3 (Berkeley) 5/8/95 - -.include - -PROG= df - -LDADD+=-lutil -DPADD+=${LIBUTIL} - -.include diff --git a/bin/df/df.1 b/bin/df/df.1 deleted file mode 100644 index 63f7d4e23..000000000 --- a/bin/df/df.1 +++ /dev/null @@ -1,206 +0,0 @@ -.\" $NetBSD: df.1,v 1.46.6.1 2018/08/28 13:21:42 martin Exp $ -.\" -.\" Copyright (c) 1989, 1990, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)df.1 8.2 (Berkeley) 1/13/92 -.\" -.Dd August 27, 2018 -.Dt DF 1 -.Os -.Sh NAME -.Nm df -.Nd display free disk space -.Sh SYNOPSIS -.Nm -.Op Fl agln -.Op Fl Ghkm | Fl ihkm | Fl Pk -.Op Fl t Ar type -.Op Ar file | Ar file_system ... -.Sh DESCRIPTION -.Nm -displays statistics about the amount of free disk space on the specified -.Ar file_system -or on the file system of which -.Ar file -is a part. -By default, all sizes are reported in 512-byte block counts. -If neither a file or a -.Ar file_system -operand is specified, -statistics for all mounted file systems are displayed -(subject to the -.Fl l -and -.Fl t -options below). -.Pp -Note that the printed count of available blocks takes -.Va minfree -into account, and thus will be negative when the number of free blocks -on the filesystem is less than -.Va minfree . -.Pp -The following options are available: -.Bl -tag -width Ds -.It Fl a -Show all mount points, -including those that were mounted with the -.Dv MNT_IGNORE -flag. -.It Fl G -Display all the fields of the structure(s) returned by -.Xr statvfs 2 . -This option cannot be used with the -.Fl i -or -.Fl P -options, and it is modelled after the Solaris -.Fl g -option. -This option will override the -.Fl g , -.Fl h , -.Fl k , -and -.Fl m -options, as well as any setting of -.Ev BLOCKSIZE . -.It Fl g -The -.Fl g -option causes the numbers to be reported in gigabytes (1024*1024*1024 -bytes). -.It Fl h -"Human-readable" output. -Use unit suffixes: Byte, Kilobyte, Megabyte, -Gigabyte, Terabyte, Petabyte, Exabyte in order to reduce the number of -digits to four or less. -.It Fl i -Include statistics on the number of free inodes. -.It Fl k -By default, all sizes are reported in 512-byte block counts. -The -.Fl k -option causes the numbers to be reported in kilobytes (1024 bytes). -.It Fl l -Display statistics only about mounted file systems with the -.Dv MNT_LOCAL -flag set. -If a non-local file system is given as an argument, a -warning is issued and no information is given on that file system. -.It Fl m -The -.Fl m -option causes the numbers to be reported in megabytes (1024*1024 bytes). -.It Fl n -Print out the previously obtained statistics from the file systems. -This option should be used if it is possible that one or more -file systems are in a state such that they will not be able to provide -statistics without a long delay. -When this option is specified, -.Nm -will not request new statistics from the file systems, but will respond -with the possibly stale statistics that were previously obtained. -.It Fl P -Produce output in the following portable format: -.Pp -If both the -.Fl P -and -.Fl k -option are specified, the output will be preceded by the following header -line, formatted to match the data following it: -.Bd -literal -"Filesystem 1024-blocks Used Available Capacity Mounted on\en" -.Ed -.Pp -If the -.Fl P -option is specified without the -.Fl k -options, the output will be preceded by the following header line, -formatted to match the data following it: -.Bd -literal -"Filesystem \*[Lt]blksize\*[Gt]-blocks Used Available Capacity Mounted on\en" -.Ed -.Pp -The header line is followed by data formatted as follows: -.Bd -literal -"%s %d %d %d %d%% %s\en", \*[Lt]file system name\*[Gt], \*[Lt]total space\*[Gt], - \*[Lt]space used\*[Gt], \*[Lt]space free\*[Gt], \*[Lt]percentage used\*[Gt], - \*[Lt]file system root\*[Gt] -.Ed -.Pp -Note that the -.Fl i -option may not be specified with -.Fl P . -.It Fl t Ar type -Is used to indicate the actions should only be taken on -filesystems of the specified type. -More than one type may be specified in a comma-separated list. -The list of filesystem types can be prefixed with -.Dq no -to specify the filesystem types for which action should -.Em not -be taken. -If a file system is given on the command line that is not of -the specified type, a warning is issued and no information is given on -that file system. -.El -.Sh ENVIRONMENT -.Bl -tag -width BLOCKSIZE -.It Ev BLOCKSIZE -If the environment variable -.Ev BLOCKSIZE -is set, and the -.Fl g , -.Fl h , -.Fl k -and -.Fl m -options are not specified, the block counts will be displayed in units of that -size block. -.El -.Sh SEE ALSO -.Xr quota 1 , -.Xr fstatvfs 2 , -.Xr getvfsstat 2 , -.Xr statvfs 2 , -.Xr getbsize 3 , -.Xr getmntinfo 3 , -.Xr fs 5 , -.Xr fstab 5 , -.Xr mount 8 , -.Xr quot 8 , -.Xr tunefs 8 -.Sh HISTORY -A -.Nm -utility appeared in -.At v1 . diff --git a/bin/df/df.c b/bin/df/df.c deleted file mode 100644 index ad7ba3687..000000000 --- a/bin/df/df.c +++ /dev/null @@ -1,520 +0,0 @@ -/* $NetBSD: df.c,v 1.92.8.1 2018/08/28 13:21:42 martin Exp $ */ - -/* - * Copyright (c) 1980, 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * (c) UNIX System Laboratories, Inc. - * All or some portions of this file are derived from material licensed - * to the University of California by American Telephone and Telegraph - * Co. or Unix System Laboratories, Inc. and are reproduced herein with - * the permission of UNIX System Laboratories, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT( -"@(#) Copyright (c) 1980, 1990, 1993, 1994\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)df.c 8.7 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: df.c,v 1.92.8.1 2018/08/28 13:21:42 martin Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static char *getmntpt(const char *); -static void prtstat(struct statvfs *, int); -static int selected(const char *, size_t); -static void maketypelist(char *); -static size_t regetmntinfo(struct statvfs **, size_t); -__dead static void usage(void); -static void prthumanval(int64_t, const char *); -static void prthuman(struct statvfs *, int64_t, int64_t); - -static int aflag, gflag, hflag, iflag, lflag, nflag, Pflag; -static long usize; -static char **typelist; - -int -main(int argc, char *argv[]) -{ - struct stat stbuf; - struct statvfs *mntbuf; - long mntsize; - int ch, i, maxwidth, width; - char *mntpt; - - setprogname(argv[0]); - (void)setlocale(LC_ALL, ""); - - while ((ch = getopt(argc, argv, "aGghiklmnPt:")) != -1) - switch (ch) { - case 'a': - aflag = 1; - break; - case 'g': - hflag = 0; - usize = 1024 * 1024 * 1024; - break; - case 'G': - gflag = 1; - break; - case 'h': - hflag = 1; - usize = 0; - break; - case 'i': - iflag = 1; - break; - case 'k': - hflag = 0; - usize = 1024; - break; - case 'l': - lflag = 1; - break; - case 'm': - hflag = 0; - usize = 1024 * 1024; - break; - case 'n': - nflag = 1; - break; - case 'P': - Pflag = 1; - break; - case 't': - if (typelist != NULL) - errx(EXIT_FAILURE, - "only one -t option may be specified."); - maketypelist(optarg); - break; - case '?': - default: - usage(); - } - - if (gflag && (Pflag || iflag)) - errx(EXIT_FAILURE, - "only one of -G and -P or -i may be specified"); - if (Pflag && iflag) - errx(EXIT_FAILURE, - "only one of -P and -i may be specified"); -#if 0 - /* - * The block size cannot be checked until after getbsize() is called. - */ - if (Pflag && (hflag || (usize != 1024 && usize != 512))) - errx(EXIT_FAILURE, - "non-standard block size incompatible with -P"); -#endif - argc -= optind; - argv += optind; - - mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); - if (mntsize == 0) - err(EXIT_FAILURE, - "retrieving information on mounted file systems"); - - if (*argv == NULL) { - mntsize = regetmntinfo(&mntbuf, mntsize); - } else { - if ((mntbuf = malloc(argc * sizeof(*mntbuf))) == NULL) - err(EXIT_FAILURE, "can't allocate statvfs array"); - mntsize = 0; - for (/*EMPTY*/; *argv != NULL; argv++) { - if (stat(*argv, &stbuf) < 0) { - if ((mntpt = getmntpt(*argv)) == 0) { - warn("%s", *argv); - continue; - } - } else if (S_ISBLK(stbuf.st_mode)) { - if ((mntpt = getmntpt(*argv)) == 0) - mntpt = *argv; - } else - mntpt = *argv; - /* - * Statfs does not take a `wait' flag, so we cannot - * implement nflag here. - */ - if (!statvfs(mntpt, &mntbuf[mntsize])) - if (lflag && - (mntbuf[mntsize].f_flag & MNT_LOCAL) == 0) - warnx("Warning: %s is not a local %s", - *argv, "file system"); - else if - (!selected(mntbuf[mntsize].f_fstypename, - sizeof(mntbuf[mntsize].f_fstypename))) - warnx("Warning: %s mounted as a %s %s", - *argv, - mntbuf[mntsize].f_fstypename, - "file system"); - else - ++mntsize; - else - warn("%s", *argv); - } - } - - maxwidth = 0; - for (i = 0; i < mntsize; i++) { - width = (int)strlen(mntbuf[i].f_mntfromname); - if (width > maxwidth) - maxwidth = width; - } - for (i = 0; i < mntsize; i++) - prtstat(&mntbuf[i], maxwidth); - return 0; -} - -static char * -getmntpt(const char *name) -{ - size_t mntsize, i; - struct statvfs *mntbuf; - - mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); - if (mntsize == 0) - err(EXIT_FAILURE, "Can't get mount information"); - for (i = 0; i < mntsize; i++) { - if (!strcmp(mntbuf[i].f_mntfromname, name)) - return mntbuf[i].f_mntonname; - } - return 0; -} - -static enum { IN_LIST, NOT_IN_LIST } which; - -static int -selected(const char *type, size_t len) -{ - char **av; - - /* If no type specified, it's always selected. */ - if (typelist == NULL) - return 1; - for (av = typelist; *av != NULL; ++av) - if (!strncmp(type, *av, len)) - return which == IN_LIST ? 1 : 0; - return which == IN_LIST ? 0 : 1; -} - -static void -maketypelist(char *fslist) -{ - size_t i; - char *nextcp, **av; - - if ((fslist == NULL) || (fslist[0] == '\0')) - errx(EXIT_FAILURE, "empty type list"); - - /* - * XXX - * Note: the syntax is "noxxx,yyy" for no xxx's and - * no yyy's, not the more intuitive "noyyy,noyyy". - */ - if (fslist[0] == 'n' && fslist[1] == 'o') { - fslist += 2; - which = NOT_IN_LIST; - } else - which = IN_LIST; - - /* Count the number of types. */ - for (i = 1, nextcp = fslist; - (nextcp = strchr(nextcp, ',')) != NULL; i++) - ++nextcp; - - /* Build an array of that many types. */ - if ((av = typelist = malloc((i + 1) * sizeof(*av))) == NULL) - err(EXIT_FAILURE, "can't allocate type array"); - av[0] = fslist; - for (i = 1, nextcp = fslist; - (nextcp = strchr(nextcp, ',')) != NULL; i++) { - *nextcp = '\0'; - av[i] = ++nextcp; - } - /* Terminate the array. */ - av[i] = NULL; -} - -/* - * Make a pass over the filesystem info in ``mntbuf'' filtering out - * filesystem types not in ``fsmask'' and possibly re-stating to get - * current (not cached) info. Returns the new count of valid statvfs bufs. - */ -static size_t -regetmntinfo(struct statvfs **mntbufp, size_t mntsize) -{ - size_t i, j; - struct statvfs *mntbuf; - - if (!lflag && typelist == NULL && aflag) - return nflag ? mntsize : (size_t)getmntinfo(mntbufp, MNT_WAIT); - - mntbuf = *mntbufp; - j = 0; - for (i = 0; i < mntsize; i++) { - if (!aflag && (mntbuf[i].f_flag & MNT_IGNORE) != 0) - continue; - if (lflag && (mntbuf[i].f_flag & MNT_LOCAL) == 0) - continue; - if (!selected(mntbuf[i].f_fstypename, - sizeof(mntbuf[i].f_fstypename))) - continue; - if (nflag) - mntbuf[j] = mntbuf[i]; - else { - struct statvfs layerbuf = mntbuf[i]; - (void)statvfs(mntbuf[i].f_mntonname, &mntbuf[j]); - /* - * If the FS name changed, then new data is for - * a different layer and we don't want it. - */ - if (memcmp(layerbuf.f_mntfromname, - mntbuf[j].f_mntfromname, MNAMELEN)) - mntbuf[j] = layerbuf; - } - j++; - } - return j; -} - -static void -prthumanval(int64_t bytes, const char *pad) -{ - char buf[6]; - - (void)humanize_number(buf, sizeof(buf) - (bytes < 0 ? 0 : 1), - bytes, "", HN_AUTOSCALE, - HN_B | HN_NOSPACE | HN_DECIMAL); - - (void)printf("%s %6s", pad, buf); -} - -static void -prthuman(struct statvfs *sfsp, int64_t used, int64_t bavail) -{ - - prthumanval((int64_t)(sfsp->f_blocks * sfsp->f_frsize), " "); - prthumanval((int64_t)(used * sfsp->f_frsize), " "); - prthumanval((int64_t)(bavail * sfsp->f_frsize), " "); -} - -/* - * Convert statvfs returned filesystem size into BLOCKSIZE units. - * Attempts to avoid overflow for large filesystems. - */ -#define fsbtoblk(num, fsbs, bs) \ - (((fsbs) != 0 && (uint64_t)(fsbs) < (uint64_t)(bs)) ? \ - (int64_t)(num) / (int64_t)((bs) / (fsbs)) : \ - (int64_t)(num) * (int64_t)((fsbs) / (bs))) - -/* - * Print out status about a filesystem. - */ -static void -prtstat(struct statvfs *sfsp, int maxwidth) -{ - static long blocksize; - static int headerlen, timesthrough; - static const char *header; - static const char full[] = "100"; - static const char empty[] = " 0"; - int64_t used, availblks, inodes; - int64_t bavail; - char pb[64]; - - if (gflag) { - /* - * From SunOS-5.6: - * - * /var (/dev/dsk/c0t0d0s3 ): 8192 block size 1024 frag size - * 984242 total blocks 860692 free blocks 859708 available 249984 total files - * 248691 free files 8388611 filesys id - * ufs fstype 0x00000004 flag 255 filename length - * - */ - (void)printf("%10s (%-12s): %7ld block size %12ld frag size\n", - sfsp->f_mntonname, sfsp->f_mntfromname, - sfsp->f_bsize, /* On UFS/FFS systems this is - * also called the "optimal - * transfer block size" but it - * is of course the file - * system's block size too. - */ - sfsp->f_frsize); /* not so surprisingly the - * "fundamental file system - * block size" is the frag - * size. - */ - (void)printf("%10" PRId64 " total blocks %10" PRId64 - " free blocks %10" PRId64 " available\n", - (uint64_t)sfsp->f_blocks, (uint64_t)sfsp->f_bfree, - (uint64_t)sfsp->f_bavail); - (void)printf("%10" PRId64 " total files %10" PRId64 - " free files %12lx filesys id\n", - (uint64_t)sfsp->f_ffree, (uint64_t)sfsp->f_files, - sfsp->f_fsid); - (void)printf("%10s fstype %#15lx flag %17ld filename " - "length\n", sfsp->f_fstypename, sfsp->f_flag, - sfsp->f_namemax); - (void)printf("%10lu owner %17" PRId64 " syncwrites %12" PRId64 - " asyncwrites\n\n", (unsigned long)sfsp->f_owner, - sfsp->f_syncwrites, sfsp->f_asyncwrites); - - /* - * a concession by the structured programming police to the - * indentation police.... - */ - return; - } - if (maxwidth < 12) - maxwidth = 12; - if (++timesthrough == 1) { - switch (blocksize = usize) { - case 1024: - header = Pflag ? "1024-blocks" : "1K-blocks"; - headerlen = (int)strlen(header); - break; - case 1024 * 1024: - header = "1M-blocks"; - headerlen = (int)strlen(header); - break; - case 1024 * 1024 * 1024: - header = "1G-blocks"; - headerlen = (int)strlen(header); - break; - default: - if (hflag) { - header = "Size"; - headerlen = (int)strlen(header); - } else - header = getbsize(&headerlen, &blocksize); - break; - } - if (Pflag) { - /* - * either: - * "Filesystem 1024-blocks Used Available Capacity Mounted on\n" - * or: - * "Filesystem 512-blocks Used Available Capacity Mounted on\n" - */ - if (blocksize != 1024 && blocksize != 512) - errx(EXIT_FAILURE, - "non-standard block size incompatible with -P"); - (void)printf("Filesystem %s Used Available Capacity " - "Mounted on\n", header); - } else { - (void)printf("%-*.*s %s Used Avail %%Cap", - maxwidth - (headerlen - 10), - maxwidth - (headerlen - 10), - "Filesystem", header); - if (iflag) - (void)printf(" iUsed iAvail %%iCap"); - (void)printf(" Mounted on\n"); - } - } - used = sfsp->f_blocks - sfsp->f_bfree; - bavail = sfsp->f_bfree - sfsp->f_bresvd; - availblks = bavail + used; - if (Pflag) { - assert(hflag == 0); - assert(blocksize > 0); - /* - * "%s %d %d %d %s %s\n", , , - * , , , - * - */ - (void)printf("%s %" PRId64 " %" PRId64 " %" PRId64 " %s%% %s\n", - sfsp->f_mntfromname, - fsbtoblk(sfsp->f_blocks, sfsp->f_frsize, blocksize), - fsbtoblk(used, sfsp->f_frsize, blocksize), - fsbtoblk(bavail, sfsp->f_frsize, blocksize), - availblks == 0 ? full : strspct(pb, sizeof(pb), used, - availblks, 0), sfsp->f_mntonname); - /* - * another concession by the structured programming police to - * the indentation police.... - * - * Note iflag cannot be set when Pflag is set. - */ - return; - } - - (void)printf("%-*.*s ", maxwidth, maxwidth, sfsp->f_mntfromname); - - if (hflag) - prthuman(sfsp, used, bavail); - else - (void)printf("%10" PRId64 " %10" PRId64 " %10" PRId64, - fsbtoblk(sfsp->f_blocks, sfsp->f_frsize, blocksize), - fsbtoblk(used, sfsp->f_frsize, blocksize), - fsbtoblk(bavail, sfsp->f_frsize, blocksize)); - (void)printf(" %3s%%", - availblks == 0 ? full : - strspct(pb, sizeof(pb), used, availblks, 0)); - if (iflag) { - inodes = sfsp->f_files; - used = inodes - sfsp->f_ffree; - (void)printf(" %8jd %8jd %4s%%", - (intmax_t)used, (intmax_t)sfsp->f_ffree, - inodes == 0 ? (used == 0 ? empty : full) : - strspct(pb, sizeof(pb), used, inodes, 0)); - } - (void)printf(" %s\n", sfsp->f_mntonname); -} - -static void -usage(void) -{ - - (void)fprintf(stderr, - "Usage: %s [-agln] [-Ghkm|-ihkm|-Pk] [-t type] [file | " - "file_system ...]\n", - getprogname()); - exit(1); - /* NOTREACHED */ -} diff --git a/bin/domainname/Makefile b/bin/domainname/Makefile deleted file mode 100644 index 5e0164f31..000000000 --- a/bin/domainname/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# $NetBSD: Makefile,v 1.6 1997/07/20 22:36:50 christos Exp $ -# @(#)Makefile 8.1 (Berkeley) 5/31/93 - -PROG= domainname - -.include diff --git a/bin/domainname/domainname.1 b/bin/domainname/domainname.1 deleted file mode 100644 index c52159dfa..000000000 --- a/bin/domainname/domainname.1 +++ /dev/null @@ -1,65 +0,0 @@ -.\" $NetBSD: domainname.1,v 1.15 2004/06/15 14:08:33 jmmv Exp $ -.\" -.\" Copyright (c) 1983, 1988, 1990, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)hostname.1 8.1 (Berkeley) 5/31/93 -.\" -.Dd May 31, 1993 -.Dt DOMAINNAME 1 -.Os -.Sh NAME -.Nm domainname -.Nd set or print YP domain of current host system -.Sh SYNOPSIS -.Nm -.Op Ar name-of-domain -.Sh DESCRIPTION -.Nm -prints the -.Tn YP -domain name of the current host. -The super-user can set the domain name by supplying an argument; -this is usually done in the network initialization script -.Pa /etc/rc.d/network , -normally run at boot -time. -.Sh SEE ALSO -.Xr hostname 1 , -.Xr getdomainname 3 , -.Xr setdomainname 3 -.Sh HISTORY -The -.Nm -utility is derived from the -.Nm hostname -utility, which appeared in -.Bx 4.2 . -The -.Nm -utility appeared in -.Nx 0.8 . diff --git a/bin/domainname/domainname.c b/bin/domainname/domainname.c deleted file mode 100644 index b06cbdf2d..000000000 --- a/bin/domainname/domainname.c +++ /dev/null @@ -1,95 +0,0 @@ -/* $NetBSD: domainname.c,v 1.15 2011/08/29 14:51:18 joerg Exp $ */ - -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1988, 1993\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)hostname.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: domainname.c,v 1.15 2011/08/29 14:51:18 joerg Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include -#include -#include -#include - -__dead static void usage(void); - -int -main(int argc, char *argv[]) -{ - int ch; - char domainname[MAXHOSTNAMELEN]; - - setprogname(argv[0]); - - while ((ch = getopt(argc, argv, "")) != -1) { - switch (ch) { - case '?': - default: - usage(); - /* NOTREACHED */ - } - } - argc -= optind; - argv += optind; - - if (argc > 1) - usage(); - - if (*argv) { - if (setdomainname(*argv, strlen(*argv))) - err(1, "setdomainname"); - } else { - if (getdomainname(domainname, sizeof(domainname))) - err(1, "getdomainname"); - (void)printf("%s\n", domainname); - } - exit(EXIT_SUCCESS); - /* NOTREACHED */ -} - -static void -usage(void) -{ - (void)fprintf(stderr, "usage: %s [name-of-domain]\n", getprogname()); - exit(EXIT_FAILURE); -} diff --git a/bin/ed/Makefile b/bin/ed/Makefile deleted file mode 100644 index b7ecc8454..000000000 --- a/bin/ed/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# $NetBSD: Makefile,v 1.37 2017/05/21 15:28:36 riastradh Exp $ - -.include - -PROG= ed -CPPFLAGS+=-DBACKWARDS -CPPFLAGS+=-DDES - -SRCS= buf.c cbc.c glbl.c io.c main.c re.c sub.c undo.c - -LDADD+= -lcrypt -DPADD+= ${LIBCRYPT} - -#LINKS= ${BINDIR}/ed ${BINDIR}/red -#MLINKS= ed.1 red.1 - -.include diff --git a/bin/ed/POSIX b/bin/ed/POSIX deleted file mode 100644 index 6bea801d4..000000000 --- a/bin/ed/POSIX +++ /dev/null @@ -1,103 +0,0 @@ -$NetBSD: POSIX,v 1.10 1999/11/18 19:16:34 kristerw Exp $ - -This version of ed(1) is not strictly POSIX compliant, as described in -the POSIX 1003.2 document. The following is a summary of the omissions, -extensions and possible deviations from POSIX 1003.2. - -OMISSIONS ---------- -1) Locale(3) is not supported yet. - -2) For backwards compatibility, the POSIX rule that says a range of - addresses cannot be used where only a single address is expected has - been relaxed. - -3) To support the BSD `s' command (see extension [1] below), - substitution patterns cannot be delimited by numbers or the characters - `r', `g' and `p'. In contrast, POSIX specifies any character expect - space or newline can used as a delimiter. - -EXTENSIONS ----------- -1) BSD commands have been implemented wherever they do not conflict with - the POSIX standard. The BSD-ism's included are: - i) `s' (i.e., s[n][rgp]*) to repeat a previous substitution, - ii) `W' for appending text to an existing file, - iii) `wq' for exiting after a write, - iv) `z' for scrolling through the buffer, and - v) BSD line addressing syntax (i.e., `^' and `%') is recognized. - -2) If crypt(3) is available, files can be read and written using DES - encryption. The `x' command prompts the user to enter a key used for - encrypting/ decrypting subsequent reads and writes. If only a newline - is entered as the key, then encryption is disabled. Otherwise, a key - is read in the same manner as a password entry. The key remains in - effect until encryption is disabled. For more information on the - encryption algorithm, see the bdes(1) man page. Encryption/decryption - should be fully compatible with SunOS des(1). - -3) The POSIX interactive global commands `G' and `V' are extended to - support multiple commands, including `a', `i' and `c'. The command - format is the same as for the global commands `g' and `v', i.e., one - command per line with each line, except for the last, ending in a - backslash (\). - -4) An extension to the POSIX file commands `E', `e', `r', `W' and `w' is - that arguments are processed for backslash escapes, i.e., any - character preceded by a backslash is interpreted literally. If the - first unescaped character of a argument is a bang (!), then the - rest of the line is interpreted as a shell command, and no escape - processing is performed by ed. - -5) For SunOS ed(1) compatibility, ed runs in restricted mode if invoked - as red. This limits editing of files in the local directory only and - prohibits shell commands. - -DEVIATIONS ----------- -1) Though ed is not a stream editor, it can be used to edit binary files. - To assist in binary editing, when a file containing at least one ASCII - NUL character is written, a newline is not appended if it did not - already contain one upon reading. In particular, reading /dev/null - prior to writing prevents appending a newline to a binary file. - - For example, to create a file with ed containing a single NUL character: - $ ed file - a - ^@ - . - r /dev/null - wq - - Similarly, to remove a newline from the end of binary `file': - $ ed file - r /dev/null - wq - -2) Since the behavior of `u' (undo) within a `g' (global) command list is - not specified by POSIX, it follows the behavior of the SunOS ed: - undo forces a global command list to be executed only once, rather than - for each line matching a global pattern. In addtion, each instance of - `u' within a global command undoes all previous commands (including - undo's) in the command list. This seems the best way, since the - alternatives are either too complicated to implement or too confusing - to use. - - The global/undo combination is useful for masking errors that - would otherwise cause a script to fail. For instance, an ed script - to remove any occurrences of either `censor1' or `censor2' might be - written as: - ed - file < -#ifndef lint -#if 0 -static char *rcsid = "@(#)buf.c,v 1.4 1994/02/01 00:34:35 alm Exp"; -#else -__RCSID("$NetBSD: buf.c,v 1.27 2014/03/23 05:06:42 dholland Exp $"); -#endif -#endif /* not lint */ - -#include -#include - -#include -#include -#include - -#include "ed.h" - - -FILE *sfp; /* scratch file pointer */ -off_t sfseek; /* scratch file position */ -int seek_write; /* seek before writing */ -line_t buffer_head; /* incore buffer */ - -/* get_sbuf_line: get a line of text from the scratch file; return pointer - to the text */ -char * -get_sbuf_line(line_t *lp) -{ - static char *sfbuf = NULL; /* buffer */ - static int sfbufsz = 0; /* buffer size */ - - int len, ct; - - if (lp == &buffer_head) - return NULL; - seek_write = 1; /* force seek on write */ - /* out of position */ - if (sfseek != lp->seek) { - sfseek = lp->seek; - if (fseek(sfp, sfseek, SEEK_SET) < 0) { - fprintf(stderr, "%s\n", strerror(errno)); - seterrmsg("cannot seek temp file"); - return NULL; - } - } - len = lp->len; - REALLOC(sfbuf, sfbufsz, len + 1, NULL); - if ((ct = fread(sfbuf, sizeof(char), len, sfp)) < 0 || ct != len) { - fprintf(stderr, "%s\n", strerror(errno)); - seterrmsg("cannot read temp file"); - return NULL; - } - sfseek += len; /* update file position */ - sfbuf[len] = '\0'; - return sfbuf; -} - - -/* put_sbuf_line: write a line of text to the scratch file and add a line node - to the editor buffer; return a pointer to the end of the text */ -char * -put_sbuf_line(char *cs) -{ - line_t *lp; - int len, ct; - char *s; - - if ((lp = (line_t *) malloc(sizeof(line_t))) == NULL) { - fprintf(stderr, "%s\n", strerror(errno)); - seterrmsg("out of memory"); - return NULL; - } - /* assert: cs is '\n' terminated */ - for (s = cs; *s != '\n'; s++) - ; - if (s - cs >= LINECHARS) { - seterrmsg("line too long"); - free(lp); - return NULL; - } - len = s - cs; - /* out of position */ - if (seek_write) { - if (fseek(sfp, 0L, SEEK_END) < 0) { - fprintf(stderr, "%s\n", strerror(errno)); - seterrmsg("cannot seek temp file"); - free(lp); - return NULL; - } - sfseek = ftell(sfp); - seek_write = 0; - } - /* assert: SPL1() */ - if ((ct = fwrite(cs, sizeof(char), len, sfp)) < 0 || ct != len) { - sfseek = -1; - fprintf(stderr, "%s\n", strerror(errno)); - seterrmsg("cannot write temp file"); - free(lp); - return NULL; - } - lp->len = len; - lp->seek = sfseek; - add_line_node(lp); - sfseek += len; /* update file position */ - return ++s; -} - - -/* add_line_node: add a line node in the editor buffer after the current line */ -void -add_line_node(line_t *lp) -{ - line_t *cp; - - cp = get_addressed_line_node(current_addr); /* this get_addressed_line_node last! */ - INSQUE(lp, cp); - addr_last++; - current_addr++; -} - - -/* get_line_node_addr: return line number of pointer */ -long -get_line_node_addr(line_t *lp) -{ - line_t *cp = &buffer_head; - long n = 0; - - while (cp != lp && (cp = cp->q_forw) != &buffer_head) - n++; - if (n && cp == &buffer_head) { - seterrmsg("invalid address"); - return ERR; - } - return n; -} - - -/* get_addressed_line_node: return pointer to a line node in the editor buffer */ -line_t * -get_addressed_line_node(long n) -{ - static line_t *lp = &buffer_head; - static long on = 0; - - SPL1(); - if (n > on) { - if (n <= (on + addr_last) >> 1) { - for (; on < n; on++) - lp = lp->q_forw; - } else { - lp = buffer_head.q_back; - for (on = addr_last; on > n; on--) - lp = lp->q_back; - } - } else { - if (n >= on >> 1) { - for (; on > n; on--) - lp = lp->q_back; - } else { - lp = &buffer_head; - for (on = 0; on < n; on++) - lp = lp->q_forw; - } - } - SPL0(); - return lp; -} - - -char *sfn = NULL; /* scratch file name */ - -/* open_sbuf: open scratch file */ -int -open_sbuf(void) -{ - int u, fd; - const char *tmp; - size_t s; - - isbinary = newline_added = 0; - fd = -1; - u = umask(077); - - if ((tmp = getenv("TMPDIR")) == NULL) - tmp = _PATH_TMP; - - if ((s = strlen(tmp)) == 0 || tmp[s - 1] == '/') - (void)asprintf(&sfn, "%sed.XXXXXX", tmp); - else - (void)asprintf(&sfn, "%s/ed.XXXXXX", tmp); - if (sfn == NULL) { - warn(NULL); - seterrmsg("could not allocate memory"); - umask(u); - return ERR; - } - - - if ((fd = mkstemp(sfn)) == -1 || (sfp = fdopen(fd, "w+")) == NULL) { - if (fd != -1) - close(fd); - warn("%s", sfn); - seterrmsg("cannot open temp file"); - umask(u); - return ERR; - } - umask(u); - return 0; -} - - -/* close_sbuf: close scratch file */ -int -close_sbuf(void) -{ - if (sfp) { - if (fclose(sfp) < 0) { - fprintf(stderr, "%s: %s\n", sfn, strerror(errno)); - seterrmsg("cannot close temp file"); - return ERR; - } - sfp = NULL; - if (sfn) { - unlink(sfn); - free(sfn); - sfn = NULL; - } - } - sfseek = seek_write = 0; - return 0; -} - - -/* quit: remove_lines scratch file and exit */ -void -quit(int n) -{ - if (sfp) { - fclose(sfp); - if (sfn) { - unlink(sfn); - free(sfn); - sfn = NULL; - } - } - exit(n); - /* NOTREACHED */ -} - - -unsigned char ctab[256]; /* character translation table */ - -/* init_buffers: open scratch buffer; initialize line queue */ -void -init_buffers(void) -{ - int i = 0; - - /* Read stdin one character at a time to avoid i/o contention - with shell escapes invoked by nonterminal input, e.g., - ed - < 0; us++) - *us = ctab[*us]; - return s; -} diff --git a/bin/ed/cbc.c b/bin/ed/cbc.c deleted file mode 100644 index ef4282915..000000000 --- a/bin/ed/cbc.c +++ /dev/null @@ -1,460 +0,0 @@ -/* $NetBSD: cbc.c,v 1.24 2016/02/01 17:34:00 christos Exp $ */ - -/* cbc.c: This file contains the encryption routines for the ed line editor */ -/*- - * Copyright (c) 1993 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)bdes.c 5.5 (Berkeley) 6/27/91 - */ - -/*- - * Copyright (c) 1993 Andrew Moore, Talke Studio. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)bdes.c 5.5 (Berkeley) 6/27/91 - */ - -#include -#ifndef lint -#if 0 -static char *rcsid = "@(#)cbc.c,v 1.2 1994/02/01 00:34:36 alm Exp"; -#else -__RCSID("$NetBSD: cbc.c,v 1.24 2016/02/01 17:34:00 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#ifdef DES -#include -#endif - -#include "ed.h" - - -/* - * Define a divisor for rand() that yields a uniform distribution in the - * range 0-255. - */ -#define RAND_DIV (((unsigned) RAND_MAX + 1) >> 8) - -/* - * BSD and System V systems offer special library calls that do - * block move_liness and fills, so if possible we take advantage of them - */ -#define MEMCPY(dest,src,len) memcpy((dest),(src),(len)) -#define MEMZERO(dest,len) memset((dest), 0, (len)) - -/* Hide the calls to the primitive encryption routines. */ -#define DES_KEY(buf) \ - if (des_setkey(buf)) \ - des_error("des_setkey"); -#define DES_XFORM(buf) \ - if (des_cipher(buf, buf, 0L, (inverse ? -1 : 1))) \ - des_error("des_cipher"); - -/* - * read/write - no error checking - */ -#define READ(buf, n, fp) fread(buf, sizeof(char), n, fp) -#define WRITE(buf, n, fp) fwrite(buf, sizeof(char), n, fp) - -/* - * some things to make references easier - */ -typedef char Desbuf[8]; -#define CHAR(x,i) (x[i]) -#define UCHAR(x,i) (x[i]) -#define BUFFER(x) (x) -#define UBUFFER(x) (x) - -#ifdef DES -/* - * global variables and related macros - */ - -static Desbuf ivec; /* initialization vector */ -static Desbuf pvec; /* padding vector */ -static char bits[] = { /* used to extract bits from a char */ - '\200', '\100', '\040', '\020', '\010', '\004', '\002', '\001' -}; -static int pflag; /* 1 to preserve parity bits */ - -static char des_buf[8]; /* shared buffer for get_des_char/put_des_char */ -static int des_ct = 0; /* count for get_des_char/put_des_char */ -static int des_n = 0; /* index for put_des_char/get_des_char */ -#endif - - -#ifdef DES -static void des_error(const char *); -static int hex_to_binary(int, int); -static void expand_des_key(char *, char *); -static void set_des_key(char *); -static int cbc_decode(char *, FILE *); -static int cbc_encode(char *, int, FILE *); -#endif - - -/* init_des_cipher: initialize DES */ -void -init_des_cipher(void) -{ -#ifdef DES - int i; - - des_ct = des_n = 0; - - /* initialize the initialization vector */ - MEMZERO(ivec, 8); - - /* intialize the padding vector */ - srand((unsigned) time((time_t *) 0)); - for (i = 0; i < 8; i++) - CHAR(pvec, i) = (char) (rand()/RAND_DIV); -#endif -} - - -/* get_des_char: return next char in an encrypted file */ -int -get_des_char(FILE *fp) -{ -#ifdef DES - if (des_n >= des_ct) { - des_n = 0; - des_ct = cbc_decode(des_buf, fp); - } - return (des_ct > 0) ? (unsigned char) des_buf[des_n++] : EOF; -#else - return EOF; -#endif -} - - -/* put_des_char: write a char to an encrypted file; return char written */ -int -put_des_char(int c, FILE *fp) -{ -#ifdef DES - if (des_n == sizeof des_buf) { - des_ct = cbc_encode(des_buf, des_n, fp); - des_n = 0; - } - return (des_ct >= 0) ? (unsigned char) (des_buf[des_n++] = c) : EOF; -#else - return EOF; -#endif -} - - -/* flush_des_file: flush an encrypted file's output; return status */ -int -flush_des_file(FILE *fp) -{ -#ifdef DES - if (des_n == sizeof des_buf) { - des_ct = cbc_encode(des_buf, des_n, fp); - des_n = 0; - } - return (des_ct >= 0 && cbc_encode(des_buf, des_n, fp) >= 0) ? 0 : EOF; -#else - return EOF; -#endif -} - -#ifdef DES -/* - * get keyword from tty or stdin - */ -int -get_keyword(void) -{ - char *p; /* used to obtain the key */ - Desbuf msgbuf; /* I/O buffer */ - - /* - * get the key - */ - if (*(p = getpass("Enter key: "))) { - - /* - * copy it, nul-padded, into the key area - */ - expand_des_key(BUFFER(msgbuf), p); - MEMZERO(p, _PASSWORD_LEN); - set_des_key(msgbuf); - MEMZERO(msgbuf, sizeof msgbuf); - return 1; - } - return 0; -} - - -/* - * print a warning message and, possibly, terminate - */ -static void -des_error(const char *s /* the message */) -{ - seterrmsg("%s", s ? s : strerror(errno)); -} - -/* - * map a hex character to an integer - */ -static int -hex_to_binary(int c /* char to be converted */, - int radix /* base (2 to 16) */) -{ - switch(c) { - case '0': return(0x0); - case '1': return(0x1); - case '2': return(radix > 2 ? 0x2 : -1); - case '3': return(radix > 3 ? 0x3 : -1); - case '4': return(radix > 4 ? 0x4 : -1); - case '5': return(radix > 5 ? 0x5 : -1); - case '6': return(radix > 6 ? 0x6 : -1); - case '7': return(radix > 7 ? 0x7 : -1); - case '8': return(radix > 8 ? 0x8 : -1); - case '9': return(radix > 9 ? 0x9 : -1); - case 'A': case 'a': return(radix > 10 ? 0xa : -1); - case 'B': case 'b': return(radix > 11 ? 0xb : -1); - case 'C': case 'c': return(radix > 12 ? 0xc : -1); - case 'D': case 'd': return(radix > 13 ? 0xd : -1); - case 'E': case 'e': return(radix > 14 ? 0xe : -1); - case 'F': case 'f': return(radix > 15 ? 0xf : -1); - } - /* - * invalid character - */ - return(-1); -} - -/* - * convert the key to a bit pattern - */ -static void -expand_des_key(char *obuf /* bit pattern */, char *inbuf /* the key itself */) -{ - int i, j; /* counter in a for loop */ - int nbuf[64]; /* used for hex/key translation */ - - /* - * leading '0x' or '0X' == hex key - */ - if (inbuf[0] == '0' && (inbuf[1] == 'x' || inbuf[1] == 'X')) { - inbuf = &inbuf[2]; - /* - * now translate it, bombing on any illegal hex digit - */ - for (i = 0; i < 16 && inbuf[i]; i++) - if ((nbuf[i] = hex_to_binary((int) inbuf[i], 16)) == -1) - des_error("bad hex digit in key"); - while (i < 16) - nbuf[i++] = 0; - for (i = 0; i < 8; i++) - obuf[i] = - ((nbuf[2*i]&0xf)<<4) | (nbuf[2*i+1]&0xf); - /* preserve parity bits */ - pflag = 1; - return; - } - /* - * leading '0b' or '0B' == binary key - */ - if (inbuf[0] == '0' && (inbuf[1] == 'b' || inbuf[1] == 'B')) { - inbuf = &inbuf[2]; - /* - * now translate it, bombing on any illegal binary digit - */ - for (i = 0; i < 16 && inbuf[i]; i++) - if ((nbuf[i] = hex_to_binary((int) inbuf[i], 2)) == -1) - des_error("bad binary digit in key"); - while (i < 64) - nbuf[i++] = 0; - for (i = 0; i < 8; i++) - for (j = 0; j < 8; j++) - obuf[i] = (obuf[i]<<1)|nbuf[8*i+j]; - /* preserve parity bits */ - pflag = 1; - return; - } - /* - * no special leader -- ASCII - */ - (void)strncpy(obuf, inbuf, 8); -} - -/***************** - * DES FUNCTIONS * - *****************/ -/* - * This sets the DES key and (if you're using the deszip version) - * the direction of the transformation. This uses the Sun - * to map the 64-bit key onto the 56 bits that the key schedule - * generation routines use: the old way, which just uses the user- - * supplied 64 bits as is, and the new way, which resets the parity - * bit to be the same as the low-order bit in each character. The - * new way generates a greater variety of key schedules, since many - * systems set the parity (high) bit of each character to 0, and the - * DES ignores the low order bit of each character. - */ -static void -set_des_key(Desbuf buf /* key block */) -{ - int i, j; /* counter in a for loop */ - int par; /* parity counter */ - - /* - * if the parity is not preserved, flip it - */ - if (!pflag) { - for (i = 0; i < 8; i++) { - par = 0; - for (j = 1; j < 8; j++) - if ((bits[j]&UCHAR(buf, i)) != 0) - par++; - if ((par&01) == 01) - UCHAR(buf, i) = UCHAR(buf, i)&0177; - else - UCHAR(buf, i) = (UCHAR(buf, i)&0177)|0200; - } - } - - DES_KEY(UBUFFER(buf)); -} - - -/* - * This encrypts using the Cipher Block Chaining mode of DES - */ -static int -cbc_encode(char *msgbuf, int n, FILE *fp) -{ - int inverse = 0; /* 0 to encrypt, 1 to decrypt */ - - /* - * do the transformation - */ - if (n == 8) { - for (n = 0; n < 8; n++) - CHAR(msgbuf, n) ^= CHAR(ivec, n); - DES_XFORM(UBUFFER(msgbuf)); - MEMCPY(BUFFER(ivec), BUFFER(msgbuf), 8); - return WRITE(BUFFER(msgbuf), 8, fp); - } - /* - * at EOF or last block -- in either case, the last byte contains - * the character representation of the number of bytes in it - */ -/* - MEMZERO(msgbuf + n, 8 - n); -*/ - /* - * Pad the last block randomly - */ - (void)MEMCPY(BUFFER(msgbuf + n), BUFFER(pvec), 8 - n); - CHAR(msgbuf, 7) = n; - for (n = 0; n < 8; n++) - CHAR(msgbuf, n) ^= CHAR(ivec, n); - DES_XFORM(UBUFFER(msgbuf)); - return WRITE(BUFFER(msgbuf), 8, fp); -} - -/* - * This decrypts using the Cipher Block Chaining mode of DES - */ -static int -cbc_decode(char *msgbuf /* I/O buffer */, - FILE *fp /* input file descriptor */) -{ - Desbuf inbuf; /* temp buffer for initialization vector */ - int n; /* number of bytes actually read */ - int c; /* used to test for EOF */ - int inverse = 1; /* 0 to encrypt, 1 to decrypt */ - - if ((n = READ(BUFFER(msgbuf), 8, fp)) == 8) { - /* - * do the transformation - */ - MEMCPY(BUFFER(inbuf), BUFFER(msgbuf), 8); - DES_XFORM(UBUFFER(msgbuf)); - for (c = 0; c < 8; c++) - UCHAR(msgbuf, c) ^= UCHAR(ivec, c); - MEMCPY(BUFFER(ivec), BUFFER(inbuf), 8); - /* - * if the last one, handle it specially - */ - if ((c = fgetc(fp)) == EOF) { - n = CHAR(msgbuf, 7); - if (n < 0 || n > 7) { - des_error("decryption failed (block corrupted)"); - return EOF; - } - } else - (void)ungetc(c, fp); - return n; - } - if (n > 0) - des_error("decryption failed (incomplete block)"); - else if (n < 0) - des_error("cannot read file"); - return EOF; -} -#endif /* DES */ diff --git a/bin/ed/ed.1 b/bin/ed/ed.1 deleted file mode 100644 index c459197b3..000000000 --- a/bin/ed/ed.1 +++ /dev/null @@ -1,979 +0,0 @@ -.\" $NetBSD: ed.1,v 1.30.40.1 2018/04/08 06:04:08 snj Exp $ -.\" $OpenBSD: ed.1,v 1.42 2003/07/27 13:25:43 jmc Exp $ -.\" -.\" Copyright (c) 1993 Andrew Moore, Talke Studio. -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.Dd April 5, 2018 -.Dt ED 1 -.Os -.Sh NAME -.Nm ed -.Nd text editor -.Sh SYNOPSIS -.Nm -.Op Fl -.Op Fl ESsx -.Op Fl p Ar string -.Op Ar file -.Sh DESCRIPTION -.Nm -is a line-oriented text editor. -It is used to create, display, modify, and otherwise manipulate text files. -If invoked with a -.Ar file -argument, then a copy of -.Ar file -is read into the editor's buffer. -Changes are made to this copy and not directly to -.Ar file -itself. -Upon quitting -.Nm , -any changes not explicitly saved with a -.Ic w -command are lost. -.Pp -Editing is done in two distinct modes: -.Em command -and -.Em input . -When first invoked, -.Nm -is in command mode. -In this mode, commands are read from the standard input and -executed to manipulate the contents of the editor buffer. -.Pp -A typical command might look like: -.Bd -literal -offset indent -,s/old/new/g -.Ed -.Pp -which replaces all occurrences of the string -.Pa old -with -.Pa new . -.Pp -When an input command, such as -.Ic a -(append), -.Ic i -(insert), -or -.Ic c -(change) is given, -.Nm -enters input mode. -This is the primary means of adding text to a file. -In this mode, no commands are available; -instead, the standard input is written directly to the editor buffer. -Lines consist of text up to and including a newline character. -Input mode is terminated by entering a single period -.Pq Ql \&. -on a line. -.Pp -All -.Nm -commands operate on whole lines or ranges of lines; e.g., -the -.Ic d -command deletes lines; the -.Ic m -command moves lines, and so on. -It is possible to modify only a portion of a line by means of replacement, -as in the example above. -However, even here, the -.Ic s -command is applied to whole lines at a time. -.Pp -In general, -.Nm -commands consist of zero or more line addresses, followed by a single -character command and possibly additional parameters; i.e., -commands have the structure: -.Bd -literal -offset indent -[address [,address]]command[parameters] -.Ed -.Pp -The address(es) indicate the line or range of lines to be affected by the -command. -If fewer addresses are given than the command accepts, then -default addresses are supplied. -.Pp -The options are as follows: -.Bl -tag -width Ds -.It Fl -Same as the -.Fl s -option (deprecated). -.It Fl E -Enables the use of extended regular expressions instead of the basic -regular expressions that are normally used. -.It Fl S -Disables using of the -.Dq ! -command (execuring a subshell). -Intended to be used by batch jobs like -.Xr patch 1 . -.It Fl p Ar string -Specifies a command prompt. -This may be toggled on and off with the -.Ic P -command. -.It Fl s -Suppress diagnostics. -This should be used if -.Nm -standard input is from a script. -.It Fl x -Prompt for an encryption key to be used in subsequent reads and writes -(see the -.Ic x -command). -.It Ar file -Specifies the name of a file to read. -If -.Ar file -is prefixed with a -bang -.Pq Ql \&! , -then it is interpreted as a shell command. -In this case, what is read is the standard output of -.Ar file -executed via -.Xr sh 1 . -To read a file whose name begins with a bang, prefix the -name with a backslash -.Pq Ql \e . -The default filename is set to -.Ar file -only if it is not prefixed with a bang. -.El -.Ss LINE ADDRESSING -An address represents the number of a line in the buffer. -.Nm -maintains a -.Em current address -which is typically supplied to commands as the default address -when none is specified. -When a file is first read, the current address is set to the last line -of the file. -In general, the current address is set to the last line affected by a command. -.Pp -A line address is -constructed from one of the bases in the list below, optionally followed -by a numeric offset. -The offset may include any combination of digits, operators (i.e., -.Sq + , -.Sq - , -and -.Sq ^ ) , -and whitespace. -Addresses are read from left to right, and their values are computed -relative to the current address. -.Pp -One exception to the rule that addresses represent line numbers is the -address -.Em 0 -(zero). -This means -.Dq before the first line , -and is legal wherever it makes sense. -.Pp -An address range is two addresses separated either by a comma or semi-colon. -The value of the first address in a range cannot exceed the -value of the second. -If only one address is given in a range, -then the second address is set to the given address. -If an -.Em n Ns No -tuple -of addresses is given where -.Em n \*[Gt] 2 , -then the corresponding range is determined by the last two addresses in the -.Em n Ns No -tuple. -If only one address is expected, then the last address is used. -.Pp -Each address in a comma-delimited range is interpreted relative to the -current address. -In a semi-colon-delimited range, the first address is -used to set the current address, and the second address is interpreted -relative to the first. -.Pp -The following address symbols are recognized: -.Bl -tag -width Ds -.It Em \&. -The current line (address) in the buffer. -.It Em $ -The last line in the buffer. -.It Em n -The -.Em n Ns No th -line in the buffer where -.Em n -is a number in the range -.Em [0,$] . -.It Em - No or Em ^ -The previous line. -This is equivalent to -.Em -1 -and may be repeated with cumulative effect. -.It Em -n No or Em ^n -The -.Em n Ns No th -previous line, where -.Em n -is a non-negative number. -.It Em + -The next line. -This is equivalent to -.Em +1 -and may be repeated with cumulative effect. -.It Em +n -The -.Em n Ns No th -next line, where -.Em n -is a non-negative number. -.It Em whitespace Em n -.Em whitespace -followed by a number -.Em n -is interpreted as -.Sq Em +n . -.It Em \&, No or Em % -The first through last lines in the buffer. -This is equivalent to the address range -.Em 1,$ . -.It Em \&; -The current through last lines in the buffer. -This is equivalent to the address range -.Em .,$ . -.It Em / Ns Ar re Ns Em / -The next line containing the regular expression -.Ar re . -The search wraps to the beginning of the buffer and continues down to the -current line, if necessary. -.Em // -repeats the last search. -.It Em \&? Ns Ar re Ns Em \&? -The previous line containing the regular expression -.Ar re . -The search wraps to the end of the buffer and continues up to the -current line, if necessary. -.Em ?? -repeats the last search. -.It Em \&\' Ns Ar lc -The line previously marked by a -.Ic k -(mark) command, where -.Ar lc -is a lower case letter. -.El -.Ss REGULAR EXPRESSIONS -Regular expressions are patterns used in selecting text. -For example, the -.Nm -command -.Bd -literal -offset indent -g/string/ -.Ed -.Pp -prints all lines containing -.Em string . -Regular expressions are also used by the -.Ic s -command for selecting old text to be replaced with new. -.Pp -In addition to specifying string literals, regular expressions can -represent classes of strings. -Strings thus represented are said to be matched by the -corresponding regular expression. -If it is possible for a regular expression to match several strings in -a line, then the leftmost longest match is the one selected. -.Pp -The following symbols are used in constructing regular expressions: -.Bl -tag -width Dsasdfsd -.It Em c -Any character -.Em c -not listed below, including -.Sq { , -.Sq } , -.Sq \&( , -.Sq \&) , -.Sq \*[Lt] , -and -.Sq \*[Gt] -matches itself. -.It Em \ec -Any backslash-escaped character -.Em c , -except for -.Sq { , -.Sq } , -.Sq \&( , -.Sq \&) , -.Sq \*[Lt] , -and -.Sq \*[Gt] -matches itself. -.It Em \&. -Matches any single character. -.It Em [char-class] -Matches any single character in the character class -.Em char-class . -See -.Sx CHARACTER CLASSES -below for further information. -.It Em [^char-class] -Matches any single character, other than newline, not in the -character class -.Em char-class . -.It Em ^ -If -.Em ^ -is the first character of a regular expression, then it -anchors the regular expression to the beginning of a line. -Otherwise, it matches itself. -.It Em $ -If -.Em $ -is the last character of a regular expression, -it anchors the regular expression to the end of a line. -Otherwise, it matches itself. -.It Em \e\*[Lt] -Anchors the single character regular expression or subexpression -immediately following it to the beginning of a word. -(This may not be available.) -.It Em \e\*[Gt] -Anchors the single character regular expression or subexpression -immediately following it to the end of a word. -(This may not be available.) -.It Em \e( Ns Ar re Ns Em \e) -Defines a subexpression -.Ar re . -Subexpressions may be nested. -A subsequent backreference of the form -.Em \en , -where -.Em n -is a number in the range [1,9], expands to the text matched by the -.Em n Ns No th -subexpression. -For example, the regular expression -.Em \e(.*\e)\e1 -matches any string consisting of identical adjacent substrings. -Subexpressions are ordered relative to their left delimiter. -.It Em * -Matches the single character regular expression or subexpression -immediately preceding it zero or more times. -If -.Em * -is the first character of a regular expression or subexpression, -then it matches itself. -The -.Em * -operator sometimes yields unexpected results. -For example, the regular expression -.Em b* -matches the beginning of the string -.Em abbb -(as opposed to the substring -.Em bbb ) , -since a null match is the only leftmost match. -.Sm off -.It Em \e{ No n,m Em \e}\ \e{ No n, Em \e}\ \& Em \e{ No n Em \e} -.Sm on -Matches the single character regular expression or subexpression -immediately preceding it at least -.Em n -and at most -.Em m -times. -If -.Em m -is omitted, then it matches at least -.Em n -times. -If the comma is also omitted, then it matches exactly -.Em n -times. -.El -.Pp -Additional regular expression operators may be defined depending on the -particular -.Xr regex 3 -implementation. -.Ss CHARACTER CLASSES -A character class specifies a set of characters. It is written within -square brackets -.Pq [] -and in its most basic form contains just the characters in the set. -.Pp -To include a -.Sq \&] -in a character class, it must be the first character. -A range of characters may be specified by separating the end characters -of the range with a -.Sq \&- , -e.g., -.Sq a-z -specifies the lower case characters. -.Pp -The following literals can also be used within character classes as -shorthand for particular sets of characters: -.Bl -tag -offset indent -compact -width [:blahblah:] -.It [:alnum:] -Alphanumeric characters. -.It [:cntrl:] -Control characters. -.It [:lower:] -Lowercase alphabetic characters. -.It [:space:] -Whitespace (space, tab, newline, form feed, etc.) -.It [:alpha:] -Alphabetic characters. -.It [:digit:] -Numeric characters (digits). -.It [:print:] -Printable characters. -.It [:upper:] -Uppercase alphabetic characters. -.It [:blank:] -Blank characters (space and tab). -.It [:graph:] -Graphical characters (printing nonblank characters). -.It [:punct:] -Punctuation characters. -.It [:xdigit:] -Hexadecimal digits. -.El -If -.Sq \&- -appears as the first or last character of a character class, then -it matches itself. -All other characters in a character class match themselves. -.Pp -Patterns in -a character class -of the form -.Em [.col-elm.] -or -.Em [=col-elm=] -where -.Em col-elm -is a -.Em collating element -are interpreted according to -.Xr locale 5 -(not currently supported). -See -.Xr regex 3 -for an explanation of these constructs. -.Ss COMMANDS -All -.Nm -commands are single characters, though some require additional parameters. -If a command's parameters extend over several lines, then -each line except for the last must be terminated with a backslash -.Pq Ql \e . -.Pp -In general, at most one command is allowed per line. -However, most commands accept a print suffix, which is any of -.Ic p -(print), -.Ic l -(list), -or -.Ic n -(enumerate), to print the last line affected by the command. -.Pp -An interrupt (typically ^C) has the effect of aborting the current command -and returning the editor to command mode. -.Pp -.Nm -recognizes the following commands. -The commands are shown together with -the default address or address range supplied if none is -specified (in parentheses), and other possible arguments on the right. -.Bl -tag -width Dxxs -.It (.) Ns Ic a -Appends text to the buffer after the addressed line. -Text is entered in input mode. -The current address is set to last line entered. -.It (.,.) Ns Ic c -Changes lines in the buffer. -The addressed lines are deleted from the buffer, -and text is appended in their place. -Text is entered in input mode. -The current address is set to last line entered. -.It (.,.) Ns Ic d -Deletes the addressed lines from the buffer. -If there is a line after the deleted range, then the current address is set -to this line. -Otherwise the current address is set to the line before the deleted range. -.It Ic e Ar file -Edits -.Ar file , -and sets the default filename. -If -.Ar file -is not specified, then the default filename is used. -Any lines in the buffer are deleted before the new file is read. -The current address is set to the last line read. -.It Ic e Ar !command -Edits the standard output of -.Ar command , -(see -.Ic \&! Ar command -below). -The default filename is unchanged. -Any lines in the buffer are deleted before the output of -.Em command -is read. -The current address is set to the last line read. -.It Ic E Ar file -Edits -.Ar file -unconditionally. -This is similar to the -.Ic e -command, except that unwritten changes are discarded without warning. -The current address is set to the last line read. -.It Ic f Ar file -Sets the default filename to -.Ar file . -If -.Ar file -is not specified, then the default unescaped filename is printed. -.It (1,$) Ns Ic g Ns Ar /re/command-list -Applies -.Ar command-list -to each of the addressed lines matching a regular expression -.Ar re . -The current address is set to the line currently matched before -.Ar command-list -is executed. -At the end of the -.Ic g -command, the current address is set to the last line affected by -.Ar command-list . -.Pp -Each command in -.Ar command-list -must be on a separate line, -and every line except for the last must be terminated by a backslash -.Pq Sq \e . -Any commands are allowed, except for -.Ic g , -.Ic G , -.Ic v , -and -.Ic V . -A newline alone in -.Ar command-list -is equivalent to a -.Ic p -command. -.It (1,$) Ns Ic G Ns Ar /re/ -Interactively edits the addressed lines matching a regular expression -.Ar re . -For each matching line, the line is printed, the current address is set, -and the user is prompted to enter a -.Ar command-list . -At the end of the -.Ic G -command, the current address is set to the last line affected by (the last) -.Ar command-list . -.Pp -The format of -.Ar command-list -is the same as that of the -.Ic g -command. -A newline alone acts as a null command list. -A single -.Sq \*[Am] -repeats the last non-null command list. -.It Ic H -Toggles the printing of error explanations. -By default, explanations are not printed. -It is recommended that -.Nm -scripts begin with this command to aid in debugging. -.It Ic h -Prints an explanation of the last error. -.It (.) Ns Ic i -Inserts text in the buffer before the current line. -Text is entered in input mode. -The current address is set to the last line entered. -.It (.,.+1) Ns Ic j -Joins the addressed lines. -The addressed lines are deleted from the buffer and replaced by a single -line containing their joined text. -The current address is set to the resultant line. -.It (.) Ns Ic k Ns Ar lc -Marks a line with a lower case letter -.Ar lc . -The line can then be addressed as -.Ar \&'lc -(i.e., a single quote followed by -.Ar lc ) -in subsequent commands. -The mark is not cleared until the line is deleted or otherwise modified. -.It (.,.) Ns Ic l -Prints the addressed lines unambiguously. -If a single line fills more than one screen (as might be the case -when viewing a binary file, for instance), a -.Dq --More-- -prompt is printed on the last line. -.Nm -waits until the RETURN key is pressed before displaying the next screen. -The current address is set to the last line printed. -.It (.,.) Ns Ic m Ns No (.) -Moves lines in the buffer. -The addressed lines are moved to after the -right-hand destination address, which may be the address -.Em 0 -(zero). -The current address is set to the last line moved. -.It (.,.) Ns Ic n -Prints the addressed lines along with their line numbers. -The current address is set to the last line printed. -.It (.,.) Ns Ic p -Prints the addressed lines. -The current address is set to the last line printed. -.It Ic P -Toggles the command prompt on and off. -Unless a prompt was specified with the command-line option -.Fl p Ar string , -the command prompt is by default turned off. -.It Ic q -Quits -.Nm . -.It Ic Q -Quits -.Nm -unconditionally. -This is similar to the -.Ic q -command, except that unwritten changes are discarded without warning. -.It ($) Ns Ic r Ar file -Reads -.Ar file -to after the addressed line. -If -.Ar file -is not specified, then the default filename is used. -If there was no default filename prior to the command, -then the default filename is set to -.Ar file . -Otherwise, the default filename is unchanged. -The current address is set to the last line read. -.It ($) Ns Ic r Ar !command -Reads to after the addressed line the standard output of -.Ar command , -(see the -.Ic \&! -command below). -The default filename is unchanged. -The current address is set to the last line read. -.Sm off -.It (.,.) Ic s Ar /re/replacement/ , \ (.,.) \ -Ic s Ar /re/replacement/ Em g , Ar \ (.,.) \ -Ic s Ar /re/replacement/ Em n -.Sm on -Replaces text in the addressed lines matching a regular expression -.Ar re -with -.Ar replacement . -By default, only the first match in each line is replaced. -If the -.Em g -(global) suffix is given, then every match to be replaced. -The -.Em n -suffix, where -.Em n -is a positive number, causes only the -.Em n Ns No th -match to be replaced. -It is an error if no substitutions are performed on any of the addressed -lines. -The current address is set the last line affected. -.Pp -.Ar re -and -.Ar replacement -may be delimited by any character other than space and newline -(see the -.Ic s -command below). -If one or two of the last delimiters is omitted, then the last line -affected is printed as though the print suffix -.Em p -were specified. -.Pp -An unescaped -.Ql \*[Am] -in -.Ar replacement -is replaced by the currently matched text. -The character sequence -.Em \em , -where -.Em m -is a number in the range [1,9], is replaced by the -.Em m Ns No th -backreference expression of the matched text. -If -.Ar replacement -consists of a single -.Ql % , -then -.Ar replacement -from the last substitution is used. -Newlines may be embedded in -.Ar replacement -if they are escaped with a backslash -.Pq Ql \e . -.It (.,.) Ns Ic s -Repeats the last substitution. -This form of the -.Ic s -command accepts a count suffix -.Em n , -or any combination of the characters -.Em r , -.Em g , -and -.Em p . -If a count suffix -.Em n -is given, then only the -.Em n Ns No th -match is replaced. -The -.Em r -suffix causes -the regular expression of the last search to be used instead of -that of the last substitution. -The -.Em g -suffix toggles the global suffix of the last substitution. -The -.Em p -suffix toggles the print suffix of the last substitution. -The current address is set to the last line affected. -.It (.,.) Ns Ic t Ns No (.) -Copies (i.e., transfers) the addressed lines to after the right-hand -destination address, which may be the address -.Em 0 -(zero). -The current address is set to the last line copied. -.It Ic u -Undoes the last command and restores the current address -to what it was before the command. -The global commands -.Ic g , -.Ic G , -.Ic v , -and -.Ic V -are treated as a single command by undo. -.Ic u -is its own inverse. -.It (1,$) Ns Ic v Ns Ar /re/command-list -Applies -.Ar command-list -to each of the addressed lines not matching a regular expression -.Ar re . -This is similar to the -.Ic g -command. -.It (1,$) Ns Ic V Ns Ar /re/ -Interactively edits the addressed lines not matching a regular expression -.Ar re . -This is similar to the -.Ic G -command. -.It (1,$) Ns Ic w Ar file -Writes the addressed lines to -.Ar file . -Any previous contents of -.Ar file -are lost without warning. -If there is no default filename, then the default filename is set to -.Ar file , -otherwise it is unchanged. -If no filename is specified, then the default filename is used. -The current address is unchanged. -.It (1,$) Ns Ic wq Ar file -Writes the addressed lines to -.Ar file , -and then executes a -.Ic q -command. -.It (1,$) Ns Ic w Ar !command -Writes the addressed lines to the standard input of -.Ar command , -(see the -.Ic \&! -command below). -The default filename and current address are unchanged. -.It (1,$) Ns Ic W Ar file -Appends the addressed lines to the end of -.Ar file . -This is similar to the -.Ic w -command, except that the previous contents of file are not clobbered. -The current address is unchanged. -.It Ic x -Prompts for an encryption key which is used in subsequent reads and writes. -If a newline alone is entered as the key, then encryption is turned off. -Otherwise, echoing is disabled while a key is read. -Encryption/decryption is done using the -.Xr bdes 1 -algorithm. -.It (.+1) Ns Ic z Ns Ar n -Scrolls -.Ar n -lines at a time starting at addressed line. -If -.Ar n -is not specified, then the current window size is used. -The current address is set to the last line printed. -.It ($) Ns Ic = -Prints the line number of the addressed line. -.It (.+1) Ns Ic newline -Prints the addressed line, and sets the current address to that line. -.It Ic \&! Ns Ar command -Executes -.Ar command -via -.Xr sh 1 . -If the first character of -.Ar command -is -.Ic \&! , -then it is replaced by text of the previous -.Ic !command . -.Nm -does not process -.Ar command -for -.Sq \e -(backslash) escapes. -However, an unescaped -.Sq % -is replaced by the default filename. -When the shell returns from execution, a -.Sq \&! -is printed to the standard output. -The current line is unchanged. -.El -.Sh LIMITATIONS -.Nm -processes -.Em file -arguments for backslash escapes, i.e., in a filename, -any characters preceded by a backslash -.Pq Ql \e -are interpreted literally. -.Pp -If a text (non-binary) file is not terminated by a newline character, -then -.Nm -appends one on reading/writing it. -In the case of a binary file, -.Nm -does not append a newline on reading/writing. -.Sh ENVIRONMENT -.Bl -tag -width iTMPDIR -.It Ev TMPDIR -The location used to store temporary files. -.El -.Sh FILES -.Bl -tag -width /tmp/ed.* -compact -.It Pa /tmp/ed.* -buffer file -.It Pa ed.hup -where -.Nm -attempts to write the buffer if the terminal hangs up -.El -.Sh DIAGNOSTICS -When an error occurs, -.Nm -prints a -.Dq \&? -and either returns to command mode or exits if its input is from a script. -An explanation of the last error can be printed with the -.Ic h -(help) command. -.Pp -Since the -.Ic g -(global) command masks any errors from failed searches and substitutions, -it can be used to perform conditional operations in scripts; e.g., -.Bd -literal -offset indent -g/old/s//new/ -.Ed -.Pp -replaces any occurrences of -.Em old -with -.Em new . -.Pp -If the -.Ic u -(undo) command occurs in a global command list, then -the command list is executed only once. -.Pp -If diagnostics are not disabled, attempting to quit -.Nm -or edit another file before writing a modified buffer results in an error. -If the command is entered a second time, it succeeds, -but any changes to the buffer are lost. -.Sh SEE ALSO -.Xr bdes 1 , -.Xr sed 1 , -.Xr sh 1 , -.Xr vi 1 , -.Xr patch 1 , -.Xr regex 3 -.Pp -USD:09-10 -.Rs -.%A B. W. Kernighan -.%A P. J. Plauger -.%B Software Tools in Pascal -.%I Addison-Wesley -.%D 1981 -.Re -.Sh HISTORY -An -.Nm -command appeared in -.At v1 . diff --git a/bin/ed/ed.h b/bin/ed/ed.h deleted file mode 100644 index e8efd0b31..000000000 --- a/bin/ed/ed.h +++ /dev/null @@ -1,294 +0,0 @@ -/* $NetBSD: ed.h,v 1.37 2014/03/25 17:23:37 joerg Exp $ */ - -/* ed.h: type and constant definitions for the ed editor. */ -/* - * Copyright (c) 1993 Andrew Moore - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ed.h,v 1.5 1994/02/01 00:34:39 alm Exp - */ -#include -#if defined(BSD) && BSD >= 199103 || defined(__386BSD__) -# include /* for MAXPATHLEN */ -#endif -#include -#if defined(sun) || defined(__NetBSD__) || defined(__APPLE__) || \ - defined(__minix) -# include -#endif -#include -#include -#include -#include -#include -#include - -#define ERR (-2) -#define EMOD (-3) -#define FATAL (-4) - -#ifndef MAXPATHLEN -# define MAXPATHLEN 255 /* _POSIX_PATH_MAX */ -#endif - -#define MINBUFSZ 512 /* minimum buffer size - must be > 0 */ -#define SE_MAX 30 /* max subexpressions in a regular expression */ -#ifdef INT_MAX -# define LINECHARS INT_MAX /* max chars per line */ -#else -# define LINECHARS MAXINT /* max chars per line */ -#endif - -/* gflags */ -#define GLB 001 /* global command */ -#define GPR 002 /* print after command */ -#define GLS 004 /* list after command */ -#define GNP 010 /* enumerate after command */ -#define GSG 020 /* global substitute */ - -typedef regex_t pattern_t; - -/* Line node */ -typedef struct line { - struct line *q_forw; - struct line *q_back; - off_t seek; /* address of line in scratch buffer */ - int len; /* length of line */ -} line_t; - - -typedef struct undo { - -/* type of undo nodes */ -#define UADD 0 -#define UDEL 1 -#define UMOV 2 -#define VMOV 3 - - int type; /* command type */ - line_t *h; /* head of list */ - line_t *t; /* tail of list */ -} undo_t; - -#ifndef max -# define max(a,b) ((a) > (b) ? (a) : (b)) -#endif -#ifndef min -# define min(a,b) ((a) < (b) ? (a) : (b)) -#endif - -#define INC_MOD(l, k) ((l) + 1 > (k) ? 0 : (l) + 1) -#define DEC_MOD(l, k) ((l) - 1 < 0 ? (k) : (l) - 1) - -/* SPL1: disable some interrupts (requires reliable signals) */ -#define SPL1() mutex++ - -/* SPL0: enable all interrupts; check sigflags (requires reliable signals) */ -#define SPL0() \ -if (--mutex == 0) { \ - if (sigflags & (1 << (SIGHUP - 1))) handle_hup(SIGHUP); \ - if (sigflags & (1 << (SIGINT - 1))) handle_int(SIGINT); \ -} - -/* STRTOL: convert a string to long */ -#define STRTOL(i, p) { \ - errno = 0 ; \ - if (((i = strtol(p, &p, 10)) == LONG_MIN || i == LONG_MAX) && \ - errno == ERANGE) { \ - seterrmsg("number out of range"); \ - i = 0; \ - return ERR; \ - } \ -} - -#if defined(sun) || defined(NO_REALLOC_NULL) -/* REALLOC: assure at least a minimum size for buffer b */ -#define REALLOC(b,n,i,err) \ -if ((i) > (n)) { \ - int ti = (n); \ - char *ts; \ - SPL1(); \ - if ((b) != NULL) { \ - if ((ts = (char *) realloc((b), ti += max((i), MINBUFSZ))) == NULL) { \ - fprintf(stderr, "%s\n", strerror(errno)); \ - seterrmsg("out of memory"); \ - SPL0(); \ - return err; \ - } \ - } else { \ - if ((ts = (char *) malloc(ti += max((i), MINBUFSZ))) == NULL) { \ - fprintf(stderr, "%s\n", strerror(errno)); \ - seterrmsg("out of memory"); \ - SPL0(); \ - return err; \ - } \ - } \ - (n) = ti; \ - (b) = ts; \ - SPL0(); \ -} -#else /* NO_REALLOC_NULL */ -/* REALLOC: assure at least a minimum size for buffer b */ -#define REALLOC(b,n,i,err) \ -if ((i) > (n)) { \ - int ti = (n); \ - char *ts; \ - SPL1(); \ - if ((ts = (char *) realloc((b), ti += max((i), MINBUFSZ))) == NULL) { \ - fprintf(stderr, "%s\n", strerror(errno)); \ - seterrmsg("out of memory"); \ - SPL0(); \ - return err; \ - } \ - (n) = ti; \ - (b) = ts; \ - SPL0(); \ -} -#endif /* NO_REALLOC_NULL */ - -/* REQUE: link pred before succ */ -#define REQUE(pred, succ) (pred)->q_forw = (succ), (succ)->q_back = (pred) - -/* INSQUE: insert elem in circular queue after pred */ -#define INSQUE(elem, pred) \ -{ \ - REQUE((elem), (pred)->q_forw); \ - REQUE((pred), elem); \ -} - -/* remque: remove_lines elem from circular queue */ -#define REMQUE(elem) REQUE((elem)->q_back, (elem)->q_forw); - -/* NUL_TO_NEWLINE: overwrite ASCII NULs with newlines */ -#define NUL_TO_NEWLINE(s, l) translit_text(s, l, '\0', '\n') - -/* NEWLINE_TO_NUL: overwrite newlines with ASCII NULs */ -#define NEWLINE_TO_NUL(s, l) translit_text(s, l, '\n', '\0') - -#if defined(sun) && !defined(__SVR4) -# define strerror(n) sys_errlist[n] -#endif - -/* Local Function Declarations */ -void add_line_node(line_t *); -int append_lines(long); -int apply_subst_template(char *, regmatch_t *, int, int); -int build_active_list(int); -int check_addr_range(long, long); -void clear_active_list(void); -void clear_undo_stack(void); -int close_sbuf(void); -int copy_lines(long); -int delete_lines(long, long); -int display_lines(long, long, int); -line_t *dup_line_node(line_t *); -int exec_command(void); -long exec_global(int, int); -int extract_addr_range(void); -char *extract_pattern(int); -int extract_subst_tail(int *, long *); -char *extract_subst_template(void); -int filter_lines(long, long, char *); -int flush_des_file(FILE *); -line_t *get_addressed_line_node(long); -pattern_t *get_compiled_pattern(void); -int get_des_char(FILE *); -char *get_extended_line(int *, int); -char *get_filename(void); -int get_keyword(void); -long get_line_node_addr(line_t *); -long get_matching_node_addr(pattern_t *, int); -long get_marked_node_addr(int); -char *get_sbuf_line(line_t *); -int get_shell_command(void); -int get_stream_line(FILE *); -int get_tty_line(void); -__dead void handle_hup(int); -__dead void handle_int(int); -void handle_winch(int); -int has_trailing_escape(char *, char *); -void init_buffers(void); -void init_des_cipher(void); -int is_legal_filename(char *); -int join_lines(long, long); -int mark_line_node(line_t *, int); -int move_lines(long); -line_t *next_active_node(void); -long next_addr(void); -int open_sbuf(void); -char *parse_char_class(char *); -int pop_undo_stack(void); -undo_t *push_undo_stack(int, long, long); -int put_des_char(int, FILE *); -char *put_sbuf_line(char *); -int put_stream_line(FILE *, char *, int); -int put_tty_line(char *, int, long, int); -__dead void quit(int); -long read_file(char *, long); -long read_stream(FILE *, long); -int search_and_replace(pattern_t *, int, int); -int set_active_node(line_t *); -void signal_hup(int); -void signal_int(int); -char *strip_escapes(const char *); -int substitute_matching_text(pattern_t *, line_t *, int, int); -char *translit_text(char *, int, int, int); -void unmark_line_node(line_t *); -void unset_active_nodes(line_t *, line_t *); -long write_file(const char *, const char *, long, long); -long write_stream(FILE *, long, long); -void seterrmsg(const char *, ...) __printflike(1, 2); - -/* global buffers */ -extern char stdinbuf[]; -extern char *ibuf; -extern char *ibufp; -extern int ibufsz; - -/* global flags */ -extern int isbinary; -extern int isglobal; -extern int modified; -extern int mutex; -extern int sigflags; - -/* global vars */ -extern long addr_last; -extern long current_addr; -extern long first_addr; -extern int lineno; -extern long second_addr; -extern long rows; -extern int cols; -extern int scripted; -extern int ere; -extern int des; -extern int newline_added; /* io.c */ -extern int patlock; -extern char errmsg[]; /* re.c */ -extern long u_current_addr; /* undo.c */ -extern long u_addr_last; /* undo.c */ -#if defined(sun) && !defined(__SVR4) -extern char *sys_errlist[]; -#endif diff --git a/bin/ed/glbl.c b/bin/ed/glbl.c deleted file mode 100644 index 2a3a6e3c9..000000000 --- a/bin/ed/glbl.c +++ /dev/null @@ -1,227 +0,0 @@ -/* $NetBSD: glbl.c,v 1.9 2015/08/28 11:29:48 joerg Exp $ */ - -/* glob.c: This file contains the global command routines for the ed line - editor */ -/*- - * Copyright (c) 1993 Andrew Moore, Talke Studio. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char *rcsid = "@(#)glob.c,v 1.1 1994/02/01 00:34:40 alm Exp"; -#else -__RCSID("$NetBSD: glbl.c,v 1.9 2015/08/28 11:29:48 joerg Exp $"); -#endif -#endif /* not lint */ - -#include -#include - -#include "ed.h" - - -/* build_active_list: add line matching a pattern to the global-active list */ -int -build_active_list(int isgcmd) -{ - pattern_t *pat; - line_t *lp; - long n; - char *s; - char delimiter; - - if ((delimiter = *ibufp) == ' ' || delimiter == '\n') { - seterrmsg("invalid pattern delimiter"); - return ERR; - } else if ((pat = get_compiled_pattern()) == NULL) - return ERR; - else if (*ibufp == delimiter) - ibufp++; - clear_active_list(); - lp = get_addressed_line_node(first_addr); - for (n = first_addr; n <= second_addr; n++, lp = lp->q_forw) { - if ((s = get_sbuf_line(lp)) == NULL) - return ERR; - if (isbinary) - NUL_TO_NEWLINE(s, lp->len); - if ((!regexec(pat, s, 0, NULL, 0)) == isgcmd && - set_active_node(lp) < 0) - return ERR; - } - return 0; -} - - -/* exec_global: apply command list in the command buffer to the active - lines in a range; return command status */ -long -exec_global(int interact, int gflag) -{ - static char *ocmd = NULL; - static int ocmdsz = 0; - - line_t *lp = NULL; - int status; - int n; - char *cmd = NULL; -#ifdef BACKWARDS - char cmdp[] = "p\n"; - - if (!interact) { - if (!strcmp(ibufp, "\n")) - cmd = cmdp; /* null cmd-list == `p' */ - else if ((cmd = get_extended_line(&n, 0)) == NULL) - return ERR; - } -#else - if (!interact && (cmd = get_extended_line(&n, 0)) == NULL) - return ERR; -#endif - clear_undo_stack(); - while ((lp = next_active_node()) != NULL) { - if ((current_addr = get_line_node_addr(lp)) < 0) - return ERR; - if (interact) { - /* print current_addr; get a command in global syntax */ - if (display_lines(current_addr, current_addr, gflag) < 0) - return ERR; - while ((n = get_tty_line()) > 0 && - ibuf[n - 1] != '\n') - clearerr(stdin); - if (n < 0) - return ERR; - else if (n == 0) { - seterrmsg("unexpected end-of-file"); - return ERR; - } else if (n == 1 && !strcmp(ibuf, "\n")) - continue; - else if (n == 2 && !strcmp(ibuf, "&\n")) { - if (cmd == NULL) { - seterrmsg("no previous command"); - return ERR; - } else cmd = ocmd; - } else if ((cmd = get_extended_line(&n, 0)) == NULL) - return ERR; - else { - REALLOC(ocmd, ocmdsz, n + 1, ERR); - memcpy(ocmd, cmd, n + 1); - cmd = ocmd; - } - - } - ibufp = cmd; - for (; *ibufp;) - if ((status = extract_addr_range()) < 0 || - (status = exec_command()) < 0 || - (status > 0 && (status = display_lines( - current_addr, current_addr, status)) < 0)) - return status; - } - return 0; -} - - -line_t **active_list; /* list of lines active in a global command */ -long active_last; /* index of last active line in active_list */ -long active_size; /* size of active_list */ -long active_ptr; /* active_list index (non-decreasing) */ -long active_ndx; /* active_list index (modulo active_last) */ - -/* set_active_node: add a line node to the global-active list */ -int -set_active_node(line_t *lp) -{ - if (active_last + 1 > active_size) { - int ti = active_size; - line_t **ts; - SPL1(); -#if defined(sun) || defined(NO_REALLOC_NULL) - if (active_list != NULL) { -#endif - if ((ts = (line_t **) realloc(active_list, - (ti += MINBUFSZ) * sizeof(line_t **))) == NULL) { - fprintf(stderr, "%s\n", strerror(errno)); - seterrmsg("out of memory"); - SPL0(); - return ERR; - } -#if defined(sun) || defined(NO_REALLOC_NULL) - } else { - if ((ts = (line_t **) malloc((ti += MINBUFSZ) * - sizeof(line_t **))) == NULL) { - fprintf(stderr, "%s\n", strerror(errno)); - seterrmsg("out of memory"); - SPL0(); - return ERR; - } - } -#endif - active_size = ti; - active_list = ts; - SPL0(); - } - active_list[active_last++] = lp; - return 0; -} - - -/* unset_active_nodes: remove a range of lines from the global-active list */ -void -unset_active_nodes(line_t *np, line_t *mp) -{ - line_t *lp; - long i; - - for (lp = np; lp != mp; lp = lp->q_forw) - for (i = 0; i < active_last; i++) - if (active_list[active_ndx] == lp) { - active_list[active_ndx] = NULL; - active_ndx = INC_MOD(active_ndx, active_last - 1); - break; - } else active_ndx = INC_MOD(active_ndx, active_last - 1); -} - - -/* next_active_node: return the next global-active line node */ -line_t * -next_active_node(void) -{ - while (active_ptr < active_last && active_list[active_ptr] == NULL) - active_ptr++; - return (active_ptr < active_last) ? active_list[active_ptr++] : NULL; -} - - -/* clear_active_list: clear the global-active list */ -void -clear_active_list(void) -{ - SPL1(); - active_size = active_last = active_ptr = active_ndx = 0; - free(active_list); - active_list = NULL; - SPL0(); -} diff --git a/bin/ed/io.c b/bin/ed/io.c deleted file mode 100644 index 7ef23b463..000000000 --- a/bin/ed/io.c +++ /dev/null @@ -1,358 +0,0 @@ -/* $NetBSD: io.c,v 1.10 2014/03/23 05:06:42 dholland Exp $ */ - -/* io.c: This file contains the i/o routines for the ed line editor */ -/*- - * Copyright (c) 1993 Andrew Moore, Talke Studio. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char *rcsid = "@(#)io.c,v 1.1 1994/02/01 00:34:41 alm Exp"; -#else -__RCSID("$NetBSD: io.c,v 1.10 2014/03/23 05:06:42 dholland Exp $"); -#endif -#endif /* not lint */ - -#include "ed.h" - - -/* read_file: read a named file/pipe into the buffer; return line count */ -long -read_file(char *fn, long n) -{ - FILE *fp; - long size; - - - fp = (*fn == '!') ? popen(fn + 1, "r") : fopen(strip_escapes(fn), "r"); - if (fp == NULL) { - fprintf(stderr, "%s: %s\n", fn, strerror(errno)); - seterrmsg("cannot open input file"); - return ERR; - } else if ((size = read_stream(fp, n)) < 0) - return ERR; - else if (((*fn == '!') ? pclose(fp) : fclose(fp)) < 0) { - fprintf(stderr, "%s: %s\n", fn, strerror(errno)); - seterrmsg("cannot close input file"); - return ERR; - } - if (!scripted) - fprintf(stderr, "%lu\n", size); - return current_addr - n; -} - - -char *sbuf; /* file i/o buffer */ -int sbufsz; /* file i/o buffer size */ -int newline_added; /* if set, newline appended to input file */ - -/* read_stream: read a stream into the editor buffer; return status */ -long -read_stream(FILE *fp, long n) -{ - line_t *lp = get_addressed_line_node(n); - undo_t *up = NULL; - unsigned long size = 0; - int o_newline_added = newline_added; - int o_isbinary = isbinary; - int appended = (n == addr_last); - int len; - - isbinary = newline_added = 0; - if (des) - init_des_cipher(); - for (current_addr = n; (len = get_stream_line(fp)) > 0; size += len) { - SPL1(); - if (put_sbuf_line(sbuf) == NULL) { - SPL0(); - return ERR; - } - lp = lp->q_forw; - if (up) - up->t = lp; - else if ((up = push_undo_stack(UADD, current_addr, - current_addr)) == NULL) { - SPL0(); - return ERR; - } - SPL0(); - } - if (len < 0) - return ERR; - if (appended && size && o_isbinary && o_newline_added) - fputs("newline inserted\n", stderr); - else if (newline_added && (!appended || (!isbinary && !o_isbinary))) - fputs("newline appended\n", stderr); - if (isbinary && newline_added && !appended) - size += 1; - if (!size) - newline_added = 1; - newline_added = appended ? newline_added : o_newline_added; - isbinary = isbinary | o_isbinary; - if (des) - size += 8 - size % 8; /* adjust DES size */ - return size; -} - - -/* get_stream_line: read a line of text from a stream; return line length */ -int -get_stream_line(FILE *fp) -{ - int c; - int i = 0; - - while (((c = des ? get_des_char(fp) : getc(fp)) != EOF || (!feof(fp) && - !ferror(fp))) && c != '\n') { - REALLOC(sbuf, sbufsz, i + 1, ERR); - if (!(sbuf[i++] = c)) - isbinary = 1; - } - REALLOC(sbuf, sbufsz, i + 2, ERR); - if (c == '\n') - sbuf[i++] = c; - else if (ferror(fp)) { - fprintf(stderr, "%s\n", strerror(errno)); - seterrmsg("cannot read input file"); - return ERR; - } else if (i) { - sbuf[i++] = '\n'; - newline_added = 1; - } - sbuf[i] = '\0'; - return (isbinary && newline_added && i) ? --i : i; -} - - -/* write_file: write a range of lines to a named file/pipe; return line count */ -long -write_file(const char *fn, const char *mode, long n, long m) -{ - FILE *fp; - long size; - - fp = (*fn == '!') ? popen(fn+1, "w") : fopen(strip_escapes(fn), mode); - if (fp == NULL) { - fprintf(stderr, "%s: %s\n", fn, strerror(errno)); - seterrmsg("cannot open output file"); - return ERR; - } else if ((size = write_stream(fp, n, m)) < 0) - return ERR; - else if (((*fn == '!') ? pclose(fp) : fclose(fp)) < 0) { - fprintf(stderr, "%s: %s\n", fn, strerror(errno)); - seterrmsg("cannot close output file"); - return ERR; - } - if (!scripted) - fprintf(stderr, "%lu\n", size); - return n ? m - n + 1 : 0; -} - - -/* write_stream: write a range of lines to a stream; return status */ -long -write_stream(FILE *fp, long n, long m) -{ - line_t *lp = get_addressed_line_node(n); - unsigned long size = 0; - char *s; - int len; - - if (des) - init_des_cipher(); - for (; n && n <= m; n++, lp = lp->q_forw) { - if ((s = get_sbuf_line(lp)) == NULL) - return ERR; - len = lp->len; - if (n != addr_last || !isbinary || !newline_added) - s[len++] = '\n'; - if (put_stream_line(fp, s, len) < 0) - return ERR; - size += len; - } - if (des) { - flush_des_file(fp); /* flush buffer */ - size += 8 - size % 8; /* adjust DES size */ - } - return size; -} - - -/* put_stream_line: write a line of text to a stream; return status */ -int -put_stream_line(FILE *fp, char *s, int len) -{ - while (len--) - if ((des ? put_des_char(*s++, fp) : fputc(*s++, fp)) < 0) { - fprintf(stderr, "%s\n", strerror(errno)); - seterrmsg("cannot write file"); - return ERR; - } - return 0; -} - -/* get_extended_line: get a an extended line from stdin */ -char * -get_extended_line(int *sizep, int nonl) -{ - static char *cvbuf = NULL; /* buffer */ - static int cvbufsz = 0; /* buffer size */ - - int l, n; - char *t = ibufp; - - while (*t++ != '\n') - ; - if ((l = t - ibufp) < 2 || !has_trailing_escape(ibufp, ibufp + l - 1)) { - *sizep = l; - return ibufp; - } - *sizep = -1; - REALLOC(cvbuf, cvbufsz, l, NULL); - memcpy(cvbuf, ibufp, l); - *(cvbuf + --l - 1) = '\n'; /* strip trailing esc */ - if (nonl) l--; /* strip newline */ - for (;;) { - if ((n = get_tty_line()) < 0) - return NULL; - else if (n == 0 || ibuf[n - 1] != '\n') { - seterrmsg("unexpected end-of-file"); - return NULL; - } - REALLOC(cvbuf, cvbufsz, l + n, NULL); - memcpy(cvbuf + l, ibuf, n); - l += n; - if (n < 2 || !has_trailing_escape(cvbuf, cvbuf + l - 1)) - break; - *(cvbuf + --l - 1) = '\n'; /* strip trailing esc */ - if (nonl) l--; /* strip newline */ - } - REALLOC(cvbuf, cvbufsz, l + 1, NULL); - cvbuf[l] = '\0'; - *sizep = l; - return cvbuf; -} - - -/* get_tty_line: read a line of text from stdin; return line length */ -int -get_tty_line(void) -{ - int oi = 0; - int i = 0; - int c; - - for (;;) - switch (c = getchar()) { - default: - oi = 0; - REALLOC(ibuf, ibufsz, i + 2, ERR); - if (!(ibuf[i++] = c)) isbinary = 1; - if (c != '\n') - continue; - lineno++; - ibuf[i] = '\0'; - ibufp = ibuf; - return i; - case EOF: - if (ferror(stdin)) { - fprintf(stderr, "stdin: %s\n", strerror(errno)); - seterrmsg("cannot read stdin"); - clearerr(stdin); - ibufp = NULL; - return ERR; - } else { - clearerr(stdin); - if (i != oi) { - oi = i; - continue; - } else if (i) - ibuf[i] = '\0'; - ibufp = ibuf; - return i; - } - } -} - - - -#define ESCAPES "\a\b\f\n\r\t\v\\" -#define ESCCHARS "abfnrtv\\" - -/* put_tty_line: print text to stdout */ -int -put_tty_line(char *s, int l, long n, int gflag) -{ - int col = 0; - char *cp; -#ifndef BACKWARDS - int lc = 0; -#endif - - if (gflag & GNP) { - printf("%ld\t", n); - col = 8; - } - for (; l--; s++) { - if ((gflag & GLS) && ++col > cols) { - fputs("\\\n", stdout); - col = 1; -#ifndef BACKWARDS - if (!scripted && !isglobal && ++lc > rows) { - lc = 0; - fputs("Press to continue... ", stdout); - fflush(stdout); - if (get_tty_line() < 0) - return ERR; - } -#endif - } - if (gflag & GLS) { - if (31 < *s && *s < 127 && *s != '\\') - putchar(*s); - else { - putchar('\\'); - col++; - if (*s && (cp = strchr(ESCAPES, *s)) != NULL) - putchar(ESCCHARS[cp - ESCAPES]); - else { - putchar((((unsigned char) *s & 0300) >> 6) + '0'); - putchar((((unsigned char) *s & 070) >> 3) + '0'); - putchar(((unsigned char) *s & 07) + '0'); - col += 2; - } - } - - } else - putchar(*s); - } -#ifndef BACKWARDS - if (gflag & GLS) - putchar('$'); -#endif - putchar('\n'); - return 0; -} diff --git a/bin/ed/main.c b/bin/ed/main.c deleted file mode 100644 index aa6801e2b..000000000 --- a/bin/ed/main.c +++ /dev/null @@ -1,1433 +0,0 @@ -/* $NetBSD: main.c,v 1.28.8.2 2018/06/22 10:08:22 martin Exp $ */ - -/* main.c: This file contains the main control and user-interface routines - for the ed line editor. */ -/*- - * Copyright (c) 1993 Andrew Moore, Talke Studio. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT( -"@(#) Copyright (c) 1993 Andrew Moore, Talke Studio.\ - All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char *rcsid = "@(#)main.c,v 1.1 1994/02/01 00:34:42 alm Exp"; -#else -__RCSID("$NetBSD: main.c,v 1.28.8.2 2018/06/22 10:08:22 martin Exp $"); -#endif -#endif /* not lint */ - -/* - * CREDITS - * - * This program is based on the editor algorithm described in - * Brian W. Kernighan and P. J. Plauger's book "Software Tools - * in Pascal," Addison-Wesley, 1981. - * - * The buffering algorithm is attributed to Rodney Ruddock of - * the University of Guelph, Guelph, Ontario. - * - * The cbc.c encryption code is adapted from - * the bdes program by Matt Bishop of Dartmouth College, - * Hanover, NH. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "ed.h" - - -#ifdef _POSIX_SOURCE -sigjmp_buf env; -#else -jmp_buf env; -#endif - -/* static buffers */ -char stdinbuf[1]; /* stdin buffer */ -char *shcmd; /* shell command buffer */ -int shcmdsz; /* shell command buffer size */ -int shcmdi; /* shell command buffer index */ -char *ibuf; /* ed command-line buffer */ -int ibufsz; /* ed command-line buffer size */ -char *ibufp; /* pointer to ed command-line buffer */ - -/* global flags */ -int des = 0; /* if set, use crypt(3) for i/o */ -int garrulous = 0; /* if set, print all error messages */ -int isbinary; /* if set, buffer contains ASCII NULs */ -int isglobal; /* if set, doing a global command */ -int modified; /* if set, buffer modified since last write */ -int mutex = 0; /* if set, signals set "sigflags" */ -int red = 0; /* if set, restrict shell/directory access */ -int ere = 0; /* if set, use extended regexes */ -int scripted = 0; /* if set, suppress diagnostics */ -int secure = 0; /* is set, ! is not allowed */ -int sigflags = 0; /* if set, signals received while mutex set */ -int sigactive = 0; /* if set, signal handlers are enabled */ - -char old_filename[MAXPATHLEN + 1] = ""; /* default filename */ -long current_addr; /* current address in editor buffer */ -long addr_last; /* last address in editor buffer */ -int lineno; /* script line number */ -const char *prompt; /* command-line prompt */ -const char *dps = "*"; /* default command-line prompt */ - - -static const char usage[] = "Usage: %s [-] [-ESsx] [-p string] [name]\n"; - -/* ed: line editor */ -int -main(int ac, char *av[]) -{ - int c, n; - long status = 0; - volatile int argc = ac; - char ** volatile argv = av; - - red = (n = strlen(argv[0])) > 2 && argv[0][n - 3] == 'r'; -top: - while ((c = getopt(argc, argv, "p:sxES")) != -1) - switch(c) { - case 'p': /* set prompt */ - prompt = optarg; - break; - case 's': /* run script */ - scripted = 1; - break; - case 'x': /* use crypt */ -#ifdef DES - des = get_keyword(); -#else - fprintf(stderr, "crypt unavailable\n?\n"); -#endif - break; - - case 'E': - ere = REG_EXTENDED; - break; - case 'S': /* ! is not allowed */ - secure = 1; - break; - default: - fprintf(stderr, usage, getprogname()); - exit(1); - /* NOTREACHED */ - } - argv += optind; - argc -= optind; - if (argc && **argv == '-') { - scripted = 1; - if (argc > 1) { - optind = 1; - goto top; - } - argv++; - argc--; - } - /* assert: reliable signals! */ -#ifdef SIGWINCH - handle_winch(SIGWINCH); - if (isatty(0)) signal(SIGWINCH, handle_winch); -#endif - signal(SIGHUP, signal_hup); - signal(SIGQUIT, SIG_IGN); - signal(SIGINT, signal_int); -#ifdef _POSIX_SOURCE - if ((status = sigsetjmp(env, 1)) != 0) -#else - if ((status = setjmp(env)) != 0) -#endif - { - fputs("\n?\n", stderr); - seterrmsg("interrupt"); - } else { - init_buffers(); - sigactive = 1; /* enable signal handlers */ - if (argc && **argv && is_legal_filename(*argv)) { - if (read_file(*argv, 0) < 0 && !isatty(0)) - quit(2); - else if (**argv != '!') - strlcpy(old_filename, *argv, - sizeof(old_filename) - 2); - } else if (argc) { - fputs("?\n", stderr); - if (**argv == '\0') - seterrmsg("invalid filename"); - if (!isatty(0)) - quit(2); - } - } - for (;;) { - if (status < 0 && garrulous) - fprintf(stderr, "%s\n", errmsg); - if (prompt) { - printf("%s", prompt); - fflush(stdout); - } - if ((n = get_tty_line()) < 0) { - status = ERR; - continue; - } else if (n == 0) { - if (modified && !scripted) { - fputs("?\n", stderr); - seterrmsg("warning: file modified"); - if (!isatty(0)) { - if (garrulous) { - fprintf(stderr, - "script, line %d: %s\n", - lineno, errmsg); - } - quit(2); - } - clearerr(stdin); - modified = 0; - status = EMOD; - continue; - } else - quit(0); - } else if (ibuf[n - 1] != '\n') { - /* discard line */ - seterrmsg("unexpected end-of-file"); - clearerr(stdin); - status = ERR; - continue; - } - isglobal = 0; - if ((status = extract_addr_range()) >= 0 && - (status = exec_command()) >= 0) { - if (status == 0) - continue; - status = display_lines(current_addr, current_addr, - status); - if (status >= 0) - continue; - } - switch (status) { - case EOF: - quit(0); - case EMOD: - modified = 0; - fputs("?\n", stderr); /* give warning */ - seterrmsg("warning: file modified"); - if (!isatty(0)) { - if (garrulous) { - fprintf(stderr, - "script, line %d: %s\n", - lineno, errmsg); - } - quit(2); - } - break; - case FATAL: - if (garrulous) { - if (!isatty(0)) { - fprintf(stderr, - "script, line %d: %s\n", - lineno, errmsg); - } else { - fprintf(stderr, "%s\n", errmsg); - } - } - quit(3); - default: - fputs("?\n", stderr); - if (!isatty(0)) { - if (garrulous) { - fprintf(stderr, "script, line %d: %s\n", - lineno, errmsg); - } - quit(2); - } - break; - } - } - /* NOTREACHED */ -} - -long first_addr, second_addr, addr_cnt; - -/* extract_addr_range: get line addresses from the command buffer until an - illegal address is seen; return status */ -int -extract_addr_range(void) -{ - long addr; - - addr_cnt = 0; - first_addr = second_addr = current_addr; - while ((addr = next_addr()) >= 0) { - addr_cnt++; - first_addr = second_addr; - second_addr = addr; - if (*ibufp != ',' && *ibufp != ';') - break; - else if (*ibufp++ == ';') - current_addr = addr; - } - if ((addr_cnt = min(addr_cnt, 2)) == 1 || second_addr != addr) - first_addr = second_addr; - return (addr == ERR) ? ERR : 0; -} - - -#define SKIP_BLANKS() while (isspace((unsigned char)*ibufp) && *ibufp != '\n') \ - ibufp++ - -#define MUST_BE_FIRST() \ - if (!first) { seterrmsg("invalid address"); return ERR; } - -/* next_addr: return the next line address in the command buffer */ -long -next_addr(void) -{ - char *hd; - long addr = current_addr; - long n; - int first = 1; - int c; - - SKIP_BLANKS(); - for (hd = ibufp;; first = 0) - switch (c = *ibufp) { - case '+': - case '\t': - case ' ': - case '-': - case '^': - ibufp++; - SKIP_BLANKS(); - if (isdigit((unsigned char)*ibufp)) { - STRTOL(n, ibufp); - addr += (c == '-' || c == '^') ? -n : n; - } else if (!isspace((unsigned char)c)) - addr += (c == '-' || c == '^') ? -1 : 1; - break; - case '0': case '1': case '2': - case '3': case '4': case '5': - case '6': case '7': case '8': case '9': - MUST_BE_FIRST(); - STRTOL(addr, ibufp); - break; - case '.': - case '$': - MUST_BE_FIRST(); - ibufp++; - addr = (c == '.') ? current_addr : addr_last; - break; - case '/': - case '?': - MUST_BE_FIRST(); - if ((addr = get_matching_node_addr( - get_compiled_pattern(), c == '/')) < 0) - return ERR; - else if (c == *ibufp) - ibufp++; - break; - case '\'': - MUST_BE_FIRST(); - ibufp++; - if ((addr = get_marked_node_addr((unsigned char)*ibufp++)) < 0) - return ERR; - break; - case '%': - case ',': - case ';': - if (first) { - ibufp++; - addr_cnt++; - second_addr = (c == ';') ? current_addr : 1; - addr = addr_last; - break; - } - /* FALL THROUGH */ - default: - if (ibufp == hd) - return EOF; - else if (addr < 0 || addr_last < addr) { - seterrmsg("invalid address"); - return ERR; - } else - return addr; - } - /* NOTREACHED */ -} - - -#ifdef BACKWARDS -/* GET_THIRD_ADDR: get a legal address from the command buffer */ -#define GET_THIRD_ADDR(addr) \ -{ \ - long ol1, ol2; \ -\ - ol1 = first_addr, ol2 = second_addr; \ - if (extract_addr_range() < 0) \ - return ERR; \ - else if (addr_cnt == 0) { \ - seterrmsg("destination expected"); \ - return ERR; \ - } else if (second_addr < 0 || addr_last < second_addr) { \ - seterrmsg("invalid address"); \ - return ERR; \ - } \ - addr = second_addr; \ - first_addr = ol1, second_addr = ol2; \ -} -#else /* BACKWARDS */ -/* GET_THIRD_ADDR: get a legal address from the command buffer */ -#define GET_THIRD_ADDR(addr) \ -{ \ - long ol1, ol2; \ -\ - ol1 = first_addr, ol2 = second_addr; \ - if (extract_addr_range() < 0) \ - return ERR; \ - if (second_addr < 0 || addr_last < second_addr) { \ - seterrmsg("invalid address"); \ - return ERR; \ - } \ - addr = second_addr; \ - first_addr = ol1, second_addr = ol2; \ -} -#endif - - -/* GET_COMMAND_SUFFIX: verify the command suffix in the command buffer */ -#define GET_COMMAND_SUFFIX() { \ - int done = 0; \ - do { \ - switch(*ibufp) { \ - case 'p': \ - gflag |= GPR, ibufp++; \ - break; \ - case 'l': \ - gflag |= GLS, ibufp++; \ - break; \ - case 'n': \ - gflag |= GNP, ibufp++; \ - break; \ - default: \ - done++; \ - } \ - } while (!done); \ - if (*ibufp++ != '\n') { \ - seterrmsg("invalid command suffix"); \ - return ERR; \ - } \ -} - - -/* sflags */ -#define SGG 001 /* complement previous global substitute suffix */ -#define SGP 002 /* complement previous print suffix */ -#define SGR 004 /* use last regex instead of last pat */ -#define SGF 010 /* repeat last substitution */ - -int patlock = 0; /* if set, pattern not freed by get_compiled_pattern() */ - -long rows = 22; /* scroll length: ws_row - 2 */ - -/* exec_command: execute the next command in command buffer; return print - request, if any */ -int -exec_command(void) -{ - static pattern_t *pat = NULL; - static int sgflag = 0; - static long sgnum = 0; - - pattern_t *tpat; - char *fnp; - int gflag = 0; - int sflags = 0; - long addr = 0; - int n = 0; - int c; - - SKIP_BLANKS(); - switch(c = *ibufp++) { - case 'a': - GET_COMMAND_SUFFIX(); - if (!isglobal) clear_undo_stack(); - if (append_lines(second_addr) < 0) - return ERR; - break; - case 'c': - if (check_addr_range(current_addr, current_addr) < 0) - return ERR; - GET_COMMAND_SUFFIX(); - if (!isglobal) clear_undo_stack(); - if (delete_lines(first_addr, second_addr) < 0 || - append_lines(current_addr) < 0) - return ERR; - break; - case 'd': - if (check_addr_range(current_addr, current_addr) < 0) - return ERR; - GET_COMMAND_SUFFIX(); - if (!isglobal) clear_undo_stack(); - if (delete_lines(first_addr, second_addr) < 0) - return ERR; - else if ((addr = INC_MOD(current_addr, addr_last)) != 0) - current_addr = addr; - break; - case 'e': - if (modified && !scripted) - return EMOD; - /* fall through */ - case 'E': - if (addr_cnt > 0) { - seterrmsg("unexpected address"); - return ERR; - } else if (!isspace((unsigned char)*ibufp)) { - seterrmsg("unexpected command suffix"); - return ERR; - } else if ((fnp = get_filename()) == NULL) - return ERR; - GET_COMMAND_SUFFIX(); - if (delete_lines(1, addr_last) < 0) - return ERR; - clear_undo_stack(); - if (close_sbuf() < 0) - return ERR; - else if (open_sbuf() < 0) - return FATAL; - if (*fnp && *fnp != '!') strlcpy(old_filename, fnp, - sizeof(old_filename) - 2); -#ifdef BACKWARDS - if (*fnp == '\0' && *old_filename == '\0') { - seterrmsg("no current filename"); - return ERR; - } -#endif - if (read_file(*fnp ? fnp : old_filename, 0) < 0) - return ERR; - clear_undo_stack(); - modified = 0; - u_current_addr = u_addr_last = -1; - break; - case 'f': - if (addr_cnt > 0) { - seterrmsg("unexpected address"); - return ERR; - } else if (!isspace((unsigned char)*ibufp)) { - seterrmsg("unexpected command suffix"); - return ERR; - } else if ((fnp = get_filename()) == NULL) - return ERR; - else if (*fnp == '!') { - seterrmsg("invalid redirection"); - return ERR; - } - GET_COMMAND_SUFFIX(); - if (*fnp) strlcpy(old_filename, fnp, sizeof(old_filename) - 2); - printf("%s\n", strip_escapes(old_filename)); - break; - case 'g': - case 'v': - case 'G': - case 'V': - if (isglobal) { - seterrmsg("cannot nest global commands"); - return ERR; - } else if (check_addr_range(1, addr_last) < 0) - return ERR; - else if (build_active_list(c == 'g' || c == 'G') < 0) - return ERR; - else if ((n = (c == 'G' || c == 'V')) != 0) - GET_COMMAND_SUFFIX(); - isglobal++; - if (exec_global(n, gflag) < 0) - return ERR; - break; - case 'h': - if (addr_cnt > 0) { - seterrmsg("unexpected address"); - return ERR; - } - GET_COMMAND_SUFFIX(); - if (*errmsg) fprintf(stderr, "%s\n", errmsg); - break; - case 'H': - if (addr_cnt > 0) { - seterrmsg("unexpected address"); - return ERR; - } - GET_COMMAND_SUFFIX(); - if ((garrulous = 1 - garrulous) && *errmsg) - fprintf(stderr, "%s\n", errmsg); - break; - case 'i': - if (second_addr == 0) { - seterrmsg("invalid address"); - return ERR; - } - GET_COMMAND_SUFFIX(); - if (!isglobal) clear_undo_stack(); - if (append_lines(second_addr - 1) < 0) - return ERR; - break; - case 'j': - if (check_addr_range(current_addr, current_addr + 1) < 0) - return ERR; - GET_COMMAND_SUFFIX(); - if (!isglobal) clear_undo_stack(); - if (first_addr != second_addr && - join_lines(first_addr, second_addr) < 0) - return ERR; - break; - case 'k': - c = *ibufp++; - if (second_addr == 0) { - seterrmsg("invalid address"); - return ERR; - } - GET_COMMAND_SUFFIX(); - if (mark_line_node(get_addressed_line_node(second_addr), (unsigned char)c) < 0) - return ERR; - break; - case 'l': - if (check_addr_range(current_addr, current_addr) < 0) - return ERR; - GET_COMMAND_SUFFIX(); - if (display_lines(first_addr, second_addr, gflag | GLS) < 0) - return ERR; - gflag = 0; - break; - case 'm': - if (check_addr_range(current_addr, current_addr) < 0) - return ERR; - GET_THIRD_ADDR(addr); - if (first_addr <= addr && addr < second_addr) { - seterrmsg("invalid destination"); - return ERR; - } - GET_COMMAND_SUFFIX(); - if (!isglobal) clear_undo_stack(); - if (move_lines(addr) < 0) - return ERR; - break; - case 'n': - if (check_addr_range(current_addr, current_addr) < 0) - return ERR; - GET_COMMAND_SUFFIX(); - if (display_lines(first_addr, second_addr, gflag | GNP) < 0) - return ERR; - gflag = 0; - break; - case 'p': - if (check_addr_range(current_addr, current_addr) < 0) - return ERR; - GET_COMMAND_SUFFIX(); - if (display_lines(first_addr, second_addr, gflag | GPR) < 0) - return ERR; - gflag = 0; - break; - case 'P': - if (addr_cnt > 0) { - seterrmsg("unexpected address"); - return ERR; - } - GET_COMMAND_SUFFIX(); - prompt = prompt ? NULL : optarg ? optarg : dps; - break; - case 'q': - case 'Q': - if (addr_cnt > 0) { - seterrmsg("unexpected address"); - return ERR; - } - GET_COMMAND_SUFFIX(); - gflag = (modified && !scripted && c == 'q') ? EMOD : EOF; - break; - case 'r': - if (!isspace((unsigned char)*ibufp)) { - seterrmsg("unexpected command suffix"); - return ERR; - } else if (addr_cnt == 0) - second_addr = addr_last; - if ((fnp = get_filename()) == NULL) - return ERR; - GET_COMMAND_SUFFIX(); - if (!isglobal) clear_undo_stack(); - if (*old_filename == '\0' && *fnp != '!') - strlcpy(old_filename, fnp, sizeof(old_filename) - 2); -#ifdef BACKWARDS - if (*fnp == '\0' && *old_filename == '\0') { - seterrmsg("no current filename"); - return ERR; - } -#endif - if ((addr = read_file(*fnp ? fnp : old_filename, second_addr)) < 0) - return ERR; - else if (addr && addr != addr_last) - modified = 1; - break; - case 's': - do { - switch(*ibufp) { - case '\n': - sflags |=SGF; - break; - case 'g': - sflags |= SGG; - ibufp++; - break; - case 'p': - sflags |= SGP; - ibufp++; - break; - case 'r': - sflags |= SGR; - ibufp++; - break; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - STRTOL(sgnum, ibufp); - sflags |= SGF; - sgflag &= ~GSG; /* override GSG */ - break; - default: - if (sflags) { - seterrmsg("invalid command suffix"); - return ERR; - } - } - } while (sflags && *ibufp != '\n'); - if (sflags && !pat) { - seterrmsg("no previous substitution"); - return ERR; - } else if (sflags & SGG) - sgnum = 0; /* override numeric arg */ - if (*ibufp != '\n' && *(ibufp + 1) == '\n') { - seterrmsg("invalid pattern delimiter"); - return ERR; - } - tpat = pat; - SPL1(); - if ((!sflags || (sflags & SGR)) && - (tpat = get_compiled_pattern()) == NULL) { - SPL0(); - return ERR; - } else if (tpat != pat) { - if (pat) { - regfree(pat); - free(pat); - } - pat = tpat; - patlock = 1; /* reserve pattern */ - } - SPL0(); - if (!sflags && extract_subst_tail(&sgflag, &sgnum) < 0) - return ERR; - else if (isglobal) - sgflag |= GLB; - else - sgflag &= ~GLB; - if (sflags & SGG) - sgflag ^= GSG; - if (sflags & SGP) - sgflag ^= GPR, sgflag &= ~(GLS | GNP); - do { - switch(*ibufp) { - case 'p': - sgflag |= GPR, ibufp++; - break; - case 'l': - sgflag |= GLS, ibufp++; - break; - case 'n': - sgflag |= GNP, ibufp++; - break; - default: - n++; - } - } while (!n); - if (check_addr_range(current_addr, current_addr) < 0) - return ERR; - GET_COMMAND_SUFFIX(); - if (!isglobal) clear_undo_stack(); - if (search_and_replace(pat, sgflag, sgnum) < 0) - return ERR; - break; - case 't': - if (check_addr_range(current_addr, current_addr) < 0) - return ERR; - GET_THIRD_ADDR(addr); - GET_COMMAND_SUFFIX(); - if (!isglobal) clear_undo_stack(); - if (copy_lines(addr) < 0) - return ERR; - break; - case 'u': - if (addr_cnt > 0) { - seterrmsg("unexpected address"); - return ERR; - } - GET_COMMAND_SUFFIX(); - if (pop_undo_stack() < 0) - return ERR; - break; - case 'w': - case 'W': - if ((n = *ibufp) == 'q' || n == 'Q') { - gflag = EOF; - ibufp++; - } - if (!isspace((unsigned char)*ibufp)) { - seterrmsg("unexpected command suffix"); - return ERR; - } else if ((fnp = get_filename()) == NULL) - return ERR; - if (addr_cnt == 0 && !addr_last) - first_addr = second_addr = 0; - else if (check_addr_range(1, addr_last) < 0) - return ERR; - GET_COMMAND_SUFFIX(); - if (*old_filename == '\0' && *fnp != '!') - strlcpy(old_filename, fnp, sizeof(old_filename) - 2); -#ifdef BACKWARDS - if (*fnp == '\0' && *old_filename == '\0') { - seterrmsg("no current filename"); - return ERR; - } -#endif - if ((addr = write_file(*fnp ? fnp : old_filename, - (c == 'W') ? "a" : "w", first_addr, second_addr)) < 0) - return ERR; - else if (addr == addr_last) - modified = 0; - else if (modified && !scripted && n == 'q') - gflag = EMOD; - break; - case 'x': - if (addr_cnt > 0) { - seterrmsg("unexpected address"); - return ERR; - } - GET_COMMAND_SUFFIX(); -#ifdef DES - des = get_keyword(); -#else - seterrmsg("crypt unavailable"); - return ERR; -#endif - break; - case 'z': -#ifdef BACKWARDS - if (check_addr_range(first_addr = 1, current_addr + 1) < 0) -#else - if (check_addr_range(first_addr = 1, current_addr + !isglobal) < 0) -#endif - return ERR; - else if ('0' < *ibufp && *ibufp <= '9') - STRTOL(rows, ibufp); - GET_COMMAND_SUFFIX(); - if (display_lines(second_addr, min(addr_last, - second_addr + rows), gflag) < 0) - return ERR; - gflag = 0; - break; - case '=': - GET_COMMAND_SUFFIX(); - printf("%ld\n", addr_cnt ? second_addr : addr_last); - break; - case '!': - if (addr_cnt > 0) { - seterrmsg("unexpected address"); - return ERR; - } - if ((sflags = get_shell_command()) < 0) - return ERR; - GET_COMMAND_SUFFIX(); - if (sflags) printf("%s\n", shcmd + 1); - system(shcmd + 1); - if (!scripted) printf("!\n"); - break; - case '\n': -#ifdef BACKWARDS - if (check_addr_range(first_addr = 1, current_addr + 1) < 0 -#else - if (check_addr_range(first_addr = 1, current_addr + !isglobal) < 0 -#endif - || display_lines(second_addr, second_addr, 0) < 0) - return ERR; - break; - default: - seterrmsg("unknown command"); - return ERR; - } - return gflag; -} - - -/* check_addr_range: return status of address range check */ -int -check_addr_range(long n, long m) -{ - if (addr_cnt == 0) { - first_addr = n; - second_addr = m; - } - if (first_addr > second_addr || 1 > first_addr || - second_addr > addr_last) { - seterrmsg("invalid address"); - return ERR; - } - return 0; -} - - -/* get_matching_node_addr: return the address of the next line matching a - pattern in a given direction. wrap around begin/end of editor buffer if - necessary */ -long -get_matching_node_addr(pattern_t *pat, int dir) -{ - char *s; - long n = current_addr; - line_t *lp; - - if (!pat) return ERR; - do { - if ((n = dir ? INC_MOD(n, addr_last) : - DEC_MOD(n, addr_last)) != 0) { - lp = get_addressed_line_node(n); - if ((s = get_sbuf_line(lp)) == NULL) - return ERR; - if (isbinary) - NUL_TO_NEWLINE(s, lp->len); - if (!regexec(pat, s, 0, NULL, 0)) - return n; - } - } while (n != current_addr); - seterrmsg("no match"); - return ERR; -} - - -/* get_filename: return pointer to copy of filename in the command buffer */ -char * -get_filename(void) -{ - static char *file = NULL; - static int filesz = 0; - - int n; - - if (*ibufp != '\n') { - SKIP_BLANKS(); - if (*ibufp == '\n') { - seterrmsg("invalid filename"); - return NULL; - } else if ((ibufp = get_extended_line(&n, 1)) == NULL) - return NULL; - else if (*ibufp == '!') { - ibufp++; - if ((n = get_shell_command()) < 0) - return NULL; - if (n) printf("%s\n", shcmd + 1); - return shcmd; - } else if (n - 1 > MAXPATHLEN) { - seterrmsg("filename too long"); - return NULL; - } - } -#ifndef BACKWARDS - else if (*old_filename == '\0') { - seterrmsg("no current filename"); - return NULL; - } -#endif - REALLOC(file, filesz, MAXPATHLEN + 1, NULL); - for (n = 0; *ibufp != '\n';) - file[n++] = *ibufp++; - file[n] = '\0'; - return is_legal_filename(file) ? file : NULL; -} - - -/* get_shell_command: read a shell command from stdin; return substitution - status */ -int -get_shell_command(void) -{ - static char *buf = NULL; - static int n = 0; - - char *s; /* substitution char pointer */ - int i = 0; - int j = 0; - - if (red || secure) { - seterrmsg("shell access restricted"); - return ERR; - } else if ((s = ibufp = get_extended_line(&j, 1)) == NULL) - return ERR; - REALLOC(buf, n, j + 1, ERR); - buf[i++] = '!'; /* prefix command w/ bang */ - while (*ibufp != '\n') - switch (*ibufp) { - default: - REALLOC(buf, n, i + 2, ERR); - buf[i++] = *ibufp; - if (*ibufp++ == '\\') - buf[i++] = *ibufp++; - break; - case '!': - if (s != ibufp) { - REALLOC(buf, n, i + 1, ERR); - buf[i++] = *ibufp++; - } -#ifdef BACKWARDS - else if (shcmd == NULL || *(shcmd + 1) == '\0') -#else - else if (shcmd == NULL) -#endif - { - seterrmsg("no previous command"); - return ERR; - } else { - REALLOC(buf, n, i + shcmdi, ERR); - for (s = shcmd + 1; s < shcmd + shcmdi;) - buf[i++] = *s++; - s = ibufp++; - } - break; - case '%': - if (*old_filename == '\0') { - seterrmsg("no current filename"); - return ERR; - } - j = strlen(s = strip_escapes(old_filename)); - REALLOC(buf, n, i + j, ERR); - while (j--) - buf[i++] = *s++; - s = ibufp++; - break; - } - REALLOC(shcmd, shcmdsz, i + 1, ERR); - memcpy(shcmd, buf, i); - shcmd[shcmdi = i] = '\0'; - return *s == '!' || *s == '%'; -} - - -/* append_lines: insert text from stdin to after line n; stop when either a - single period is read or EOF; return status */ -int -append_lines(long n) -{ - int l; - char *lp = ibuf; - char *eot; - undo_t *up = NULL; - - for (current_addr = n;;) { - if (!isglobal) { - if ((l = get_tty_line()) < 0) - return ERR; - else if (l == 0 || ibuf[l - 1] != '\n') { - clearerr(stdin); - return l ? EOF : 0; - } - lp = ibuf; - } else if (*(lp = ibufp) == '\0') - return 0; - else { - while (*ibufp++ != '\n') - ; - l = ibufp - lp; - } - if (l == 2 && lp[0] == '.' && lp[1] == '\n') { - return 0; - } - eot = lp + l; - SPL1(); - do { - if ((lp = put_sbuf_line(lp)) == NULL) { - SPL0(); - return ERR; - } else if (up) - up->t = get_addressed_line_node(current_addr); - else if ((up = push_undo_stack(UADD, current_addr, - current_addr)) == NULL) { - SPL0(); - return ERR; - } - } while (lp != eot); - modified = 1; - SPL0(); - } - /* NOTREACHED */ -} - - -/* join_lines: replace a range of lines with the joined text of those lines */ -int -join_lines(long from, long to) -{ - static char *buf = NULL; - static int n; - - char *s; - int size = 0; - line_t *bp, *ep; - - ep = get_addressed_line_node(INC_MOD(to, addr_last)); - bp = get_addressed_line_node(from); - for (; bp != ep; bp = bp->q_forw) { - if ((s = get_sbuf_line(bp)) == NULL) - return ERR; - REALLOC(buf, n, size + bp->len, ERR); - memcpy(buf + size, s, bp->len); - size += bp->len; - } - REALLOC(buf, n, size + 2, ERR); - memcpy(buf + size, "\n", 2); - if (delete_lines(from, to) < 0) - return ERR; - current_addr = from - 1; - SPL1(); - if (put_sbuf_line(buf) == NULL || - push_undo_stack(UADD, current_addr, current_addr) == NULL) { - SPL0(); - return ERR; - } - modified = 1; - SPL0(); - return 0; -} - - -/* move_lines: move a range of lines */ -int -move_lines(long addr) -{ - line_t *b1, *a1, *b2, *a2; - long n = INC_MOD(second_addr, addr_last); - long p = first_addr - 1; - int done = (addr == first_addr - 1 || addr == second_addr); - - SPL1(); - if (done) { - a2 = get_addressed_line_node(n); - b2 = get_addressed_line_node(p); - current_addr = second_addr; - } else if (push_undo_stack(UMOV, p, n) == NULL || - push_undo_stack(UMOV, addr, INC_MOD(addr, addr_last)) == NULL) { - SPL0(); - return ERR; - } else { - a1 = get_addressed_line_node(n); - if (addr < first_addr) { - b1 = get_addressed_line_node(p); - b2 = get_addressed_line_node(addr); - /* this get_addressed_line_node last! */ - } else { - b2 = get_addressed_line_node(addr); - b1 = get_addressed_line_node(p); - /* this get_addressed_line_node last! */ - } - a2 = b2->q_forw; - REQUE(b2, b1->q_forw); - REQUE(a1->q_back, a2); - REQUE(b1, a1); - current_addr = addr + ((addr < first_addr) ? - second_addr - first_addr + 1 : 0); - } - if (isglobal) - unset_active_nodes(b2->q_forw, a2); - modified = 1; - SPL0(); - return 0; -} - - -/* copy_lines: copy a range of lines; return status */ -int -copy_lines(long addr) -{ - line_t *lp, *np = get_addressed_line_node(first_addr); - undo_t *up = NULL; - long n = second_addr - first_addr + 1; - long m = 0; - - current_addr = addr; - if (first_addr <= addr && addr < second_addr) { - n = addr - first_addr + 1; - m = second_addr - addr; - } - for (; n > 0; n=m, m=0, np = get_addressed_line_node(current_addr + 1)) - for (; n-- > 0; np = np->q_forw) { - SPL1(); - if ((lp = dup_line_node(np)) == NULL) { - SPL0(); - return ERR; - } - add_line_node(lp); - if (up) - up->t = lp; - else if ((up = push_undo_stack(UADD, current_addr, - current_addr)) == NULL) { - SPL0(); - return ERR; - } - modified = 1; - SPL0(); - } - return 0; -} - - -/* delete_lines: delete a range of lines */ -int -delete_lines(long from, long to) -{ - line_t *n, *p; - - SPL1(); - if (push_undo_stack(UDEL, from, to) == NULL) { - SPL0(); - return ERR; - } - n = get_addressed_line_node(INC_MOD(to, addr_last)); - p = get_addressed_line_node(from - 1); - /* this get_addressed_line_node last! */ - if (isglobal) - unset_active_nodes(p->q_forw, n); - REQUE(p, n); - addr_last -= to - from + 1; - current_addr = from - 1; - modified = 1; - SPL0(); - return 0; -} - - -/* display_lines: print a range of lines to stdout */ -int -display_lines(long from, long to, int gflag) -{ - line_t *bp; - line_t *ep; - char *s; - - if (!from) { - seterrmsg("invalid address"); - return ERR; - } - ep = get_addressed_line_node(INC_MOD(to, addr_last)); - bp = get_addressed_line_node(from); - for (; bp != ep; bp = bp->q_forw) { - if ((s = get_sbuf_line(bp)) == NULL) - return ERR; - if (put_tty_line(s, bp->len, current_addr = from++, gflag) < 0) - return ERR; - } - return 0; -} - - -#define MAXMARK 26 /* max number of marks */ - -line_t *mark[MAXMARK]; /* line markers */ -int markno; /* line marker count */ - -/* mark_line_node: set a line node mark */ -int -mark_line_node(line_t *lp, int n) -{ - if (!islower(n)) { - seterrmsg("invalid mark character"); - return ERR; - } else if (mark[n - 'a'] == NULL) - markno++; - mark[n - 'a'] = lp; - return 0; -} - - -/* get_marked_node_addr: return address of a marked line */ -long -get_marked_node_addr(int n) -{ - if (!islower(n)) { - seterrmsg("invalid mark character"); - return ERR; - } - return get_line_node_addr(mark[n - 'a']); -} - - -/* unmark_line_node: clear line node mark */ -void -unmark_line_node(line_t *lp) -{ - int i; - - for (i = 0; markno && i < MAXMARK; i++) - if (mark[i] == lp) { - mark[i] = NULL; - markno--; - } -} - - -/* dup_line_node: return a pointer to a copy of a line node */ -line_t * -dup_line_node(line_t *lp) -{ - line_t *np; - - if ((np = (line_t *) malloc(sizeof(line_t))) == NULL) { - fprintf(stderr, "%s\n", strerror(errno)); - seterrmsg("out of memory"); - return NULL; - } - np->seek = lp->seek; - np->len = lp->len; - return np; -} - - -/* has_trailing_escape: return the parity of escapes preceding a character - in a string */ -int -has_trailing_escape(char *s, char *t) -{ - return (s == t || *(t - 1) != '\\') ? 0 : !has_trailing_escape(s, t - 1); -} - - -/* strip_escapes: return copy of escaped string of at most length MAXPATHLEN */ -char * -strip_escapes(const char *s) -{ - static char *file = NULL; - static int filesz = 0; - - int i = 0; - - REALLOC(file, filesz, MAXPATHLEN + 1, NULL); - while ((i < (filesz - 1)) && - (file[i++] = (*s == '\\') != '\0' ? *++s : *s)) - s++; - file[filesz - 1] = '\0'; - return file; -} - - -void -signal_hup(int signo) -{ - if (mutex) - sigflags |= (1 << (signo - 1)); - else handle_hup(signo); -} - - -void -signal_int(int signo) -{ - if (mutex) - sigflags |= (1 << (signo - 1)); - else handle_int(signo); -} - - -void -handle_hup(int signo) -{ - char *hup = NULL; /* hup filename */ - char *s; - int n; - - if (!sigactive) - quit(1); - sigflags &= ~(1 << (signo - 1)); - if (addr_last && write_file("ed.hup", "w", 1, addr_last) < 0 && - (s = getenv("HOME")) != NULL && - (n = strlen(s)) + 8 <= MAXPATHLEN && /* "ed.hup" + '/' */ - (hup = (char *) malloc(n + 10)) != NULL) { - strcpy(hup, s); - if (hup[n - 1] != '/') - hup[n] = '/', hup[n+1] = '\0'; - strcat(hup, "ed.hup"); - write_file(hup, "w", 1, addr_last); - } - quit(2); -} - - -void -handle_int(int signo) -{ - if (!sigactive) - quit(1); - sigflags &= ~(1 << (signo - 1)); -#ifdef _POSIX_SOURCE - siglongjmp(env, -1); -#else - longjmp(env, -1); -#endif -} - - -int cols = 72; /* wrap column */ - -void -handle_winch(int signo) -{ - struct winsize ws; /* window size structure */ - - sigflags &= ~(1 << (signo - 1)); - if (ioctl(0, TIOCGWINSZ, (char *) &ws) >= 0) { - if (ws.ws_row > 2) rows = ws.ws_row - 2; - if (ws.ws_col > 8) cols = ws.ws_col - 8; - } -} - - -/* is_legal_filename: return a legal filename */ -int -is_legal_filename(char *s) -{ - if (red && (*s == '!' || !strcmp(s, "..") || strchr(s, '/'))) { - seterrmsg("shell access restricted"); - return 0; - } - return 1; -} diff --git a/bin/ed/re.c b/bin/ed/re.c deleted file mode 100644 index bc4abc936..000000000 --- a/bin/ed/re.c +++ /dev/null @@ -1,146 +0,0 @@ -/* $NetBSD: re.c,v 1.21 2014/03/23 05:06:42 dholland Exp $ */ - -/* re.c: This file contains the regular expression interface routines for - the ed line editor. */ -/*- - * Copyright (c) 1993 Andrew Moore, Talke Studio. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char *rcsid = "@(#)re.c,v 1.6 1994/02/01 00:34:43 alm Exp"; -#else -__RCSID("$NetBSD: re.c,v 1.21 2014/03/23 05:06:42 dholland Exp $"); -#endif -#endif /* not lint */ - -#include -#include "ed.h" - - -char errmsg[MAXPATHLEN + 40] = ""; - -void -seterrmsg(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - vsnprintf(errmsg, sizeof(errmsg), fmt, ap); - va_end(ap); -} - -/* get_compiled_pattern: return pointer to compiled pattern from command - buffer */ -pattern_t * -get_compiled_pattern(void) -{ - static pattern_t *expr = NULL; - - char *exps; - char delimiter; - int n; - - if ((delimiter = *ibufp) == ' ') { - seterrmsg("invalid pattern delimiter"); - return NULL; - } else if (delimiter == '\n' || *++ibufp == '\n' || *ibufp == delimiter) { - if (!expr) seterrmsg("no previous pattern"); - return expr; - } else if ((exps = extract_pattern(delimiter)) == NULL) - return NULL; - /* buffer alloc'd && not reserved */ - if (expr && !patlock) - regfree(expr); - else if ((expr = (pattern_t *) malloc(sizeof(pattern_t))) == NULL) { - fprintf(stderr, "%s\n", strerror(errno)); - seterrmsg("out of memory"); - return NULL; - } - patlock = 0; - if ((n = regcomp(expr, exps, ere)) != 0) { - regerror(n, expr, errmsg, sizeof errmsg); - free(expr); - return expr = NULL; - } - return expr; -} - - -/* extract_pattern: copy a pattern string from the command buffer; return - pointer to the copy */ -char * -extract_pattern(int delimiter) -{ - static char *lhbuf = NULL; /* buffer */ - static int lhbufsz = 0; /* buffer size */ - - char *nd; - int len; - - for (nd = ibufp; *nd != delimiter && *nd != '\n'; nd++) - switch (*nd) { - default: - break; - case '[': - if ((nd = parse_char_class(nd + 1)) == NULL) { - seterrmsg("unbalanced brackets ([])"); - return NULL; - } - break; - case '\\': - if (*++nd == '\n') { - seterrmsg("trailing backslash (\\)"); - return NULL; - } - break; - } - len = nd - ibufp; - REALLOC(lhbuf, lhbufsz, len + 1, NULL); - memcpy(lhbuf, ibufp, len); - lhbuf[len] = '\0'; - ibufp = nd; - return (isbinary) ? NUL_TO_NEWLINE(lhbuf, len) : lhbuf; -} - - -/* parse_char_class: expand a POSIX character class */ -char * -parse_char_class(char *s) -{ - int c, d; - - if (*s == '^') - s++; - if (*s == ']') - s++; - for (; *s != ']' && *s != '\n'; s++) - if (*s == '[' && ((d = *(s+1)) == '.' || d == ':' || d == '=')) - for (s++, c = *++s; *s != ']' || c != d; s++) - if ((c = *s) == '\n') - return NULL; - return (*s == ']') ? s : NULL; -} diff --git a/bin/ed/sub.c b/bin/ed/sub.c deleted file mode 100644 index 933c6b921..000000000 --- a/bin/ed/sub.c +++ /dev/null @@ -1,262 +0,0 @@ -/* $NetBSD: sub.c,v 1.7 2014/03/23 05:06:42 dholland Exp $ */ - -/* sub.c: This file contains the substitution routines for the ed - line editor */ -/*- - * Copyright (c) 1993 Andrew Moore, Talke Studio. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char *rcsid = "@(#)sub.c,v 1.1 1994/02/01 00:34:44 alm Exp"; -#else -__RCSID("$NetBSD: sub.c,v 1.7 2014/03/23 05:06:42 dholland Exp $"); -#endif -#endif /* not lint */ - -#include "ed.h" - - -char *rhbuf; /* rhs substitution buffer */ -int rhbufsz; /* rhs substitution buffer size */ -int rhbufi; /* rhs substitution buffer index */ - -/* extract_subst_tail: extract substitution tail from the command buffer */ -int -extract_subst_tail(int *flagp, long *np) -{ - char delimiter; - - *flagp = *np = 0; - if ((delimiter = *ibufp) == '\n') { - rhbufi = 0; - *flagp = GPR; - return 0; - } else if (extract_subst_template() == NULL) - return ERR; - else if (*ibufp == '\n') { - *flagp = GPR; - return 0; - } else if (*ibufp == delimiter) - ibufp++; - if ('1' <= *ibufp && *ibufp <= '9') { - STRTOL(*np, ibufp); - return 0; - } else if (*ibufp == 'g') { - ibufp++; - *flagp = GSG; - return 0; - } - return 0; -} - - -/* extract_subst_template: return pointer to copy of substitution template - in the command buffer */ -char * -extract_subst_template(void) -{ - int n = 0; - int i = 0; - char c; - char delimiter = *ibufp++; - - if (*ibufp == '%' && *(ibufp + 1) == delimiter) { - ibufp++; - if (!rhbuf) { - seterrmsg("no previous substitution"); - } - return rhbuf; - } - while (*ibufp != delimiter) { - REALLOC(rhbuf, rhbufsz, i + 2, NULL); - if ((c = rhbuf[i++] = *ibufp++) == '\n' && *ibufp == '\0') { - i--, ibufp--; - break; - } else if (c != '\\') - ; - else if ((rhbuf[i++] = *ibufp++) != '\n') - ; - else if (!isglobal) { - while ((n = get_tty_line()) == 0 || - (n > 0 && ibuf[n - 1] != '\n')) - clearerr(stdin); - if (n < 0) - return NULL; - } - } - REALLOC(rhbuf, rhbufsz, i + 1, NULL); - rhbuf[rhbufi = i] = '\0'; - return rhbuf; -} - - -char *rbuf; /* substitute_matching_text buffer */ -int rbufsz; /* substitute_matching_text buffer size */ - -/* search_and_replace: for each line in a range, change text matching a pattern - according to a substitution template; return status */ -int -search_and_replace(pattern_t *pat, int gflag, int kth) -{ - undo_t *up; - char *txt; - char *eot; - long lc; - long xa = current_addr; - int nsubs = 0; - line_t *lp; - int len; - - current_addr = first_addr - 1; - for (lc = 0; lc <= second_addr - first_addr; lc++) { - lp = get_addressed_line_node(++current_addr); - if ((len = substitute_matching_text(pat, lp, gflag, kth)) < 0) - return ERR; - else if (len) { - up = NULL; - if (delete_lines(current_addr, current_addr) < 0) - return ERR; - txt = rbuf; - eot = rbuf + len; - SPL1(); - do { - if ((txt = put_sbuf_line(txt)) == NULL) { - SPL0(); - return ERR; - } else if (up) - up->t = get_addressed_line_node(current_addr); - else if ((up = push_undo_stack(UADD, - current_addr, current_addr)) == NULL) { - SPL0(); - return ERR; - } - } while (txt != eot); - SPL0(); - nsubs++; - xa = current_addr; - } - } - current_addr = xa; - if (nsubs == 0 && !(gflag & GLB)) { - seterrmsg("no match"); - return ERR; - } else if ((gflag & (GPR | GLS | GNP)) && - display_lines(current_addr, current_addr, gflag) < 0) - return ERR; - return 0; -} - - -/* substitute_matching_text: replace text matched by a pattern according to - a substitution template; return pointer to the modified text */ -int -substitute_matching_text(pattern_t *pat, line_t *lp, int gflag, int kth) -{ - int off = 0; - int changed = 0; - int matchno = 0; - int i = 0; - regmatch_t rm[SE_MAX]; - char *txt; - char *eot; - - if ((txt = get_sbuf_line(lp)) == NULL) - return ERR; - if (isbinary) - NUL_TO_NEWLINE(txt, lp->len); - eot = txt + lp->len; - if (!regexec(pat, txt, SE_MAX, rm, 0)) { - do { - if (!kth || kth == ++matchno) { - changed++; - i = rm[0].rm_so; - REALLOC(rbuf, rbufsz, off + i, ERR); - if (isbinary) - NEWLINE_TO_NUL(txt, rm[0].rm_eo); - memcpy(rbuf + off, txt, i); - off += i; - if ((off = apply_subst_template(txt, rm, off, - pat->re_nsub)) < 0) - return ERR; - } else { - i = rm[0].rm_eo; - REALLOC(rbuf, rbufsz, off + i, ERR); - if (isbinary) - NEWLINE_TO_NUL(txt, i); - memcpy(rbuf + off, txt, i); - off += i; - } - txt += rm[0].rm_eo; - } while (*txt && (!changed || ((gflag & GSG) && rm[0].rm_eo)) - && !regexec(pat, txt, SE_MAX, rm, REG_NOTBOL)); - i = eot - txt; - REALLOC(rbuf, rbufsz, off + i + 2, ERR); - if (i > 0 && !rm[0].rm_eo && (gflag & GSG)) { - seterrmsg("infinite substitution loop"); - return ERR; - } - if (isbinary) - NEWLINE_TO_NUL(txt, i); - memcpy(rbuf + off, txt, i); - memcpy(rbuf + off + i, "\n", 2); - } - return changed ? off + i + 1 : 0; -} - - -/* apply_subst_template: modify text according to a substitution template; - return offset to end of modified text */ -int -apply_subst_template(char *boln, regmatch_t *rm, int off, int re_nsub) -{ - int j = 0; - int k = 0; - int n; - char *sub = rhbuf; - - for (; sub - rhbuf < rhbufi; sub++) - if (*sub == '&') { - j = rm[0].rm_so; - k = rm[0].rm_eo; - REALLOC(rbuf, rbufsz, off + k - j, ERR); - while (j < k) - rbuf[off++] = boln[j++]; - } else if (*sub == '\\' && '1' <= *++sub && *sub <= '9' && - (n = *sub - '0') <= re_nsub) { - j = rm[n].rm_so; - k = rm[n].rm_eo; - REALLOC(rbuf, rbufsz, off + k - j, ERR); - while (j < k) - rbuf[off++] = boln[j++]; - } else { - REALLOC(rbuf, rbufsz, off + 1, ERR); - rbuf[off++] = *sub; - } - REALLOC(rbuf, rbufsz, off + 1, ERR); - rbuf[off] = '\0'; - return off; -} diff --git a/bin/ed/test/Makefile b/bin/ed/test/Makefile deleted file mode 100644 index fe631a83b..000000000 --- a/bin/ed/test/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -# $NetBSD: Makefile,v 1.12 2003/10/26 03:50:07 lukem Exp $ - -.include - -ED?= ../obj/ed - -all: check - @: - -check: build test - @if grep -h '\*\*\*' errs.o scripts.o; then :; else \ - echo "tests completed successfully."; \ - fi - -build: mkscripts.sh - @if [ -f errs.o ]; then :; else \ - echo "building test scripts for $(ED) ..."; \ - ${HOST_SH} ${.CURDIR}/mkscripts.sh $(ED); \ - fi - -test: build ckscripts.sh - @echo testing $(ED) ... - @${HOST_SH} ckscripts.sh $(ED) - -clean: - rm -f *.ed *.red *.[oz] *~ - -.include diff --git a/bin/ed/test/TODO b/bin/ed/test/TODO deleted file mode 100644 index c516d1eb8..000000000 --- a/bin/ed/test/TODO +++ /dev/null @@ -1,17 +0,0 @@ -$NetBSD: TODO,v 1.3 1995/03/21 09:05:20 cgd Exp $ - -Some missing tests: -0) g/./s^@^@ - okay: NULs in commands -1) g/./s/^@/ - okay: NULs in patterns -2) a - hello^V^Jworld - . - okay: embedded newlines in insert mode -3) ed "" - error: invalid filename -4) red .. - error: restricted -5) red / - error: restricted -5) red !xx - error: restricted -6) ed -x - verify: 8-bit clean -7) ed - verify: long-line support -8) ed - verify: interactive/help mode -9) G/pat/ - verify: global interactive command -10) V/pat/ - verify: global interactive command diff --git a/bin/ed/test/ckscripts.sh b/bin/ed/test/ckscripts.sh deleted file mode 100755 index 86a19b18d..000000000 --- a/bin/ed/test/ckscripts.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -# $NetBSD: ckscripts.sh,v 1.9 1995/04/23 10:07:34 cgd Exp $ -# -# This script runs the .ed scripts generated by mkscripts.sh -# and compares their output against the .r files, which contain -# the correct output - -PATH="/bin:/usr/bin:/usr/local/bin/:." -ED=$1 -[ ! -x $ED ] && { echo "$ED: cannot execute"; exit 1; } - -# Run the *.red scripts first, since these don't generate output; -# they exit with non-zero status -for i in *.red; do - echo $i - if $i; then - echo "*** The script $i exited abnormally ***" - fi -done >errs.o 2>&1 - -# Run the remainding scripts; they exit with zero status -for i in *.ed; do -# base=`expr $i : '\([^.]*\)'` -# base=`echo $i | sed 's/\..*//'` - base=`$ED - \!"echo $i" <<-EOF - s/\..* - EOF` - if $base.ed; then - if cmp -s $base.o $base.r; then :; else - echo "*** Output $base.o of script $i is incorrect ***" - fi - else - echo "*** The script $i exited abnormally ***" - fi -done >scripts.o 2>&1 - -grep -h '\*\*\*' errs.o scripts.o diff --git a/bin/ed/test/mkscripts.sh b/bin/ed/test/mkscripts.sh deleted file mode 100755 index 5e1a09527..000000000 --- a/bin/ed/test/mkscripts.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/sh - -# $NetBSD: mkscripts.sh,v 1.10 1995/04/23 10:07:36 cgd Exp $ -# -# This script generates ed test scripts (.ed) from .t files - -PATH="/bin:/usr/bin:/usr/local/bin/:." -ED=$1 -[ ! -x $ED ] && { echo "$ED: cannot execute"; exit 1; } - -for i in *.t; do -# base=${i%.*} -# base=`echo $i | sed 's/\..*//'` -# base=`expr $i : '\([^.]*\)'` -# ( -# echo "#!/bin/sh -" -# echo "$ED - <<\EOT" -# echo "r $base.d" -# cat $i -# echo "w $base.o" -# echo EOT -# ) >$base.ed -# chmod +x $base.ed -# The following is pretty ugly way of doing the above, and not appropriate -# use of ed but the point is that it can be done... - base=`$ED - \!"echo $i" <<-EOF - s/\..* - EOF` - $ED - <<-EOF - a - #!/bin/sh - - $ED - <<\EOT - H - r $base.d - w $base.o - EOT - . - -2r $i - w $base.ed - !chmod +x $base.ed - EOF -done - -for i in *.err; do -# base=${i%.*} -# base=`echo $i | sed 's/\..*//'` -# base=`expr $i : '\([^.]*\)'` -# ( -# echo "#!/bin/sh -" -# echo "$ED - <<\EOT" -# echo H -# echo "r $base.err" -# cat $i -# echo "w $base.o" -# echo EOT -# ) >$base-err.ed -# chmod +x $base-err.ed -# The following is pretty ugly way of doing the above, and not appropriate -# use of ed but the point is that it can be done... - base=`$ED - \!"echo $i" <<-EOF - s/\..* - EOF` - $ED - <<-EOF - a - #!/bin/sh - - $ED - <<\EOT - H - r $base.err - w $base.o - EOT - . - -2r $i - w ${base}.red - !chmod +x ${base}.red - EOF -done diff --git a/bin/ed/undo.c b/bin/ed/undo.c deleted file mode 100644 index c754873a9..000000000 --- a/bin/ed/undo.c +++ /dev/null @@ -1,158 +0,0 @@ -/* $NetBSD: undo.c,v 1.6 2014/03/23 05:06:42 dholland Exp $ */ - -/* undo.c: This file contains the undo routines for the ed line editor */ -/*- - * Copyright (c) 1993 Andrew Moore, Talke Studio. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char *rcsid = "@(#)undo.c,v 1.1 1994/02/01 00:34:44 alm Exp"; -#else -__RCSID("$NetBSD: undo.c,v 1.6 2014/03/23 05:06:42 dholland Exp $"); -#endif -#endif /* not lint */ - -#include "ed.h" - - -#define USIZE 100 /* undo stack size */ -undo_t *ustack = NULL; /* undo stack */ -long usize = 0; /* stack size variable */ -long u_p = 0; /* undo stack pointer */ - -/* push_undo_stack: return pointer to initialized undo node */ -undo_t * -push_undo_stack(int type, long from, long to) -{ - undo_t *t; - -#if defined(sun) || defined(NO_REALLOC_NULL) - if (ustack == NULL && - (ustack = (undo_t *) malloc((usize = USIZE) * sizeof(undo_t))) == NULL) { - fprintf(stderr, "%s\n", strerror(errno)); - seterrmsg("out of memory"); - return NULL; - } -#endif - t = ustack; - if (u_p < usize || - (t = (undo_t *) realloc(ustack, (usize += USIZE) * sizeof(undo_t))) != NULL) { - ustack = t; - ustack[u_p].type = type; - ustack[u_p].t = get_addressed_line_node(to); - ustack[u_p].h = get_addressed_line_node(from); - return ustack + u_p++; - } - /* out of memory - release undo stack */ - fprintf(stderr, "%s\n", strerror(errno)); - seterrmsg("out of memory"); - clear_undo_stack(); - free(ustack); - ustack = NULL; - usize = 0; - return NULL; -} - - -/* USWAP: swap undo nodes */ -#define USWAP(x,y) { \ - undo_t utmp; \ - utmp = x, x = y, y = utmp; \ -} - - -long u_current_addr = -1; /* if >= 0, undo enabled */ -long u_addr_last = -1; /* if >= 0, undo enabled */ - -/* pop_undo_stack: undo last change to the editor buffer */ -int -pop_undo_stack(void) -{ - long n; - long o_current_addr = current_addr; - long o_addr_last = addr_last; - - if (u_current_addr == -1 || u_addr_last == -1) { - seterrmsg("nothing to undo"); - return ERR; - } else if (u_p) - modified = 1; - get_addressed_line_node(0); /* this get_addressed_line_node last! */ - SPL1(); - for (n = u_p; n-- > 0;) { - switch(ustack[n].type) { - case UADD: - REQUE(ustack[n].h->q_back, ustack[n].t->q_forw); - break; - case UDEL: - REQUE(ustack[n].h->q_back, ustack[n].h); - REQUE(ustack[n].t, ustack[n].t->q_forw); - break; - case UMOV: - case VMOV: - REQUE(ustack[n - 1].h, ustack[n].h->q_forw); - REQUE(ustack[n].t->q_back, ustack[n - 1].t); - REQUE(ustack[n].h, ustack[n].t); - n--; - break; - default: - /*NOTREACHED*/ - ; - } - ustack[n].type ^= 1; - } - /* reverse undo stack order */ - for (n = u_p; n-- > (u_p + 1)/ 2;) - USWAP(ustack[n], ustack[u_p - 1 - n]); - if (isglobal) - clear_active_list(); - current_addr = u_current_addr, u_current_addr = o_current_addr; - addr_last = u_addr_last, u_addr_last = o_addr_last; - SPL0(); - return 0; -} - - -/* clear_undo_stack: clear the undo stack */ -void -clear_undo_stack(void) -{ - line_t *lp, *ep, *tl; - - while (u_p--) - if (ustack[u_p].type == UDEL) { - ep = ustack[u_p].t->q_forw; - for (lp = ustack[u_p].h; lp != ep; lp = tl) { - unmark_line_node(lp); - tl = lp->q_forw; - free(lp); - } - } - u_p = 0; - u_current_addr = current_addr; - u_addr_last = addr_last; -} diff --git a/bin/expr/Makefile b/bin/expr/Makefile deleted file mode 100644 index 7c7612fca..000000000 --- a/bin/expr/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# $NetBSD: Makefile,v 1.14 2000/09/19 17:20:00 jdolecek Exp $ - -PROG= expr -SRCS= expr.y - -.include diff --git a/bin/expr/expr.1 b/bin/expr/expr.1 deleted file mode 100644 index dcfcc8719..000000000 --- a/bin/expr/expr.1 +++ /dev/null @@ -1,280 +0,0 @@ -.\" $NetBSD: expr.1,v 1.36 2016/08/23 20:34:23 sevan Exp $ -.\" -.\" Copyright (c) 2000,2003 The NetBSD Foundation, Inc. -.\" All rights reserved. -.\" -.\" This code is derived from software contributed to The NetBSD Foundation -.\" by J.T. Conklin and Jaromir Dolecek . -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS -.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS -.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -.\" POSSIBILITY OF SUCH DAMAGE. -.\" -.Dd August 23, 2016 -.Dt EXPR 1 -.Os -.Sh NAME -.Nm expr -.Nd evaluate expression -.Sh SYNOPSIS -.Nm -.Ar expression -.Sh DESCRIPTION -The -.Nm -utility evaluates -.Ar expression -and writes the result on standard output. -.Pp -All operators are separate arguments to the -.Nm -utility. -Characters special to the command interpreter must be escaped. -.Pp -Operators are listed below in order of increasing precedence. -Operators with equal precedence are grouped within { } symbols. -.Bl -tag -width indent -.It Ar expr1 Li \&| Ar expr2 -Returns the evaluation of -.Ar expr1 -if it is neither an empty string nor zero; -otherwise, returns the evaluation of -.Ar expr2 . -.It Ar expr1 Li \*[Am] Ar expr2 -Returns the evaluation of -.Ar expr1 -if neither expression evaluates to an empty string or zero; -otherwise, returns zero. -.It Ar expr1 Li "{=, \*[Gt], \*[Ge], \*[Lt], \*[Le], !=}" Ar expr2 -Returns the results of integer comparison if both arguments are integers; -otherwise, returns the results of string comparison using the locale-specific -collation sequence. -The result of each comparison is 1 if the specified relation is true, -or 0 if the relation is false. -.It Ar expr1 Li "{+, -}" Ar expr2 -Returns the results of addition or subtraction of integer-valued arguments. -.It Ar expr1 Li "{*, /, %}" Ar expr2 -Returns the results of multiplication, integer division, or remainder of integer-valued arguments. -.It Ar expr1 Li \&: Ar expr2 -The -.Dq \&: -operator matches -.Ar expr1 -against -.Ar expr2 , -which must be a regular expression. -The regular expression is anchored -to the beginning of the string with an implicit -.Dq ^ . -.Pp -If the match succeeds and the pattern contains at least one regular -expression subexpression -.Dq "\e(...\e)" , -the string corresponding to -.Dq "\e1" -is returned; -otherwise the matching operator returns the number of characters matched. -If the match fails and the pattern contains a regular expression subexpression -the null string is returned; -otherwise 0. -.It "( " Ar expr No " )" -Parentheses are used for grouping in the usual manner. -.El -.Pp -Additionally, the following keywords are recognized: -.Bl -tag -width indent -.It length Ar expr -Returns the length of the specified string in bytes. -.El -.Pp -Operator precedence (from highest to lowest): -.Bl -enum -compact -offset indent -.It -parentheses -.It -length -.It -.Dq \&: -.It -.Dq "*" , -.Dq "/" , -and -.Dq "%" -.It -.Dq "+" -and -.Dq "-" -.It -compare operators -.It -.Dq \*[Am] -.It -.Dq \&| -.El -.Sh EXIT STATUS -The -.Nm -utility exits with one of the following values: -.Bl -tag -width Ds -compact -.It 0 -the expression is neither an empty string nor 0. -.It 1 -the expression is an empty string or 0. -.It 2 -the expression is invalid. -.It \*[Gt]2 -an error occurred (such as memory allocation failure). -.El -.Sh EXAMPLES -.Bl -enum -.It -The following example adds one to variable -.Dq a : -.Dl a=`expr $a + 1` -.It -The following example returns zero, due to subtraction having higher precedence -than the -.Dq \*[Am] -operator: -.Dl expr 1 '\*[Am]' 1 - 1 -.It -The following example returns the filename portion of a pathname stored -in variable -.Dq a : -.Dl expr "/$a" Li : '.*/\e(.*\e)' -.It -The following example returns the number of characters in variable -.Dq a : -.Dl expr $a Li : '.*' -.El -.Sh COMPATIBILITY -This implementation of -.Nm -internally uses 64 bit representation of integers and checks for -over- and underflows. -It also treats -.Dq / -(the division mark) and option -.Dq -- -correctly depending upon context. -.Pp -.Nm -on other systems (including -.Nx -up to and including -.Nx 1.5 ) -might not be so graceful. -Arithmetic results might be arbitrarily -limited on such systems, most commonly to 32 bit quantities. -This means such -.Nm -can only process values between -2147483648 and +2147483647. -.Pp -On other systems, -.Nm -might also not work correctly for regular expressions where -either side contains -.Dq / -(a single forward slash), like this: -.Bd -literal -offset indent -expr / : '.*/\e(.*\e)' -.Ed -.Pp -If this is the case, you might use -.Dq // -(a double forward slash) -to avoid confusion with the division operator: -.Bd -literal -offset indent -expr "//$a" : '.*/\e(.*\e)' -.Ed -.Pp -According to -.St -p1003.2 , -.Nm -has to recognize special option -.Dq -- , -treat it as a delimiter to mark the end of command -line options, and ignore it. -Some -.Nm -implementations do not recognize it at all; others -might ignore it even in cases where doing so results in syntax -error. -There should be same result for both following examples, -but it might not always be: -.Bl -enum -compact -offset indent -.It -expr -- : . -.It -expr -- -- : . -.El -Although -.Nx -.Nm -handles both cases correctly, you should not depend on this behavior -for portability reasons and avoid passing a bare -.Dq -- -as the first -argument. -.Sh STANDARDS -The -.Nm -utility conforms to -.St -p1003.2 . -The -.Ar length -keyword is an extension for compatibility with GNU -.Nm . -.Sh HISTORY -An -.Nm -utility first appeared in the Programmer's Workbench (PWB/UNIX). -A public domain version of -.Nm -written by -.An Pace Willisson -.Aq pace@blitz.com -appeared in -.Bx 386 0.1 . -.Sh AUTHORS -Initial implementation by -.An Pace Willisson Aq Mt pace@blitz.com -was largely rewritten by -.An -nosplit -.An J.T. Conklin Aq Mt jtc@NetBSD.org . -It was rewritten again for -.Nx 1.6 -by -.An -nosplit -.An Jaromir Dolecek Aq Mt jdolecek@NetBSD.org . -.Sh NOTES -The empty string -.Do Dc -cannot be matched with the intuitive: -.Bd -literal -offset indent -expr '' : '$' -.Ed -.Pp -The reason is that the returned number of matched characters (zero) -is indistinguishable from a failed match, so this returns failure. -To match the empty string, use something like: -.Bd -literal -offset indent -expr x'' : 'x$' -.Ed diff --git a/bin/expr/expr.y b/bin/expr/expr.y deleted file mode 100644 index 4efcf59ef..000000000 --- a/bin/expr/expr.y +++ /dev/null @@ -1,457 +0,0 @@ -/* $NetBSD: expr.y,v 1.39 2016/09/05 01:00:07 sevan Exp $ */ - -/*_ - * Copyright (c) 2000 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jaromir Dolecek and J.T. Conklin . - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -%{ -#include -#ifndef lint -__RCSID("$NetBSD: expr.y,v 1.39 2016/09/05 01:00:07 sevan Exp $"); -#endif /* not lint */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static const char * const *av; - -static void yyerror(const char *, ...) __dead; -static int yylex(void); -static int is_zero_or_null(const char *); -static int is_integer(const char *); -static int64_t perform_arith_op(const char *, const char *, const char *); - -#define YYSTYPE const char * - -%} -%token STRING -%left SPEC_OR -%left SPEC_AND -%left COMPARE -%left ADD_SUB_OPERATOR -%left MUL_DIV_MOD_OPERATOR -%left SPEC_REG -%left LENGTH -%left LEFT_PARENT RIGHT_PARENT - -%% - -exp: expr = { - (void) printf("%s\n", $1); - return (is_zero_or_null($1)); - } - ; - -expr: item { $$ = $1; } - | expr SPEC_OR expr = { - /* - * Return evaluation of first expression if it is neither - * an empty string nor zero; otherwise, returns the evaluation - * of second expression. - */ - if (!is_zero_or_null($1)) - $$ = $1; - else - $$ = $3; - } - | expr SPEC_AND expr = { - /* - * Returns the evaluation of first expr if neither expression - * evaluates to an empty string or zero; otherwise, returns - * zero. - */ - if (!is_zero_or_null($1) && !is_zero_or_null($3)) - $$ = $1; - else - $$ = "0"; - } - | expr SPEC_REG expr = { - /* - * The ``:'' operator matches first expr against the second, - * which must be a regular expression. - */ - regex_t rp; - regmatch_t rm[2]; - int eval; - - /* compile regular expression */ - if ((eval = regcomp(&rp, $3, REG_BASIC)) != 0) { - char errbuf[256]; - (void)regerror(eval, &rp, errbuf, sizeof(errbuf)); - yyerror("%s", errbuf); - /* NOT REACHED */ - } - - /* compare string against pattern -- remember that patterns - are anchored to the beginning of the line */ - if (regexec(&rp, $1, 2, rm, 0) == 0 && rm[0].rm_so == 0) { - char *val; - if (rm[1].rm_so >= 0) { - (void) asprintf(&val, "%.*s", - (int) (rm[1].rm_eo - rm[1].rm_so), - $1 + rm[1].rm_so); - } else { - (void) asprintf(&val, "%d", - (int)(rm[0].rm_eo - rm[0].rm_so)); - } - if (val == NULL) - err(1, NULL); - $$ = val; - } else { - if (rp.re_nsub == 0) { - $$ = "0"; - } else { - $$ = ""; - } - } - - } - | expr ADD_SUB_OPERATOR expr = { - /* Returns the results of addition, subtraction */ - char *val; - int64_t res; - - res = perform_arith_op($1, $2, $3); - (void) asprintf(&val, "%lld", (long long int) res); - if (val == NULL) - err(1, NULL); - $$ = val; - } - - | expr MUL_DIV_MOD_OPERATOR expr = { - /* - * Returns the results of multiply, divide or remainder of - * numeric-valued arguments. - */ - char *val; - int64_t res; - - res = perform_arith_op($1, $2, $3); - (void) asprintf(&val, "%lld", (long long int) res); - if (val == NULL) - err(1, NULL); - $$ = val; - - } - | expr COMPARE expr = { - /* - * Returns the results of integer comparison if both arguments - * are integers; otherwise, returns the results of string - * comparison using the locale-specific collation sequence. - * The result of each comparison is 1 if the specified relation - * is true, or 0 if the relation is false. - */ - - int64_t l, r; - int res; - - res = 0; - - /* - * Slight hack to avoid differences in the compare code - * between string and numeric compare. - */ - if (is_integer($1) && is_integer($3)) { - /* numeric comparison */ - l = strtoll($1, NULL, 10); - r = strtoll($3, NULL, 10); - } else { - /* string comparison */ - l = strcoll($1, $3); - r = 0; - } - - switch($2[0]) { - case '=': /* equal */ - res = (l == r); - break; - case '>': /* greater or greater-equal */ - if ($2[1] == '=') - res = (l >= r); - else - res = (l > r); - break; - case '<': /* lower or lower-equal */ - if ($2[1] == '=') - res = (l <= r); - else - res = (l < r); - break; - case '!': /* not equal */ - /* the check if this is != was done in yylex() */ - res = (l != r); - } - - $$ = (res) ? "1" : "0"; - - } - | LEFT_PARENT expr RIGHT_PARENT { $$ = $2; } - | LENGTH expr { - /* - * Return length of 'expr' in bytes. - */ - char *ln; - - asprintf(&ln, "%ld", (long) strlen($2)); - if (ln == NULL) - err(1, NULL); - $$ = ln; - } - ; - -item: STRING - | ADD_SUB_OPERATOR - | MUL_DIV_MOD_OPERATOR - | COMPARE - | SPEC_OR - | SPEC_AND - | SPEC_REG - | LENGTH - ; -%% - -/* - * Returns 1 if the string is empty or contains only numeric zero. - */ -static int -is_zero_or_null(const char *str) -{ - char *endptr; - - return str[0] == '\0' - || ( strtoll(str, &endptr, 10) == 0LL - && endptr[0] == '\0'); -} - -/* - * Returns 1 if the string is an integer. - */ -static int -is_integer(const char *str) -{ - char *endptr; - - (void) strtoll(str, &endptr, 10); - /* note we treat empty string as valid number */ - return (endptr[0] == '\0'); -} - -static int64_t -perform_arith_op(const char *left, const char *op, const char *right) -{ - int64_t res, sign, l, r; - u_int64_t temp; - - res = 0; - - if (!is_integer(left)) { - yyerror("non-integer argument '%s'", left); - /* NOTREACHED */ - } - if (!is_integer(right)) { - yyerror("non-integer argument '%s'", right); - /* NOTREACHED */ - } - - errno = 0; - l = strtoll(left, NULL, 10); - if (errno == ERANGE) { - yyerror("value '%s' is %s is %lld", left, - (l > 0) ? "too big, maximum" : "too small, minimum", - (l > 0) ? LLONG_MAX : LLONG_MIN); - /* NOTREACHED */ - } - - errno = 0; - r = strtoll(right, NULL, 10); - if (errno == ERANGE) { - yyerror("value '%s' is %s is %lld", right, - (l > 0) ? "too big, maximum" : "too small, minimum", - (l > 0) ? LLONG_MAX : LLONG_MIN); - /* NOTREACHED */ - } - - switch(op[0]) { - case '+': - /* - * Do the op into an unsigned to avoid overflow and then cast - * back to check the resulting signage. - */ - temp = l + r; - res = (int64_t) temp; - /* very simplistic check for over-& underflow */ - if ((res < 0 && l > 0 && r > 0) - || (res > 0 && l < 0 && r < 0)) - yyerror("integer overflow or underflow occurred for " - "operation '%s %s %s'", left, op, right); - break; - case '-': - /* - * Do the op into an unsigned to avoid overflow and then cast - * back to check the resulting signage. - */ - temp = l - r; - res = (int64_t) temp; - /* very simplistic check for over-& underflow */ - if ((res < 0 && l > 0 && l > r) - || (res > 0 && l < 0 && l < r) ) - yyerror("integer overflow or underflow occurred for " - "operation '%s %s %s'", left, op, right); - break; - case '/': - if (r == 0) - yyerror("second argument to '%s' must not be zero", op); - res = l / r; - - break; - case '%': - if (r == 0) - yyerror("second argument to '%s' must not be zero", op); - res = l % r; - break; - case '*': - /* shortcut */ - if ((l == 0) || (r == 0)) { - res = 0; - break; - } - - sign = 1; - if (l < 0) - sign *= -1; - if (r < 0) - sign *= -1; - - res = l * r; - /* - * XXX: not the most portable but works on anything with 2's - * complement arithmetic. If the signs don't match or the - * result was 0 on 2's complement this overflowed. - */ - if ((res < 0 && sign > 0) || (res > 0 && sign < 0) || - (res == 0)) - yyerror("integer overflow or underflow occurred for " - "operation '%s %s %s'", left, op, right); - /* NOTREACHED */ - break; - } - return res; -} - -static const char *x = "|&=<>+-*/%:()"; -static const int x_token[] = { - SPEC_OR, SPEC_AND, COMPARE, COMPARE, COMPARE, ADD_SUB_OPERATOR, - ADD_SUB_OPERATOR, MUL_DIV_MOD_OPERATOR, MUL_DIV_MOD_OPERATOR, - MUL_DIV_MOD_OPERATOR, SPEC_REG, LEFT_PARENT, RIGHT_PARENT -}; - -static int handle_ddash = 1; - -int -yylex(void) -{ - const char *p = *av++; - int retval; - - if (!p) - retval = 0; - else if (p[1] == '\0') { - const char *w = strchr(x, p[0]); - if (w) { - retval = x_token[w-x]; - } else { - retval = STRING; - } - } else if (p[1] == '=' && p[2] == '\0' - && (p[0] == '>' || p[0] == '<' || p[0] == '!')) - retval = COMPARE; - else if (handle_ddash && p[0] == '-' && p[1] == '-' && p[2] == '\0') { - /* ignore "--" if passed as first argument and isn't followed - * by another STRING */ - retval = yylex(); - if (retval != STRING && retval != LEFT_PARENT - && retval != RIGHT_PARENT) { - /* is not followed by string or parenthesis, use as - * STRING */ - retval = STRING; - av--; /* was increased in call to yylex() above */ - p = "--"; - } else { - /* "--" is to be ignored */ - p = yylval; - } - } else if (strcmp(p, "length") == 0) - retval = LENGTH; - else - retval = STRING; - - handle_ddash = 0; - yylval = p; - - return retval; -} - -/* - * Print error message and exit with error 2 (syntax error). - */ -static __printflike(1, 2) void -yyerror(const char *fmt, ...) -{ - va_list arg; - - va_start(arg, fmt); - verrx(2, fmt, arg); - va_end(arg); -} - -int -main(int argc, const char * const *argv) -{ - setprogname(argv[0]); - (void)setlocale(LC_ALL, ""); - - if (argc == 1) { - (void)fprintf(stderr, "usage: %s expression\n", - getprogname()); - exit(2); - } - - av = argv + 1; - - exit(yyparse()); - /* NOTREACHED */ -} diff --git a/bin/hostname/Makefile b/bin/hostname/Makefile deleted file mode 100644 index 665543219..000000000 --- a/bin/hostname/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# $NetBSD: Makefile,v 1.8 1997/07/20 22:37:07 christos Exp $ -# @(#)Makefile 8.1 (Berkeley) 5/31/93 - -PROG= hostname - -.include diff --git a/bin/hostname/hostname.1 b/bin/hostname/hostname.1 deleted file mode 100644 index 6b7f39169..000000000 --- a/bin/hostname/hostname.1 +++ /dev/null @@ -1,65 +0,0 @@ -.\" $NetBSD: hostname.1,v 1.20 2014/02/13 12:00:29 elric Exp $ -.\" -.\" Copyright (c) 1983, 1988, 1990, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)hostname.1 8.2 (Berkeley) 4/28/95 -.\" -.Dd April 28, 1995 -.Dt HOSTNAME 1 -.Os -.Sh NAME -.Nm hostname -.Nd set or print name of current host system -.Sh SYNOPSIS -.Nm -.Op Fl s -.Op Ar name-of-host -.Sh DESCRIPTION -.Nm -prints the name of the current host. -The super-user can set the host name by supplying an argument; this is -usually done in the network initialization script -.Pa /etc/rc.d/network , -normally run at boot -time. -.Pp -Options: -.Bl -tag -width flag -.It Fl s -Trims off any domain information from the printed -name. -.El -.Sh SEE ALSO -.Xr domainname 1 , -.Xr gethostname 3 , -.Xr sethostname 3 -.Sh HISTORY -The -.Nm -utility appeared in -.Bx 4.2 . diff --git a/bin/hostname/hostname.c b/bin/hostname/hostname.c deleted file mode 100644 index 66363a8ca..000000000 --- a/bin/hostname/hostname.c +++ /dev/null @@ -1,101 +0,0 @@ -/* $NetBSD: hostname.c,v 1.21 2014/02/13 12:00:29 elric Exp $ */ - -/* - * Copyright (c) 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1988, 1993\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)hostname.c 8.2 (Berkeley) 4/28/95"; -#else -__RCSID("$NetBSD: hostname.c,v 1.21 2014/02/13 12:00:29 elric Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include -#include -#include -#include - -__dead static void usage(void); - -int -main(int argc, char *argv[]) -{ - int ch, sflag; - char *p, hostname[MAXHOSTNAMELEN + 1]; - - setprogname(argv[0]); - sflag = 0; - while ((ch = getopt(argc, argv, "s")) != -1) - switch (ch) { - case 's': - sflag = 1; - break; - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc > 1) - usage(); - - if (*argv) { - if (sethostname(*argv, strlen(*argv))) - err(1, "sethostname"); - } else { - if (gethostname(hostname, sizeof(hostname))) - err(1, "gethostname"); - hostname[sizeof(hostname) - 1] = '\0'; - if (sflag && (p = strchr(hostname, '.'))) - *p = '\0'; - (void)printf("%s\n", hostname); - } - exit(0); - /* NOTREACHED */ -} - -static void -usage(void) -{ - (void)fprintf(stderr, "usage: %s [-s] [name-of-host]\n", - getprogname()); - exit(1); - /* NOTREACHED */ -} diff --git a/bin/kill/Makefile b/bin/kill/Makefile deleted file mode 100644 index c2b60979b..000000000 --- a/bin/kill/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# $NetBSD: Makefile,v 1.8 1997/07/20 22:37:09 christos Exp $ -# @(#)Makefile 8.1 (Berkeley) 5/31/93 - -PROG= kill - -.include diff --git a/bin/kill/kill.1 b/bin/kill/kill.1 deleted file mode 100644 index 86b05fdd5..000000000 --- a/bin/kill/kill.1 +++ /dev/null @@ -1,156 +0,0 @@ -.\" $NetBSD: kill.1,v 1.28 2017/04/22 23:01:36 christos Exp $ -.\" -.\" Copyright (c) 1980, 1990, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Institute of Electrical and Electronics Engineers, Inc. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)kill.1 8.2 (Berkeley) 4/28/95 -.\" -.Dd April 22, 2017 -.Dt KILL 1 -.Os -.Sh NAME -.Nm kill -.Nd terminate or signal a process -.Sh SYNOPSIS -.Nm -.Op Fl s Ar signal_name -.Ar pid -\&... -.Nm -.Fl l -.Op Ar exit_status -.Nm -.Fl signal_name -.Ar pid -\&... -.Nm -.Fl signal_number -.Ar pid -\&... -.Sh DESCRIPTION -The -.Nm -utility sends a signal to the process(es) specified -by the pid operand(s). -.Pp -Only the super-user may send signals to other users' processes. -.Pp -The options are as follows: -.Bl -tag -width Ds -.It Fl s Ar signal_name -A symbolic signal name specifying the signal to be sent instead of the -default -.Dv TERM . -.It Fl l Op Ar exit_status -Display the name of the signal corresponding to -.Ar exit_status . -.Ar exit_status -may be the exit status of a command killed by a signal -(see the -special -.Xr sh 1 -parameter -.Sq ?\& ) -or a signal number. -.Pp -If no operand is given, display the names of all the signals. -.It Fl signal_name -A symbolic signal name specifying the signal to be sent instead of the -default -.Dv TERM . -.It Fl signal_number -A non-negative decimal integer, specifying the signal to be sent instead -of the default -.Dv TERM . -.El -.Pp -The following pids have special meanings: -.Bl -tag -width Ds -compact -.It -1 -If superuser, broadcast the signal to all processes; otherwise broadcast -to all processes belonging to the user. -.It 0 -Broadcast the signal to all processes in the current process group -belonging to the user. -.El -.Pp -Some of the more commonly used signals: -.Bl -tag -width Ds -compact -.It 0 -0 (does not affect the process; can be used to test whether the -process exists) -.It 1 -HUP (hang up) -.It 2 -INT (interrupt) -.It 3 -QUIT (quit) -.It 6 -ABRT (abort) -.It 9 -KILL (non-catchable, non-ignorable kill) -.It 14 -ALRM (alarm clock) -.It 15 -TERM (software termination signal) -.El -.Pp -.Nm -is a built-in to -.Xr csh 1 ; -it allows job specifiers of the form ``%...'' as arguments -so process id's are not as often used as -.Nm -arguments. -See -.Xr csh 1 -for details. -.Sh DIAGNOSTICS -.Ex -std -.Sh SEE ALSO -.Xr csh 1 , -.Xr pgrep 1 , -.Xr pkill 1 , -.Xr ps 1 , -.Xr kill 2 , -.Xr sigaction 2 , -.Xr signal 7 -.Sh STANDARDS -The -.Nm -utility is expected to be -.St -p1003.2 -compatible. -.Sh HISTORY -A -.Nm -command appeared in -.At v3 -in section 8 of the manual. diff --git a/bin/kill/kill.c b/bin/kill/kill.c deleted file mode 100644 index 059257795..000000000 --- a/bin/kill/kill.c +++ /dev/null @@ -1,253 +0,0 @@ -/* $NetBSD: kill.c,v 1.27 2011/08/29 14:51:18 joerg Exp $ */ - -/* - * Copyright (c) 1988, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#if !defined(lint) && !defined(SHELL) -__COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)kill.c 8.4 (Berkeley) 4/28/95"; -#else -__RCSID("$NetBSD: kill.c,v 1.27 2011/08/29 14:51:18 joerg Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef SHELL /* sh (aka ash) builtin */ -int killcmd(int, char *argv[]); -#define main killcmd -#include "../../bin/sh/bltin/bltin.h" -#endif /* SHELL */ - -__dead static void nosig(char *); -static void printsignals(FILE *); -static int signame_to_signum(char *); -__dead static void usage(void); - -int -main(int argc, char *argv[]) -{ - int errors; - intmax_t numsig, pid; - char *ep; - - setprogname(argv[0]); - setlocale(LC_ALL, ""); - if (argc < 2) - usage(); - - numsig = SIGTERM; - - argc--, argv++; - if (strcmp(*argv, "-l") == 0) { - argc--, argv++; - if (argc > 1) - usage(); - if (argc == 1) { - if (isdigit((unsigned char)**argv) == 0) - usage(); - numsig = strtoimax(*argv, &ep, 10); - /* check for correctly parsed number */ - if (*ep != '\0' || numsig == INTMAX_MIN || numsig == INTMAX_MAX) { - errx(EXIT_FAILURE, "illegal signal number: %s", - *argv); - /* NOTREACHED */ - } - if (numsig >= 128) - numsig -= 128; - /* and whether it fits into signals range */ - if (numsig <= 0 || numsig >= NSIG) - nosig(*argv); - printf("%s\n", sys_signame[(int) numsig]); - exit(0); - } - printsignals(stdout); - exit(0); - } - - if (!strcmp(*argv, "-s")) { - argc--, argv++; - if (argc < 1) { - warnx("option requires an argument -- s"); - usage(); - } - if (strcmp(*argv, "0")) { - if ((numsig = signame_to_signum(*argv)) < 0) - nosig(*argv); - } else - numsig = 0; - argc--, argv++; - } else if (**argv == '-') { - char *sn = *argv + 1; - if (isalpha((unsigned char)*sn)) { - if ((numsig = signame_to_signum(sn)) < 0) - nosig(sn); - } else if (isdigit((unsigned char)*sn)) { - numsig = strtoimax(sn, &ep, 10); - /* check for correctly parsed number */ - if (*ep || numsig == INTMAX_MIN || numsig == INTMAX_MAX ) { - errx(EXIT_FAILURE, "illegal signal number: %s", - sn); - /* NOTREACHED */ - } - /* and whether it fits into signals range */ - if (numsig < 0 || numsig >= NSIG) - nosig(sn); - } else - nosig(sn); - argc--, argv++; - } - - if (argc == 0) - usage(); - - for (errors = 0; argc; argc--, argv++) { -#ifdef SHELL - extern int getjobpgrp(const char *); - if (*argv[0] == '%') { - pid = getjobpgrp(*argv); - if (pid == 0) { - warnx("illegal job id: %s", *argv); - errors = 1; - continue; - } - } else -#endif - { - pid = strtoimax(*argv, &ep, 10); - /* make sure the pid is a number and fits into pid_t */ - if (!**argv || *ep || pid == INTMAX_MIN || - pid == INTMAX_MAX || pid != (pid_t) pid) { - - warnx("illegal process id: %s", *argv); - errors = 1; - continue; - } - } - if (kill((pid_t) pid, (int) numsig) == -1) { - warn("%s", *argv); - errors = 1; - } -#ifdef SHELL - /* Wakeup the process if it was suspended, so it can - exit without an explicit 'fg'. */ - if (numsig == SIGTERM || numsig == SIGHUP) - kill((pid_t) pid, SIGCONT); -#endif - } - - exit(errors); - /* NOTREACHED */ -} - -static int -signame_to_signum(char *sig) -{ - int n; - - if (strncasecmp(sig, "sig", 3) == 0) - sig += 3; - for (n = 1; n < NSIG; n++) { - if (!strcasecmp(sys_signame[n], sig)) - return (n); - } - return (-1); -} - -static void -nosig(char *name) -{ - - warnx("unknown signal %s; valid signals:", name); - printsignals(stderr); - exit(1); - /* NOTREACHED */ -} - -static void -printsignals(FILE *fp) -{ - int sig; - int len, nl; - const char *name; - int termwidth = 80; - - if (isatty(fileno(fp))) { - struct winsize win; - if (ioctl(fileno(fp), TIOCGWINSZ, &win) == 0 && win.ws_col > 0) - termwidth = win.ws_col; - } - - for (len = 0, sig = 1; sig < NSIG; sig++) { - name = sys_signame[sig]; - nl = 1 + strlen(name); - - if (len + nl >= termwidth) { - fprintf(fp, "\n"); - len = 0; - } else - if (len != 0) - fprintf(fp, " "); - len += nl; - fprintf(fp, "%s", name); - } - if (len != 0) - fprintf(fp, "\n"); -} - -static void -usage(void) -{ - - fprintf(stderr, "usage: %s [-s signal_name] pid ...\n" - " %s -l [exit_status]\n" - " %s -signal_name pid ...\n" - " %s -signal_number pid ...\n", - getprogname(), getprogname(), getprogname(), getprogname()); - exit(1); - /* NOTREACHED */ -} diff --git a/bin/ksh/Makefile b/bin/ksh/Makefile deleted file mode 100644 index f2465a345..000000000 --- a/bin/ksh/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -# $NetBSD: Makefile,v 1.31 2015/01/29 20:46:31 joerg Exp $ - -WARNS=3 -CWARNFLAGS.clang+= -Wno-error=cast-qual - -.include - -CPPFLAGS+= -I. - -PROG= ksh -SRCS= alloc.c c_ksh.c c_sh.c c_test.c c_ulimit.c edit.c emacs.c \ - eval.c exec.c expr.c history.c io.c jobs.c lex.c mail.c \ - main.c misc.c path.c shf.c sigact.c syn.c table.c trap.c \ - tree.c tty.c var.c version.c vi.c -DPSRCS= emacs.out siglist.out -.if (${MKMAN} != "no") -DPSRCS+=ksh.1 -.endif - -# needs tbl for the man page. -USETBL= - -# Environment for scripts executed during build. -SCRIPT_ENV= \ - AWK=${TOOL_AWK:Q} \ - SED=${TOOL_SED:Q} - -CLEANFILES+= siglist.out siglist.out.tmp -# two steps to prevent the creation of a bogus siglist.out -siglist.out: config.h sh.h siglist.in siglist.sh - ${_MKTARGET_CREATE} - ${SCRIPT_ENV} \ - ${HOST_SH} $(.CURDIR)/siglist.sh "$(CC) -E $(CPPFLAGS) $(DEFS) -I. -I$(.CURDIR)" < $(.CURDIR)/siglist.in > siglist.out.tmp \ - && mv siglist.out.tmp siglist.out - -# two steps to prevent the creation of a bogus emacs.out -CLEANFILES+= emacs.out emacs.out.tmp -emacs.out: emacs.c - ${_MKTARGET_CREATE} - ${SCRIPT_ENV} \ - ${HOST_SH} $(.CURDIR)/emacs-gen.sh $(.CURDIR)/emacs.c > emacs.out.tmp \ - && mv emacs.out.tmp emacs.out - -CLEANFILES+= ksh.1 ksh.1.tmp -ksh.1: ksh.Man mkman - ${_MKTARGET_CREATE} - ${SCRIPT_ENV} \ - ${HOST_SH} $(.CURDIR)/mkman ksh $(.CURDIR)/ksh.Man >ksh.1.tmp \ - && mv ksh.1.tmp ksh.1 - -.include diff --git a/bin/ksh/alloc.c b/bin/ksh/alloc.c deleted file mode 100644 index 31f233041..000000000 --- a/bin/ksh/alloc.c +++ /dev/null @@ -1,127 +0,0 @@ -/* $NetBSD: alloc.c,v 1.10 2007/12/12 22:55:42 lukem Exp $ */ - -/* - * Copyright (c) 2002 Marc Espie. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD - * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * area-based allocation built on malloc/free - */ -#include -__RCSID("$NetBSD: alloc.c,v 1.10 2007/12/12 22:55:42 lukem Exp $"); - -#include "sh.h" - -struct link { - struct link *prev; - struct link *next; -}; - -Area * -ainit(Area *ap) -{ - ap->freelist = NULL; - return ap; -} - -void -afreeall(Area *ap) -{ - struct link *l, *l2; - - for (l = ap->freelist; l != NULL; l = l2) { - l2 = l->next; - free(l); - } - ap->freelist = NULL; -} - -#define L2P(l) ( (void *)(((char *)(l)) + sizeof(struct link)) ) -#define P2L(p) ( (struct link *)(((char *)(p)) - sizeof(struct link)) ) - -/* coverity[+alloc] */ -void * -alloc(size_t size, Area *ap) -{ - struct link *l; - - l = malloc(sizeof(struct link) + size); - if (l == NULL) - internal_errorf(1, "unable to allocate memory"); - l->next = ap->freelist; - l->prev = NULL; - if (ap->freelist) - ap->freelist->prev = l; - ap->freelist = l; - - return L2P(l); -} - -/* coverity[+alloc] */ -/* coverity[+free : arg-0] */ -void * -aresize(void *ptr, size_t size, Area *ap) -{ - struct link *l, *l2, *lprev, *lnext; - - if (ptr == NULL) - return alloc(size, ap); - - l = P2L(ptr); - lprev = l->prev; - lnext = l->next; - - l2 = realloc(l, sizeof(struct link) + size); - if (l2 == NULL) - internal_errorf(1, "unable to allocate memory"); - if (lprev) - lprev->next = l2; - else - ap->freelist = l2; - if (lnext) - lnext->prev = l2; - - return L2P(l2); -} - -/* coverity[+free : arg-0] */ -void -afree(void *ptr, Area *ap) -{ - struct link *l; - - if (!ptr) - return; - - l = P2L(ptr); - - if (l->prev) - l->prev->next = l->next; - else - ap->freelist = l->next; - if (l->next) - l->next->prev = l->prev; - - free(l); -} diff --git a/bin/ksh/c_ksh.c b/bin/ksh/c_ksh.c deleted file mode 100644 index 5fff393d6..000000000 --- a/bin/ksh/c_ksh.c +++ /dev/null @@ -1,1490 +0,0 @@ -/* $NetBSD: c_ksh.c,v 1.18 2011/10/16 17:12:11 joerg Exp $ */ - -/* - * built-in Korn commands: c_* - */ -#include - -#ifndef lint -__RCSID("$NetBSD: c_ksh.c,v 1.18 2011/10/16 17:12:11 joerg Exp $"); -#endif - -#include "sh.h" -#include "ksh_stat.h" -#include - -#ifdef __CYGWIN__ -#include -#endif /* __CYGWIN__ */ - -int -c_cd(wp) - char **wp; -{ - int optc; - int physical = Flag(FPHYSICAL); - int cdnode; /* was a node from cdpath added in? */ - int printpath = 0; /* print where we cd'd? */ - int rval; - struct tbl *pwd_s, *oldpwd_s; - XString xs; - char *xp; - char *dir, *try, *pwd; - int phys_path; - char *cdpath; - char *fdir = NULL; - - while ((optc = ksh_getopt(wp, &builtin_opt, "LP")) != EOF) - switch (optc) { - case 'L': - physical = 0; - break; - case 'P': - physical = 1; - break; - case '?': - return 1; - } - wp += builtin_opt.optind; - - if (Flag(FRESTRICTED)) { - bi_errorf("restricted shell - can't cd"); - return 1; - } - - pwd_s = global("PWD"); - oldpwd_s = global("OLDPWD"); - - if (!wp[0]) { - /* No arguments - go home */ - if ((dir = str_val(global("HOME"))) == null) { - bi_errorf("no home directory (HOME not set)"); - return 1; - } - } else if (!wp[1]) { - /* One argument: - or dir */ - dir = wp[0]; - if (strcmp(dir, "-") == 0) { - dir = str_val(oldpwd_s); - if (dir == null) { - bi_errorf("no OLDPWD"); - return 1; - } - printpath++; - } - } else if (!wp[2]) { - /* Two arguments - substitute arg1 in PWD for arg2 */ - int ilen, olen, nlen, elen; - char *cp; - - if (!current_wd[0]) { - bi_errorf("don't know current directory"); - return 1; - } - /* substitute arg1 for arg2 in current path. - * if the first substitution fails because the cd fails - * we could try to find another substitution. For now - * we don't - */ - if ((cp = strstr(current_wd, wp[0])) == (char *) 0) { - bi_errorf("bad substitution"); - return 1; - } - ilen = cp - current_wd; - olen = strlen(wp[0]); - nlen = strlen(wp[1]); - elen = strlen(current_wd + ilen + olen) + 1; - fdir = dir = alloc(ilen + nlen + elen, ATEMP); - memcpy(dir, current_wd, ilen); - memcpy(dir + ilen, wp[1], nlen); - memcpy(dir + ilen + nlen, current_wd + ilen + olen, elen); - printpath++; - } else { - bi_errorf("too many arguments"); - return 1; - } - - Xinit(xs, xp, PATH, ATEMP); - /* xp will have a bogus value after make_path() - set it to 0 - * so that if it's used, it will cause a dump - */ - xp = (char *) 0; - - cdpath = str_val(global("CDPATH")); - do { - cdnode = make_path(current_wd, dir, &cdpath, &xs, &phys_path); -#ifdef S_ISLNK - if (physical) - rval = chdir(try = Xstring(xs, xp) + phys_path); - else -#endif /* S_ISLNK */ - { - simplify_path(Xstring(xs, xp)); - rval = chdir(try = Xstring(xs, xp)); - } - } while (rval < 0 && cdpath != (char *) 0); - - if (rval < 0) { - if (cdnode) - bi_errorf("%s: bad directory", dir); - else - bi_errorf("%s - %s", try, strerror(errno)); - if (fdir) - afree(fdir, ATEMP); - return 1; - } - - /* Clear out tracked aliases with relative paths */ - flushcom(0); - - /* Set OLDPWD (note: unsetting OLDPWD does not disable this - * setting in at&t ksh) - */ - if (current_wd[0]) - /* Ignore failure (happens if readonly or integer) */ - setstr(oldpwd_s, current_wd, KSH_RETURN_ERROR); - - if (!ISABSPATH(Xstring(xs, xp))) { -#ifdef OS2 - /* simplify_path() doesn't know about os/2's drive contexts, - * so it can't set current_wd when changing to a:foo. - * Handle this by calling getcwd()... - */ - pwd = ksh_get_wd((char *) 0, 0); -#else /* OS2 */ - pwd = (char *) 0; -#endif /* OS2 */ - } else -#ifdef S_ISLNK - if (!physical || !(pwd = get_phys_path(Xstring(xs, xp)))) -#endif /* S_ISLNK */ - pwd = Xstring(xs, xp); - - /* Set PWD */ - if (pwd) { -#ifdef __CYGWIN__ - char ptmp[PATH]; /* larger than MAX_PATH */ - cygwin_conv_to_full_posix_path(pwd, ptmp); -#else /* __CYGWIN__ */ - char *ptmp = pwd; -#endif /* __CYGWIN__ */ - set_current_wd(ptmp); - /* Ignore failure (happens if readonly or integer) */ - setstr(pwd_s, ptmp, KSH_RETURN_ERROR); - } else { - set_current_wd(null); - pwd = Xstring(xs, xp); - /* XXX unset $PWD? */ - } - if (printpath || cdnode) - shprintf("%s\n", pwd); - - if (fdir) - afree(fdir, ATEMP); - - return 0; -} - -int -c_pwd(wp) - char **wp; -{ - int optc; - int physical = Flag(FPHYSICAL); - char *p, *freep = NULL; - - while ((optc = ksh_getopt(wp, &builtin_opt, "LP")) != EOF) - switch (optc) { - case 'L': - physical = 0; - break; - case 'P': - physical = 1; - break; - case '?': - return 1; - } - wp += builtin_opt.optind; - - if (wp[0]) { - bi_errorf("too many arguments"); - return 1; - } -#ifdef S_ISLNK - p = current_wd[0] ? (physical ? get_phys_path(current_wd) : current_wd) - : (char *) 0; -#else /* S_ISLNK */ - p = current_wd[0] ? current_wd : (char *) 0; -#endif /* S_ISLNK */ - if (p && eaccess(p, R_OK) < 0) - p = (char *) 0; - if (!p) { - freep = p = ksh_get_wd((char *) 0, 0); - if (!p) { - bi_errorf("can't get current directory - %s", - strerror(errno)); - return 1; - } - } - shprintf("%s\n", p); - if (freep) - afree(freep, ATEMP); - return 0; -} - -int -c_print(wp) - char **wp; -{ -#define PO_NL BIT(0) /* print newline */ -#define PO_EXPAND BIT(1) /* expand backslash sequences */ -#define PO_PMINUSMINUS BIT(2) /* print a -- argument */ -#define PO_HIST BIT(3) /* print to history instead of stdout */ -#define PO_COPROC BIT(4) /* printing to coprocess: block SIGPIPE */ -#define PO_FSLASH BIT(5) /* swap slash for backslash (for os2 ) */ - int fd = 1; - int flags = PO_EXPAND|PO_NL; - char *s; - const char *emsg; - XString xs; - char *xp; - - if (wp[0][0] == 'e') { /* echo command */ - int nflags = flags; - - /* A compromise between sysV and BSD echo commands: - * escape sequences are enabled by default, and - * -n, -e and -E are recognized if they appear - * in arguments with no illegal options (ie, echo -nq - * will print -nq). - * Different from sysV echo since options are recognized, - * different from BSD echo since escape sequences are enabled - * by default. - */ - wp += 1; - while ((s = *wp) && *s == '-' && s[1]) { - while (*++s) - if (*s == 'n') - nflags &= ~PO_NL; - else if (*s == 'e') - nflags |= PO_EXPAND; - else if (*s == 'E') - nflags &= ~PO_EXPAND; - else - /* bad option: don't use nflags, print - * argument - */ - break; - if (*s) - break; - wp++; - flags = nflags; - } - } else { - int optc; -#if OS2 - const char *options = "Rnpfrsu,"; /* added f flag */ -#else - const char *options = "Rnprsu,"; -#endif - while ((optc = ksh_getopt(wp, &builtin_opt, options)) != EOF) - switch (optc) { - case 'R': /* fake BSD echo command */ - flags |= PO_PMINUSMINUS; - flags &= ~PO_EXPAND; - options = "ne"; - break; - case 'e': - flags |= PO_EXPAND; - break; -#ifdef OS2 - case 'f': - flags |= PO_FSLASH; - break; -#endif - case 'n': - flags &= ~PO_NL; - break; -#ifdef KSH - case 'p': - if ((fd = coproc_getfd(W_OK, &emsg)) < 0) { - bi_errorf("-p: %s", emsg); - return 1; - } - break; -#endif /* KSH */ - case 'r': - flags &= ~PO_EXPAND; - break; - case 's': - flags |= PO_HIST; - break; - case 'u': - if (!*(s = builtin_opt.optarg)) - fd = 0; - else if ((fd = check_fd(s, W_OK, &emsg)) < 0) { - bi_errorf("-u: %s: %s", s, emsg); - return 1; - } - break; - case '?': - return 1; - } - if (!(builtin_opt.info & GI_MINUSMINUS)) { - /* treat a lone - like -- */ - if (wp[builtin_opt.optind] - && strcmp(wp[builtin_opt.optind], "-") == 0) - builtin_opt.optind++; - } else if (flags & PO_PMINUSMINUS) - builtin_opt.optind--; - wp += builtin_opt.optind; - } - - Xinit(xs, xp, 128, ATEMP); - - while (*wp != NULL) { - register int c; - s = *wp; - while ((c = *s++) != '\0') { - Xcheck(xs, xp); -#ifdef OS2 - if ((flags & PO_FSLASH) && c == '\\') - if (*s == '\\') - *s++; - else - c = '/'; -#endif /* OS2 */ - if ((flags & PO_EXPAND) && c == '\\') { - int i; - - switch ((c = *s++)) { - /* Oddly enough, \007 seems more portable than - * \a (due to HP-UX cc, Ultrix cc, old pcc's, - * etc.). - */ - case 'a': c = '\007'; break; - case 'b': c = '\b'; break; - case 'c': flags &= ~PO_NL; - continue; /* AT&T brain damage */ - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'v': c = 0x0B; break; - case '0': - /* Look for an octal number: can have - * three digits (not counting the - * leading 0). Truly burnt. - */ - c = 0; - for (i = 0; i < 3; i++) { - if (*s >= '0' && *s <= '7') - c = c*8 + *s++ - '0'; - else - break; - } - break; - case '\0': s--; c = '\\'; break; - case '\\': break; - default: - Xput(xs, xp, '\\'); - } - } - Xput(xs, xp, c); - } - if (*++wp != NULL) - Xput(xs, xp, ' '); - } - if (flags & PO_NL) - Xput(xs, xp, '\n'); - - if (flags & PO_HIST) { - Xput(xs, xp, '\0'); - source->line++; - histsave(source->line, Xstring(xs, xp), 1); - Xfree(xs, xp); - } else { - int n, len = Xlength(xs, xp); - int UNINITIALIZED(opipe); -#ifdef KSH - - /* Ensure we aren't killed by a SIGPIPE while writing to - * a coprocess. at&t ksh doesn't seem to do this (seems - * to just check that the co-process is alive, which is - * not enough). - */ - if (coproc.write >= 0 && coproc.write == fd) { - flags |= PO_COPROC; - opipe = block_pipe(); - } -#endif /* KSH */ - for (s = Xstring(xs, xp); len > 0; ) { - n = write(fd, s, len); - if (n < 0) { -#ifdef KSH - if (flags & PO_COPROC) - restore_pipe(opipe); -#endif /* KSH */ - if (errno == EINTR) { - /* allow user to ^C out */ - intrcheck(); -#ifdef KSH - if (flags & PO_COPROC) - opipe = block_pipe(); -#endif /* KSH */ - continue; - } -#ifdef KSH - /* This doesn't really make sense - could - * break scripts (print -p generates - * error message). - *if (errno == EPIPE) - * coproc_write_close(fd); - */ -#endif /* KSH */ - return 1; - } - s += n; - len -= n; - } -#ifdef KSH - if (flags & PO_COPROC) - restore_pipe(opipe); -#endif /* KSH */ - } - - return 0; -} - -int -c_whence(wp) - char **wp; -{ - struct tbl *tp; - char *id; - int pflag = 0, vflag = 0, Vflag = 0; - int ret = 0; - int optc; - int iam_whence = wp[0][0] == 'w'; - int fcflags; - const char *options = iam_whence ? "pv" : "pvV"; - - while ((optc = ksh_getopt(wp, &builtin_opt, options)) != EOF) - switch (optc) { - case 'p': - pflag = 1; - break; - case 'v': - vflag = 1; - break; - case 'V': - Vflag = 1; - break; - case '?': - return 1; - } - wp += builtin_opt.optind; - - - fcflags = FC_BI | FC_PATH | FC_FUNC; - if (!iam_whence) { - /* Note that -p on its own is deal with in comexec() */ - if (pflag) - fcflags |= FC_DEFPATH; - /* Convert command options to whence options - note that - * command -pV uses a different path search than whence -v - * or whence -pv. This should be considered a feature. - */ - vflag = Vflag; - } - if (pflag) - fcflags &= ~(FC_BI | FC_FUNC); - - while ((vflag || ret == 0) && (id = *wp++) != NULL) { - tp = NULL; - if ((iam_whence || vflag) && !pflag) - tp = tsearch(&keywords, id, hash(id)); - if (!tp && !pflag) { - tp = tsearch(&aliases, id, hash(id)); - if (tp && !(tp->flag & ISSET)) - tp = NULL; - } - if (!tp) - tp = findcom(id, fcflags); - if (vflag || (tp->type != CALIAS && tp->type != CEXEC - && tp->type != CTALIAS)) - shprintf("%s", id); - switch (tp->type) { - case CKEYWD: - if (vflag) - shprintf(" is a reserved word"); - break; - case CALIAS: - if (vflag) - shprintf(" is an %salias for ", - (tp->flag & EXPORT) ? "exported " - : null); - if (!iam_whence && !vflag) - shprintf("alias %s=", id); - print_value_quoted(tp->val.s); - break; - case CFUNC: - if (vflag) { - shprintf(" is a"); - if (tp->flag & EXPORT) - shprintf("n exported"); - if (tp->flag & TRACE) - shprintf(" traced"); - if (!(tp->flag & ISSET)) { - shprintf(" undefined"); - if (tp->u.fpath) - shprintf(" (autoload from %s)", - tp->u.fpath); - } - shprintf(" function"); - } - break; - case CSHELL: - if (vflag) - shprintf(" is a%s shell builtin", - (tp->flag & SPEC_BI) ? " special" : null); - break; - case CTALIAS: - case CEXEC: - if (tp->flag & ISSET) { - if (vflag) { - shprintf(" is "); - if (tp->type == CTALIAS) - shprintf( - "a tracked %salias for ", - (tp->flag & EXPORT) ? - "exported " - : null); - } - shprintf("%s", tp->val.s); - } else { - if (vflag) - shprintf(" not found"); - ret = 1; - } - break; - default: - shprintf("%s is *GOK*", id); - break; - } - if (vflag || !ret) - shprintf("%s", newline); - } - return ret; -} - -/* Deal with command -vV - command -p dealt with in comexec() */ -int -c_command(wp) - char **wp; -{ - /* Let c_whence do the work. Note that c_command() must be - * a distinct function from c_whence() (tested in comexec()). - */ - return c_whence(wp); -} - -/* typeset, export, and readonly */ -int -c_typeset(wp) - char **wp; -{ - struct block *l = e->loc; - struct tbl *vp, **p; - Tflag fset = 0, fclr = 0; - int thing = 0, func = 0, localv = 0; - const char *options = "L#R#UZ#fi#lprtux"; /* see comment below */ - char *fieldstr, *basestr; - int field, base; - int optc; - Tflag flag; - int pflag = 0; - - switch (**wp) { - case 'e': /* export */ - fset |= EXPORT; - options = "p"; - break; - case 'r': /* readonly */ - fset |= RDONLY; - options = "p"; - break; - case 's': /* set */ - /* called with 'typeset -' */ - break; - case 't': /* typeset */ - localv = 1; - break; - } - - fieldstr = basestr = (char *) 0; - builtin_opt.flags |= GF_PLUSOPT; - /* at&t ksh seems to have 0-9 as options, which are multiplied - * to get a number that is used with -L, -R, -Z or -i (eg, -1R2 - * sets right justify in a field of 12). This allows options - * to be grouped in an order (eg, -Lu12), but disallows -i8 -L3 and - * does not allow the number to be specified as a separate argument - * Here, the number must follow the RLZi option, but is optional - * (see the # kludge in ksh_getopt()). - */ - while ((optc = ksh_getopt(wp, &builtin_opt, options)) != EOF) { - flag = 0; - switch (optc) { - case 'L': - flag = LJUST; - fieldstr = builtin_opt.optarg; - break; - case 'R': - flag = RJUST; - fieldstr = builtin_opt.optarg; - break; - case 'U': - /* at&t ksh uses u, but this conflicts with - * upper/lower case. If this option is changed, - * need to change the -U below as well - */ - flag = INT_U; - break; - case 'Z': - flag = ZEROFIL; - fieldstr = builtin_opt.optarg; - break; - case 'f': - func = 1; - break; - case 'i': - flag = INTEGER; - basestr = builtin_opt.optarg; - break; - case 'l': - flag = LCASEV; - break; - case 'p': /* posix export/readonly -p flag. - * typeset -p is the same as typeset (in pdksh); - * here for compatibility with ksh93. - */ - pflag = 1; - break; - case 'r': - flag = RDONLY; - break; - case 't': - flag = TRACE; - break; - case 'u': - flag = UCASEV_AL; /* upper case / autoload */ - break; - case 'x': - flag = EXPORT; - break; - case '?': - return 1; - } - if (builtin_opt.info & GI_PLUS) { - fclr |= flag; - fset &= ~flag; - thing = '+'; - } else { - fset |= flag; - fclr &= ~flag; - thing = '-'; - } - } - - field = 0; - if (fieldstr && !bi_getn(fieldstr, &field)) - return 1; - base = 0; - if (basestr && !bi_getn(basestr, &base)) - return 1; - - if (!(builtin_opt.info & GI_MINUSMINUS) && wp[builtin_opt.optind] - && (wp[builtin_opt.optind][0] == '-' - || wp[builtin_opt.optind][0] == '+') - && wp[builtin_opt.optind][1] == '\0') - { - thing = wp[builtin_opt.optind][0]; - builtin_opt.optind++; - } - - if (func && ((fset|fclr) & ~(TRACE|UCASEV_AL|EXPORT))) { - bi_errorf("only -t, -u and -x options may be used with -f"); - return 1; - } - if (wp[builtin_opt.optind]) { - /* Take care of exclusions. - * At this point, flags in fset are cleared in fclr and vise - * versa. This property should be preserved. - */ - if (fset & LCASEV) /* LCASEV has priority over UCASEV_AL */ - fset &= ~UCASEV_AL; - if (fset & LJUST) /* LJUST has priority over RJUST */ - fset &= ~RJUST; - if ((fset & (ZEROFIL|LJUST)) == ZEROFIL) { /* -Z implies -ZR */ - fset |= RJUST; - fclr &= ~RJUST; - } - /* Setting these attributes clears the others, unless they - * are also set in this command - */ - if (fset & (LJUST|RJUST|ZEROFIL|UCASEV_AL|LCASEV|INTEGER - |INT_U|INT_L)) - fclr |= ~fset & - (LJUST|RJUST|ZEROFIL|UCASEV_AL|LCASEV|INTEGER - |INT_U|INT_L); - } - - /* set variables and attributes */ - if (wp[builtin_opt.optind]) { - int i; - int rval = 0; - struct tbl *f; - - if (localv && !func) - fset |= LOCAL; - for (i = builtin_opt.optind; wp[i]; i++) { - if (func) { - f = findfunc(wp[i], hash(wp[i]), - (fset&UCASEV_AL) ? TRUE : FALSE); - if (!f) { - /* at&t ksh does ++rval: bogus */ - rval = 1; - continue; - } - if (fset | fclr) { - f->flag |= fset; - f->flag &= ~fclr; - } else - fptreef(shl_stdout, 0, - f->flag & FKSH ? - "function %s %T\n" - : "%s() %T\n" - , - wp[i], f->val.t); - } else if (!typeset(wp[i], fset, fclr, field, base)) { - bi_errorf("%s: not identifier", wp[i]); - return 1; - } - } - return rval; - } - - /* list variables and attributes */ - flag = fset | fclr; /* no difference at this point.. */ - if (func) { - for (l = e->loc; l; l = l->next) { - for (p = tsort(&l->funs); (vp = *p++); ) { - if (flag && (vp->flag & flag) == 0) - continue; - if (thing == '-') - fptreef(shl_stdout, 0, vp->flag & FKSH ? - "function %s %T\n" - : "%s() %T\n", - vp->name, vp->val.t); - else - shprintf("%s\n", vp->name); - } - } - } else { - for (l = e->loc; l; l = l->next) { - for (p = tsort(&l->vars); (vp = *p++); ) { - struct tbl *tvp; - int any_set = 0; - /* - * See if the parameter is set (for arrays, if any - * element is set). - */ - for (tvp = vp; tvp; tvp = tvp->u.array) - if (tvp->flag & ISSET) { - any_set = 1; - break; - } - /* - * Check attributes - note that all array elements - * have (should have?) the same attributes, so checking - * the first is sufficient. - * - * Report an unset param only if the user has - * explicitly given it some attribute (like export); - * otherwise, after "echo $FOO", we would report FOO... - */ - if (!any_set && !(vp->flag & USERATTRIB)) - continue; - if (flag && (vp->flag & flag) == 0) - continue; - for (; vp; vp = vp->u.array) { - /* Ignore array elements that aren't set unless there - * are no set elements, in which case the first is - * reported on - */ - if ((vp->flag&ARRAY) && any_set && !(vp->flag & ISSET)) - continue; - /* no arguments */ - if (thing == 0 && flag == 0) { - /* at&t ksh prints things like export, integer, - * leftadj, zerofill, etc., but POSIX says must - * be suitable for re-entry... - */ - shprintf("typeset "); - if ((vp->flag&INTEGER)) - shprintf("-i "); - if ((vp->flag&EXPORT)) - shprintf("-x "); - if ((vp->flag&RDONLY)) - shprintf("-r "); - if ((vp->flag&TRACE)) - shprintf("-t "); - if ((vp->flag&LJUST)) - shprintf("-L%d ", vp->u2.field); - if ((vp->flag&RJUST)) - shprintf("-R%d ", vp->u2.field); - if ((vp->flag&ZEROFIL)) - shprintf("-Z "); - if ((vp->flag&LCASEV)) - shprintf("-l "); - if ((vp->flag&UCASEV_AL)) - shprintf("-u "); - if ((vp->flag&INT_U)) - shprintf("-U "); - shprintf("%s\n", vp->name); - if (vp->flag&ARRAY) - break; - } else { - if (pflag) - shprintf("%s ", - (flag & EXPORT) ? "export" : "readonly"); - if ((vp->flag&ARRAY) && any_set) - shprintf("%s[%d]", vp->name, vp->index); - else - shprintf("%s", vp->name); - if (thing == '-' && (vp->flag&ISSET)) { - char *s = str_val(vp); - - shprintf("="); - /* at&t ksh can't have justified integers.. */ - if ((vp->flag & (INTEGER|LJUST|RJUST)) - == INTEGER) - shprintf("%s", s); - else - print_value_quoted(s); - } - shprintf("%s", newline); - } - /* Only report first `element' of an array with - * no set elements. - */ - if (!any_set) - break; - } - } - } - } - return 0; -} - -int -c_alias(wp) - char **wp; -{ - struct table *t = &aliases; - int rv = 0, rflag = 0, tflag, Uflag = 0, pflag = 0; - int prefix = 0; - Tflag xflag = 0; - int optc; - - builtin_opt.flags |= GF_PLUSOPT; - while ((optc = ksh_getopt(wp, &builtin_opt, "dprtUx")) != EOF) { - prefix = builtin_opt.info & GI_PLUS ? '+' : '-'; - switch (optc) { - case 'd': - t = &homedirs; - break; - case 'p': - pflag = 1; - break; - case 'r': - rflag = 1; - break; - case 't': - t = &taliases; - break; - case 'U': /* kludge for tracked alias initialization - * (don't do a path search, just make an entry) - */ - Uflag = 1; - break; - case 'x': - xflag = EXPORT; - break; - case '?': - return 1; - } - } - wp += builtin_opt.optind; - - if (!(builtin_opt.info & GI_MINUSMINUS) && *wp - && (wp[0][0] == '-' || wp[0][0] == '+') && wp[0][1] == '\0') - { - prefix = wp[0][0]; - wp++; - } - - tflag = t == &taliases; - - /* "hash -r" means reset all the tracked aliases.. */ - if (rflag) { - static const char *const args[] = { - "unalias", "-ta", (const char *) 0 - }; - - if (!tflag || *wp) { - shprintf( - "alias: -r flag can only be used with -t and without arguments\n"); - return 1; - } - ksh_getopt_reset(&builtin_opt, GF_ERROR); - return c_unalias((char **)__UNCONST(args)); - } - - - if (*wp == NULL) { - struct tbl *ap, **p; - - for (p = tsort(t); (ap = *p++) != NULL; ) - if ((ap->flag & (ISSET|xflag)) == (ISSET|xflag)) { - if (pflag) - shf_puts("alias ", shl_stdout); - shf_puts(ap->name, shl_stdout); - if (prefix != '+') { - shf_putc('=', shl_stdout); - print_value_quoted(ap->val.s); - } - shprintf("%s", newline); - } - } - - for (; *wp != NULL; wp++) { - char *alias = *wp; - char *val = strchr(alias, '='); - char *newval; - struct tbl *ap; - int h; - - if (val) - alias = str_nsave(alias, val++ - alias, ATEMP); - h = hash(alias); - if (val == NULL && !tflag && !xflag) { - ap = tsearch(t, alias, h); - if (ap != NULL && (ap->flag&ISSET)) { - if (pflag) - shf_puts("alias ", shl_stdout); - shf_puts(ap->name, shl_stdout); - if (prefix != '+') { - shf_putc('=', shl_stdout); - print_value_quoted(ap->val.s); - } - shprintf("%s", newline); - } else { - shprintf("%s alias not found\n", alias); - rv = 1; - } - continue; - } - ap = tenter(t, alias, h); - ap->type = tflag ? CTALIAS : CALIAS; - /* Are we setting the value or just some flags? */ - if ((val && !tflag) || (!val && tflag && !Uflag)) { - if (ap->flag&ALLOC) { - ap->flag &= ~(ALLOC|ISSET); - afree((void*)ap->val.s, APERM); - } - /* ignore values for -t (at&t ksh does this) */ - newval = tflag ? search(alias, path, X_OK, (int *) 0) - : val; - if (newval) { - ap->val.s = str_save(newval, APERM); - ap->flag |= ALLOC|ISSET; - } else - ap->flag &= ~ISSET; - } - ap->flag |= DEFINED; - if (prefix == '+') - ap->flag &= ~xflag; - else - ap->flag |= xflag; - if (val) - afree(alias, ATEMP); - } - - return rv; -} - -int -c_unalias(wp) - char **wp; -{ - register struct table *t = &aliases; - register struct tbl *ap; - int rv = 0, all = 0; - int optc; - - while ((optc = ksh_getopt(wp, &builtin_opt, "adt")) != EOF) - switch (optc) { - case 'a': - all = 1; - break; - case 'd': - t = &homedirs; - break; - case 't': - t = &taliases; - break; - case '?': - return 1; - } - wp += builtin_opt.optind; - - for (; *wp != NULL; wp++) { - ap = tsearch(t, *wp, hash(*wp)); - if (ap == NULL) { - rv = 1; /* POSIX */ - continue; - } - if (ap->flag&ALLOC) { - ap->flag &= ~(ALLOC|ISSET); - afree((void*)ap->val.s, APERM); - } - ap->flag &= ~(DEFINED|ISSET|EXPORT); - } - - if (all) { - struct tstate ts; - - for (twalk(&ts, t); (ap = tnext(&ts)); ) { - if (ap->flag&ALLOC) { - ap->flag &= ~(ALLOC|ISSET); - afree((void*)ap->val.s, APERM); - } - ap->flag &= ~(DEFINED|ISSET|EXPORT); - } - } - - return rv; -} - -#ifdef KSH -int -c_let(wp) - char **wp; -{ - int rv = 1; - long val; - - if (wp[1] == (char *) 0) /* at&t ksh does this */ - bi_errorf("no arguments"); - else - for (wp++; *wp; wp++) - if (!evaluate(*wp, &val, KSH_RETURN_ERROR)) { - rv = 2; /* distinguish error from zero result */ - break; - } else - rv = val == 0; - return rv; -} -#endif /* KSH */ - -int -c_jobs(wp) - char **wp; -{ - int optc; - int flag = 0; - int nflag = 0; - int rv = 0; - - while ((optc = ksh_getopt(wp, &builtin_opt, "lpnz")) != EOF) - switch (optc) { - case 'l': - flag = 1; - break; - case 'p': - flag = 2; - break; - case 'n': - nflag = 1; - break; - case 'z': /* debugging: print zombies */ - nflag = -1; - break; - case '?': - return 1; - } - wp += builtin_opt.optind; - if (!*wp) { - if (j_jobs((char *) 0, flag, nflag)) - rv = 1; - } else { - for (; *wp; wp++) - if (j_jobs(*wp, flag, nflag)) - rv = 1; - } - return rv; -} - -#ifdef JOBS -int -c_fgbg(wp) - char **wp; -{ - int bg = strcmp(*wp, "bg") == 0; - int UNINITIALIZED(rv); - - if (!Flag(FMONITOR)) { - bi_errorf("job control not enabled"); - return 1; - } - if (ksh_getopt(wp, &builtin_opt, null) == '?') - return 1; - wp += builtin_opt.optind; - if (*wp) - for (; *wp; wp++) - rv = j_resume(*wp, bg); - else - rv = j_resume("%%", bg); - /* POSIX says fg shall return 0 (unless an error occurs). - * at&t ksh returns the exit value of the job... - */ - return (bg || Flag(FPOSIX)) ? 0 : rv; -} -#endif - -struct kill_info { - int num_width; - int name_width; -}; -static char *kill_fmt_entry ARGS((void *arg, int i, char *buf, int buflen)); - -/* format a single kill item */ -static char * -kill_fmt_entry(arg, i, buf, buflen) - void *arg; - int i; - char *buf; - int buflen; -{ - struct kill_info *ki = (struct kill_info *) arg; - - i++; - if (sigtraps[i].name) - shf_snprintf(buf, buflen, "%*d %*s %s", - ki->num_width, i, - ki->name_width, sigtraps[i].name, - sigtraps[i].mess); - else - shf_snprintf(buf, buflen, "%*d %*d %s", - ki->num_width, i, - ki->name_width, sigtraps[i].signal, - sigtraps[i].mess); - return buf; -} - - -int -c_kill(wp) - char **wp; -{ - Trap *t = (Trap *) 0; - char *p; - int lflag = 0; - int i, n, rv, sig; - - /* assume old style options if -digits or -UPPERCASE */ - if ((p = wp[1]) && *p == '-' - && (digit(p[1]) || isupper((unsigned char)p[1]))) { - if (!(t = gettrap(p + 1, TRUE))) { - bi_errorf("bad signal `%s'", p + 1); - return 1; - } - i = (wp[2] && strcmp(wp[2], "--") == 0) ? 3 : 2; - } else { - int optc; - - while ((optc = ksh_getopt(wp, &builtin_opt, "ls:")) != EOF) - switch (optc) { - case 'l': - lflag = 1; - break; - case 's': - if (!(t = gettrap(builtin_opt.optarg, TRUE))) { - bi_errorf("bad signal `%s'", - builtin_opt.optarg); - return 1; - } - break; - case '?': - return 1; - } - i = builtin_opt.optind; - } - if ((lflag && t) || (!wp[i] && !lflag)) { - shf_fprintf(shl_out, -"usage: kill [ -s signame | -signum | -signame ] {pid|job}...\n\ - kill -l [exit_status]\n" - ); - bi_errorf("%s", null); - return 1; - } - - if (lflag) { - if (wp[i]) { - for (; wp[i]; i++) { - if (!bi_getn(wp[i], &n)) - return 1; - if (n > 128 && n < 128 + SIGNALS) - n -= 128; - if (n > 0 && n < SIGNALS && sigtraps[n].name) - shprintf("%s\n", sigtraps[n].name); - else - shprintf("%d\n", n); - } - } else if (Flag(FPOSIX)) { - p = null; - for (i = 1; i < SIGNALS; i++, p = space) - if (sigtraps[i].name) - shprintf("%s%s", p, sigtraps[i].name); - shprintf("%s", newline); - } else { - int w, si; - int mess_width; - struct kill_info ki; - - for (si = SIGNALS, ki.num_width = 1; si >= 10; si /= 10) - ki.num_width++; - ki.name_width = mess_width = 0; - for (si = 0; si < SIGNALS; si++) { - w = sigtraps[si].name ? - (int)strlen(sigtraps[si].name) : - ki.num_width; - if (w > ki.name_width) - ki.name_width = w; - w = strlen(sigtraps[si].mess); - if (w > mess_width) - mess_width = w; - } - - print_columns(shl_stdout, SIGNALS - 1, - kill_fmt_entry, (void *) &ki, - ki.num_width + ki.name_width + mess_width + 3, 1); - } - return 0; - } - rv = 0; - sig = t ? t->signal : SIGTERM; - for (; (p = wp[i]); i++) { - if (*p == '%') { - if (j_kill(p, sig)) - rv = 1; - } else if (!getn(p, &n)) { - bi_errorf("%s: arguments must be jobs or process IDs", - p); - rv = 1; - } else { - /* use killpg if < -1 since -1 does special things for - * some non-killpg-endowed kills - */ - if ((n < -1 ? killpg(-n, sig) : kill(n, sig)) < 0) { - bi_errorf("%s: %s", p, strerror(errno)); - rv = 1; - } - } - } - return rv; -} - -void -getopts_reset(val) - int val; -{ - if (val >= 1) { - ksh_getopt_reset(&user_opt, - GF_NONAME | (Flag(FPOSIX) ? 0 : GF_PLUSOPT)); - user_opt.optind = user_opt.uoptind = val; - } -} - -int -c_getopts(wp) - char **wp; -{ - int argc; - const char *options; - const char *var; - int optc; - int ret; - char buf[3]; - struct tbl *vq, *voptarg; - - if (ksh_getopt(wp, &builtin_opt, null) == '?') - return 1; - wp += builtin_opt.optind; - - options = *wp++; - if (!options) { - bi_errorf("missing options argument"); - return 1; - } - - var = *wp++; - if (!var) { - bi_errorf("missing name argument"); - return 1; - } - if (!*var || *skip_varname(var, TRUE)) { - bi_errorf("%s: is not an identifier", var); - return 1; - } - - if (e->loc->next == (struct block *) 0) { - internal_errorf(0, "c_getopts: no argv"); - return 1; - } - /* Which arguments are we parsing... */ - if (*wp == (char *) 0) - wp = e->loc->next->argv; - else - *--wp = e->loc->next->argv[0]; - - /* Check that our saved state won't cause a core dump... */ - for (argc = 0; wp[argc]; argc++) - ; - if (user_opt.optind > argc - || (user_opt.p != 0 - && user_opt.p > strlen(wp[user_opt.optind - 1]))) - { - bi_errorf("arguments changed since last call"); - return 1; - } - - user_opt.optarg = (char *) 0; - optc = ksh_getopt(wp, &user_opt, options); - - if (optc >= 0 && optc != '?' && (user_opt.info & GI_PLUS)) { - buf[0] = '+'; - buf[1] = optc; - buf[2] = '\0'; - } else { - /* POSIX says var is set to ? at end-of-options, at&t ksh - * sets it to null - we go with POSIX... - */ - buf[0] = optc < 0 ? '?' : optc; - buf[1] = '\0'; - } - - /* at&t ksh does not change OPTIND if it was an unknown option. - * Scripts counting on this are prone to break... (ie, don't count - * on this staying). - */ - if (optc != '?') { - user_opt.uoptind = user_opt.optind; - } - - voptarg = global("OPTARG"); - voptarg->flag &= ~RDONLY; /* at&t ksh clears ro and int */ - /* Paranoia: ensure no bizarre results. */ - if (voptarg->flag & INTEGER) - typeset("OPTARG", 0, INTEGER, 0, 0); - if (user_opt.optarg == (char *) 0) - unset(voptarg, 0); - else - /* This can't fail (have cleared readonly/integer) */ - setstr(voptarg, user_opt.optarg, KSH_RETURN_ERROR); - - ret = 0; - - vq = global(var); - /* Error message already printed (integer, readonly) */ - if (!setstr(vq, buf, KSH_RETURN_ERROR)) - ret = 1; - if (Flag(FEXPORT)) - typeset(var, EXPORT, 0, 0, 0); - - return optc < 0 ? 1 : ret; -} - -#ifdef EMACS -int -c_bind(wp) - char **wp; -{ - int rv = 0, macro = 0, list = 0; - register char *cp; - int optc; - - while ((optc = ksh_getopt(wp, &builtin_opt, "lm")) != EOF) - switch (optc) { - case 'l': - list = 1; - break; - case 'm': - macro = 1; - break; - case '?': - return 1; - } - wp += builtin_opt.optind; - - if (*wp == NULL) /* list all */ - rv = x_bind(NULL, NULL, 0, list); - - for (; *wp != NULL; wp++) { - cp = strchr(*wp, '='); - if (cp != NULL) - *cp++ = '\0'; - if (x_bind(*wp, cp, macro, 0)) - rv = 1; - } - - return rv; -} -#endif - -/* A leading = means assignments before command are kept; - * a leading * means a POSIX special builtin; - * a leading + means a POSIX regular builtin - * (* and + should not be combined). - */ -const struct builtin kshbuiltins [] = { - {"+alias", c_alias}, /* no =: at&t manual wrong */ - {"+cd", c_cd}, - {"+command", c_command}, - {"echo", c_print}, - {"*=export", c_typeset}, -#ifdef HISTORY - {"+fc", c_fc}, -#endif /* HISTORY */ - {"+getopts", c_getopts}, - {"+jobs", c_jobs}, - {"+kill", c_kill}, -#ifdef KSH - {"let", c_let}, -#endif /* KSH */ - {"print", c_print}, - {"pwd", c_pwd}, - {"*=readonly", c_typeset}, - {"=typeset", c_typeset}, - {"+unalias", c_unalias}, - {"whence", c_whence}, -#ifdef JOBS - {"+bg", c_fgbg}, - {"+fg", c_fgbg}, -#endif -#ifdef EMACS - {"bind", c_bind}, -#endif - {NULL, NULL} -}; diff --git a/bin/ksh/c_sh.c b/bin/ksh/c_sh.c deleted file mode 100644 index dbda824d5..000000000 --- a/bin/ksh/c_sh.c +++ /dev/null @@ -1,919 +0,0 @@ -/* $NetBSD: c_sh.c,v 1.15 2013/10/18 19:53:34 christos Exp $ */ - -/* - * built-in Bourne commands - */ -#include - -#ifndef lint -__RCSID("$NetBSD: c_sh.c,v 1.15 2013/10/18 19:53:34 christos Exp $"); -#endif - - -#include "sh.h" -#include "ksh_stat.h" /* umask() */ -#include "ksh_time.h" -#include "ksh_times.h" - -static char *clocktos ARGS((clock_t t)); - - -/* :, false and true */ -int -c_label(wp) - char **wp; -{ - return wp[0][0] == 'f' ? 1 : 0; -} - -int -c_shift(wp) - char **wp; -{ - register struct block *l = e->loc; - register int n; - long val; - char *arg; - - if (ksh_getopt(wp, &builtin_opt, null) == '?') - return 1; - arg = wp[builtin_opt.optind]; - - if (arg) { - evaluate(arg, &val, KSH_UNWIND_ERROR); - n = val; - } else - n = 1; - if (n < 0) { - bi_errorf("%s: bad number", arg); - return (1); - } - if (l->argc < n) { - bi_errorf("nothing to shift"); - return (1); - } - l->argv[n] = l->argv[0]; - l->argv += n; - l->argc -= n; - return 0; -} - -int -c_umask(wp) - char **wp; -{ - register int i; - register char *cp; - int symbolic = 0; - int old_umask; - int optc; - - while ((optc = ksh_getopt(wp, &builtin_opt, "S")) != EOF) - switch (optc) { - case 'S': - symbolic = 1; - break; - case '?': - return 1; - } - cp = wp[builtin_opt.optind]; - if (cp == NULL) { - old_umask = umask(0); - umask(old_umask); - if (symbolic) { - char buf[18]; - int j; - - old_umask = ~old_umask; - cp = buf; - for (i = 0; i < 3; i++) { - *cp++ = "ugo"[i]; - *cp++ = '='; - for (j = 0; j < 3; j++) - if (old_umask & (1 << (8 - (3*i + j)))) - *cp++ = "rwx"[j]; - *cp++ = ','; - } - cp[-1] = '\0'; - shprintf("%s\n", buf); - } else - shprintf("%#3.3o\n", old_umask); - } else { - int new_umask; - - if (digit(*cp)) { - for (new_umask = 0; *cp >= '0' && *cp <= '7'; cp++) - new_umask = new_umask * 8 + (*cp - '0'); - if (*cp) { - bi_errorf("bad number"); - return 1; - } - } else { - /* symbolic format */ - int positions, new_val; - char op; - - old_umask = umask(0); - umask(old_umask); /* in case of error */ - old_umask = ~old_umask; - new_umask = old_umask; - positions = 0; - while (*cp) { - while (*cp && strchr("augo", *cp)) - switch (*cp++) { - case 'a': positions |= 0111; break; - case 'u': positions |= 0100; break; - case 'g': positions |= 0010; break; - case 'o': positions |= 0001; break; - } - if (!positions) - positions = 0111; /* default is a */ - if (!strchr("=+-", op = *cp)) - break; - cp++; - new_val = 0; - while (*cp && strchr("rwxugoXs", *cp)) - switch (*cp++) { - case 'r': new_val |= 04; break; - case 'w': new_val |= 02; break; - case 'x': new_val |= 01; break; - case 'u': new_val |= old_umask >> 6; - break; - case 'g': new_val |= old_umask >> 3; - break; - case 'o': new_val |= old_umask >> 0; - break; - case 'X': if (old_umask & 0111) - new_val |= 01; - break; - case 's': /* ignored */ - break; - } - new_val = (new_val & 07) * positions; - switch (op) { - case '-': - new_umask &= ~new_val; - break; - case '=': - new_umask = new_val - | (new_umask & ~(positions * 07)); - break; - case '+': - new_umask |= new_val; - } - if (*cp == ',') { - positions = 0; - cp++; - } else if (!strchr("=+-", *cp)) - break; - } - if (*cp) { - bi_errorf("bad mask"); - return 1; - } - new_umask = ~new_umask; - } - umask(new_umask); - } - return 0; -} - -int -c_dot(wp) - char **wp; -{ - char *file, *cp; - char **argv; - int argc; - int i; - int err; - - if (ksh_getopt(wp, &builtin_opt, null) == '?') - return 1; - - if ((cp = wp[builtin_opt.optind]) == NULL) - return 0; - file = search(cp, path, R_OK, &err); - if (file == NULL) { - bi_errorf("%s: %s", cp, err ? strerror(err) : "not found"); - return 1; - } - - /* Set positional parameters? */ - if (wp[builtin_opt.optind + 1]) { - argv = wp + builtin_opt.optind; - argv[0] = e->loc->argv[0]; /* preserve $0 */ - for (argc = 0; argv[argc + 1]; argc++) - ; - } else { - argc = 0; - argv = (char **) 0; - } - i = include(file, argc, argv, 0); - if (i < 0) { /* should not happen */ - bi_errorf("%s: %s", cp, strerror(errno)); - return 1; - } - return i; -} - -int -c_wait(wp) - char **wp; -{ - int UNINITIALIZED(rv); - int sig; - - if (ksh_getopt(wp, &builtin_opt, null) == '?') - return 1; - wp += builtin_opt.optind; - if (*wp == (char *) 0) { - while (waitfor((char *) 0, &sig) >= 0) - ; - rv = sig; - } else { - for (; *wp; wp++) - rv = waitfor(*wp, &sig); - if (rv < 0) - rv = sig ? sig : 127; /* magic exit code: bad job-id */ - } - return rv; -} - -int -c_read(wp) - char **wp; -{ - register int c = 0; - int expandv = 1, history = 0; - int expanding; - int ecode = 0; - register char *cp; - int fd = 0; - struct shf *shf; - int optc; - const char *emsg; - XString cs, xs; - struct tbl *vp; - char UNINITIALIZED(*xp); - static char REPLY[] = "REPLY"; - - while ((optc = ksh_getopt(wp, &builtin_opt, "prsu,")) != EOF) - switch (optc) { -#ifdef KSH - case 'p': - if ((fd = coproc_getfd(R_OK, &emsg)) < 0) { - bi_errorf("-p: %s", emsg); - return 1; - } - break; -#endif /* KSH */ - case 'r': - expandv = 0; - break; - case 's': - history = 1; - break; - case 'u': - if (!*(cp = builtin_opt.optarg)) - fd = 0; - else if ((fd = check_fd(cp, R_OK, &emsg)) < 0) { - bi_errorf("-u: %s: %s", cp, emsg); - return 1; - } - break; - case '?': - return 1; - } - wp += builtin_opt.optind; - - if (*wp == NULL) - *--wp = REPLY; - - /* Since we can't necessarily seek backwards on non-regular files, - * don't buffer them so we can't read too much. - */ - shf = shf_reopen(fd, SHF_RD | SHF_INTERRUPT | can_seek(fd), shl_spare); - - if ((cp = strchr(*wp, '?')) != NULL) { - *cp = 0; - if (isatty(fd)) { - /* at&t ksh says it prints prompt on fd if it's open - * for writing and is a tty, but it doesn't do it - * (it also doesn't check the interactive flag, - * as is indicated in the Kornshell book). - */ - shellf("%s", cp+1); - } - } - -#ifdef KSH - /* If we are reading from the co-process for the first time, - * make sure the other side of the pipe is closed first. This allows - * the detection of eof. - * - * This is not compatible with at&t ksh... the fd is kept so another - * coproc can be started with same output, however, this means eof - * can't be detected... This is why it is closed here. - * If this call is removed, remove the eof check below, too. - * coproc_readw_close(fd); - */ -#endif /* KSH */ - - if (history) - Xinit(xs, xp, 128, ATEMP); - expanding = 0; - Xinit(cs, cp, 128, ATEMP); - for (; *wp != NULL; wp++) { - for (cp = Xstring(cs, cp); ; ) { - if (c == '\n' || c == EOF) - break; - while (1) { - c = shf_getc(shf); - if (c == '\0' -#ifdef OS2 - || c == '\r' -#endif /* OS2 */ - ) - continue; - if (c == EOF && shf_error(shf) - && shf_errno(shf) == EINTR) - { - /* Was the offending signal one that - * would normally kill a process? - * If so, pretend the read was killed. - */ - ecode = fatal_trap_check(); - - /* non fatal (eg, CHLD), carry on */ - if (!ecode) { - shf_clearerr(shf); - continue; - } - } - break; - } - if (history) { - Xcheck(xs, xp); - Xput(xs, xp, c); - } - Xcheck(cs, cp); - if (expanding) { - expanding = 0; - if (c == '\n') { - c = 0; - if (Flag(FTALKING_I) && isatty(fd)) { - /* set prompt in case this is - * called from .profile or $ENV - */ - set_prompt(PS2, (Source *) 0); - pprompt(prompt, 0); - } - } else if (c != EOF) - Xput(cs, cp, c); - continue; - } - if (expandv && c == '\\') { - expanding = 1; - continue; - } - if (c == '\n' || c == EOF) - break; - if (ctype(c, C_IFS)) { - if (Xlength(cs, cp) == 0 && ctype(c, C_IFSWS)) - continue; - if (wp[1]) - break; - } - Xput(cs, cp, c); - } - /* strip trailing IFS white space from last variable */ - if (!wp[1]) - while (Xlength(cs, cp) && ctype(cp[-1], C_IFS) - && ctype(cp[-1], C_IFSWS)) - cp--; - Xput(cs, cp, '\0'); - vp = global(*wp); - /* Must be done before setting export. */ - if (vp->flag & RDONLY) { - shf_flush(shf); - bi_errorf("%s is read only", *wp); - return 1; - } - if (Flag(FEXPORT)) - typeset(*wp, EXPORT, 0, 0, 0); - if (!setstr(vp, Xstring(cs, cp), KSH_RETURN_ERROR)) { - shf_flush(shf); - return 1; - } - } - - shf_flush(shf); - if (history) { - Xput(xs, xp, '\0'); - source->line++; - histsave(source->line, Xstring(xs, xp), 1); - Xfree(xs, xp); - } -#ifdef KSH - /* if this is the co-process fd, close the file descriptor - * (can get eof if and only if all processes are have died, ie, - * coproc.njobs is 0 and the pipe is closed). - */ - if (c == EOF && !ecode) - coproc_read_close(fd); -#endif /* KSH */ - - return ecode ? ecode : c == EOF; -} - -int -c_eval(wp) - char **wp; -{ - register struct source *s; - int rv; - - if (ksh_getopt(wp, &builtin_opt, null) == '?') - return 1; - s = pushs(SWORDS, ATEMP); - s->u.strv = wp + builtin_opt.optind; - if (!Flag(FPOSIX)) { - /* - * Handle case where the command is empty due to failed - * command substitution, eg, eval "$(false)". - * In this case, shell() will not set/change exstat (because - * compiled tree is empty), so will use this value. - * subst_exstat is cleared in execute(), so should be 0 if - * there were no substitutions. - * - * A strict reading of POSIX says we don't do this (though - * it is traditionally done). [from 1003.2-1992] - * 3.9.1: Simple Commands - * ... If there is a command name, execution shall - * continue as described in 3.9.1.1. If there - * is no command name, but the command contained a command - * substitution, the command shall complete with the exit - * status of the last command substitution - * 3.9.1.1: Command Search and Execution - * ...(1)...(a) If the command name matches the name of - * a special built-in utility, that special built-in - * utility shall be invoked. - * 3.14.5: Eval - * ... If there are no arguments, or only null arguments, - * eval shall return an exit status of zero. - */ - exstat = subst_exstat; - } - - rv = shell(s, FALSE); - afree(s, ATEMP); - return rv; -} - -int -c_trap(wp) - char **wp; -{ - int i; - char *s; - register Trap *p; - - if (ksh_getopt(wp, &builtin_opt, null) == '?') - return 1; - wp += builtin_opt.optind; - - if (*wp == NULL) { - int anydfl = 0; - - for (p = sigtraps, i = SIGNALS+1; --i >= 0; p++) { - if (p->trap == NULL) - anydfl = 1; - else { - shprintf("trap -- "); - print_value_quoted(p->trap); - shprintf(" %s\n", p->name); - } - } -#if 0 /* this is ugly and not clear POSIX needs it */ - /* POSIX may need this so output of trap can be saved and - * used to restore trap conditions - */ - if (anydfl) { - shprintf("trap -- -"); - for (p = sigtraps, i = SIGNALS+1; --i >= 0; p++) - if (p->trap == NULL && p->name) - shprintf(" %s", p->name); - shprintf(newline); - } -#else - __USE(anydfl); -#endif - return 0; - } - - /* - * Use case sensitive lookup for first arg so the - * command 'exit' isn't confused with the pseudo-signal - * 'EXIT'. - */ - s = (gettrap(*wp, FALSE) == NULL) ? *wp++ : NULL; /* get command */ - if (s != NULL && s[0] == '-' && s[1] == '\0') - s = NULL; - - /* set/clear traps */ - while (*wp != NULL) { - p = gettrap(*wp++, TRUE); - if (p == NULL) { - bi_errorf("bad signal %s", wp[-1]); - return 1; - } - settrap(p, s); - } - return 0; -} - -int -c_exitreturn(wp) - char **wp; -{ - int how = LEXIT; - int n; - char *arg; - - if (ksh_getopt(wp, &builtin_opt, null) == '?') - return 1; - arg = wp[builtin_opt.optind]; - - if (arg) { - if (!getn(arg, &n)) { - exstat = 1; - warningf(TRUE, "%s: bad number", arg); - } else - exstat = n; - } - if (wp[0][0] == 'r') { /* return */ - struct env *ep; - - /* need to tell if this is exit or return so trap exit will - * work right (POSIX) - */ - for (ep = e; ep; ep = ep->oenv) - if (STOP_RETURN(ep->type)) { - how = LRETURN; - break; - } - } - - if (how == LEXIT && !really_exit && j_stopped_running()) { - really_exit = 1; - how = LSHELL; - } - - quitenv(); /* get rid of any i/o redirections */ - unwind(how); - /*NOTREACHED*/ - return 0; -} - -int -c_brkcont(wp) - char **wp; -{ - int n, quit; - struct env *ep, *last_ep = (struct env *) 0; - char *arg; - - if (ksh_getopt(wp, &builtin_opt, null) == '?') - return 1; - arg = wp[builtin_opt.optind]; - - if (!arg) - n = 1; - else if (!bi_getn(arg, &n)) - return 1; - quit = n; - if (quit <= 0) { - /* at&t ksh does this for non-interactive shells only - weird */ - bi_errorf("%s: bad value", arg); - return 1; - } - - /* Stop at E_NONE, E_PARSE, E_FUNC, or E_INCL */ - for (ep = e; ep && !STOP_BRKCONT(ep->type); ep = ep->oenv) - if (ep->type == E_LOOP) { - if (--quit == 0) - break; - ep->flags |= EF_BRKCONT_PASS; - last_ep = ep; - } - - if (quit) { - /* at&t ksh doesn't print a message - just does what it - * can. We print a message 'cause it helps in debugging - * scripts, but don't generate an error (ie, keep going). - */ - if (n == quit) { - warningf(TRUE, "%s: cannot %s", wp[0], wp[0]); - return 0; - } - /* POSIX says if n is too big, the last enclosing loop - * shall be used. Doesn't say to print an error but we - * do anyway 'cause the user messed up. - */ - if (last_ep) - last_ep->flags &= ~EF_BRKCONT_PASS; - warningf(TRUE, "%s: can only %s %d level(s)", - wp[0], wp[0], n - quit); - } - - unwind(*wp[0] == 'b' ? LBREAK : LCONTIN); - /*NOTREACHED*/ -} - -int -c_set(wp) - char **wp; -{ - int argi, setargs; - struct block *l = e->loc; - register char **owp = wp; - - if (wp[1] == NULL) { - static const char *const args [] = { "set", "-", NULL }; - return c_typeset((char **)__UNCONST(args)); - } - - argi = parse_args(wp, OF_SET, &setargs); - if (argi < 0) - return 1; - /* set $# and $* */ - if (setargs) { - owp = wp += argi - 1; - wp[0] = l->argv[0]; /* save $0 */ - while (*++wp != NULL) - *wp = str_save(*wp, &l->area); - l->argc = wp - owp - 1; - l->argv = (char **) alloc(sizeofN(char *, l->argc+2), &l->area); - for (wp = l->argv; (*wp++ = *owp++) != NULL; ) - ; - } - /* POSIX says set exit status is 0, but old scripts that use - * getopt(1), use the construct: set -- `getopt ab:c "$@"` - * which assumes the exit value set will be that of the `` - * (subst_exstat is cleared in execute() so that it will be 0 - * if there are no command substitutions). - */ - return Flag(FPOSIX) ? 0 : subst_exstat; -} - -int -c_unset(wp) - char **wp; -{ - register char *id; - int optc, unset_var = 1; - int ret = 0; - - while ((optc = ksh_getopt(wp, &builtin_opt, "fv")) != EOF) - switch (optc) { - case 'f': - unset_var = 0; - break; - case 'v': - unset_var = 1; - break; - case '?': - return 1; - } - wp += builtin_opt.optind; - for (; (id = *wp) != NULL; wp++) - if (unset_var) { /* unset variable */ - struct tbl *vp = global(id); - - if (!(vp->flag & ISSET)) - ret = 1; - if ((vp->flag&RDONLY)) { - bi_errorf("%s is read only", vp->name); - return 1; - } - unset(vp, strchr(id, '[') ? 1 : 0); - } else { /* unset function */ - if (define(id, NULL)) - ret = 1; - } - return ret; -} - -int -c_times(wp) - char **wp; -{ - struct tms all; - - (void) ksh_times(&all); - shprintf("Shell: %8ss user ", clocktos(all.tms_utime)); - shprintf("%8ss system\n", clocktos(all.tms_stime)); - shprintf("Kids: %8ss user ", clocktos(all.tms_cutime)); - shprintf("%8ss system\n", clocktos(all.tms_cstime)); - - return 0; -} - -/* - * time pipeline (really a statement, not a built-in command) - */ -int -timex(t, f) - struct op *t; - int f; -{ -#define TF_NOARGS BIT(0) -#define TF_NOREAL BIT(1) /* don't report real time */ -#define TF_POSIX BIT(2) /* report in posix format */ - int rv = 0; - struct tms t0, t1, tms; - clock_t t0t, t1t = 0; - int tf = 0; - extern clock_t j_usrtime, j_systime; /* computed by j_wait */ - char opts[1]; - - t0t = ksh_times(&t0); - if (t->left) { - /* - * Two ways of getting cpu usage of a command: just use t0 - * and t1 (which will get cpu usage from other jobs that - * finish while we are executing t->left), or get the - * cpu usage of t->left. at&t ksh does the former, while - * pdksh tries to do the later (the j_usrtime hack doesn't - * really work as it only counts the last job). - */ - j_usrtime = j_systime = 0; - if (t->left->type == TCOM) - t->left->str = opts; - opts[0] = 0; - rv = execute(t->left, f | XTIME); - tf |= opts[0]; - t1t = ksh_times(&t1); - } else - tf = TF_NOARGS; - - if (tf & TF_NOARGS) { /* ksh93 - report shell times (shell+kids) */ - tf |= TF_NOREAL; - tms.tms_utime = t0.tms_utime + t0.tms_cutime; - tms.tms_stime = t0.tms_stime + t0.tms_cstime; - } else { - tms.tms_utime = t1.tms_utime - t0.tms_utime + j_usrtime; - tms.tms_stime = t1.tms_stime - t0.tms_stime + j_systime; - } - - if (!(tf & TF_NOREAL)) - shf_fprintf(shl_out, - tf & TF_POSIX ? "real %8s\n" : "%8ss real ", - clocktos(t1t - t0t)); - shf_fprintf(shl_out, tf & TF_POSIX ? "user %8s\n" : "%8ss user ", - clocktos(tms.tms_utime)); - shf_fprintf(shl_out, tf & TF_POSIX ? "sys %8s\n" : "%8ss system\n", - clocktos(tms.tms_stime)); - shf_flush(shl_out); - - return rv; -} - -void -timex_hook(t, app) - struct op *t; - char ** volatile *app; -{ - char **wp = *app; - int optc; - int i, j; - Getopt opt; - - ksh_getopt_reset(&opt, 0); - opt.optind = 0; /* start at the start */ - while ((optc = ksh_getopt(wp, &opt, ":p")) != EOF) - switch (optc) { - case 'p': - t->str[0] |= TF_POSIX; - break; - case '?': - errorf("time: -%s unknown option", opt.optarg); - case ':': - errorf("time: -%s requires an argument", - opt.optarg); - } - /* Copy command words down over options. */ - if (opt.optind != 0) { - for (i = 0; i < opt.optind; i++) - afree(wp[i], ATEMP); - for (i = 0, j = opt.optind; (wp[i] = wp[j]); i++, j++) - ; - } - if (!wp[0]) - t->str[0] |= TF_NOARGS; - *app = wp; -} - -static char * -clocktos(t) - clock_t t; -{ - static char temp[22]; /* enough for 64 bit clock_t */ - register int i; - register char *cp = temp + sizeof(temp); - - /* note: posix says must use max precision, ie, if clk_tck is - * 1000, must print 3 places after decimal (if non-zero, else 1). - */ - if (CLK_TCK != 100) /* convert to 1/100'ths */ - t = (t < (clock_t)(1000000000/CLK_TCK)) ? - (t * 100) / CLK_TCK : (t / CLK_TCK) * 100; - - *--cp = '\0'; - for (i = -2; i <= 0 || t > 0; i++) { - if (i == 0) - *--cp = '.'; - *--cp = '0' + (char)(t%10); - t /= 10; - } - return cp; -} - -/* exec with no args - args case is taken care of in comexec() */ -int -c_exec(wp) - char ** wp; -{ - int i; - - /* make sure redirects stay in place */ - if (e->savefd != NULL) { - for (i = 0; i < NUFILE; i++) { - if (e->savefd[i] > 0) - close(e->savefd[i]); - /* - * For ksh keep anything > 2 private, - * for sh, let them be (POSIX says what - * happens is unspecified and the bourne shell - * keeps them open). - */ -#ifdef KSH - if (i > 2 && e->savefd[i]) - fd_clexec(i); -#endif /* KSH */ - } - e->savefd = NULL; - } - return 0; -} - -/* dummy function, special case in comexec() */ -int -c_builtin(wp) - char ** wp; -{ - return 0; -} - -extern int c_test ARGS((char **wp)); /* in c_test.c */ -extern int c_ulimit ARGS((char **wp)); /* in c_ulimit.c */ - -/* A leading = means assignments before command are kept; - * a leading * means a POSIX special builtin; - * a leading + means a POSIX regular builtin - * (* and + should not be combined). - */ -const struct builtin shbuiltins [] = { - {"*=.", c_dot}, - {"*=:", c_label}, - {"[", c_test}, - {"*=break", c_brkcont}, - {"=builtin", c_builtin}, - {"*=continue", c_brkcont}, - {"*=eval", c_eval}, - {"*=exec", c_exec}, - {"*=exit", c_exitreturn}, - {"+false", c_label}, - {"*=return", c_exitreturn}, - {"*=set", c_set}, - {"*=shift", c_shift}, - {"=times", c_times}, - {"*=trap", c_trap}, - {"+=wait", c_wait}, - {"+read", c_read}, - {"test", c_test}, - {"+true", c_label}, - {"ulimit", c_ulimit}, - {"+umask", c_umask}, - {"*=unset", c_unset}, -#ifdef OS2 - /* In OS2, the first line of a file can be "extproc name", which - * tells the command interpreter (cmd.exe) to use name to execute - * the file. For this to be useful, ksh must ignore commands - * starting with extproc and this does the trick... - */ - {"extproc", c_label}, -#endif /* OS2 */ - {NULL, NULL} -}; diff --git a/bin/ksh/c_test.c b/bin/ksh/c_test.c deleted file mode 100644 index 41e10fed5..000000000 --- a/bin/ksh/c_test.c +++ /dev/null @@ -1,666 +0,0 @@ -/* $NetBSD: c_test.c,v 1.6 2005/06/26 19:09:00 christos Exp $ */ - -/* - * test(1); version 7-like -- author Erik Baalbergen - * modified by Eric Gisin to be used as built-in. - * modified by Arnold Robbins to add SVR3 compatibility - * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket). - * modified by Michael Rendell to add Korn's [[ .. ]] expressions. - * modified by J.T. Conklin to add POSIX compatibility. - */ -#include - -#ifndef lint -__RCSID("$NetBSD: c_test.c,v 1.6 2005/06/26 19:09:00 christos Exp $"); -#endif - - -#include "sh.h" -#include "ksh_stat.h" -#include "c_test.h" - -/* test(1) accepts the following grammar: - oexpr ::= aexpr | aexpr "-o" oexpr ; - aexpr ::= nexpr | nexpr "-a" aexpr ; - nexpr ::= primary | "!" nexpr ; - primary ::= unary-operator operand - | operand binary-operator operand - | operand - | "(" oexpr ")" - ; - - unary-operator ::= "-a"|"-r"|"-w"|"-x"|"-e"|"-f"|"-d"|"-c"|"-b"|"-p"| - "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"| - "-L"|"-h"|"-S"|"-H"; - - binary-operator ::= "="|"=="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"| - "-nt"|"-ot"|"-ef"| - "<"|">" # rules used for [[ .. ]] expressions - ; - operand ::= -*/ - -#define T_ERR_EXIT 2 /* POSIX says > 1 for errors */ - -struct t_op { - char op_text[4]; - Test_op op_num; -}; -static const struct t_op u_ops [] = { - {"-a", TO_FILAXST }, - {"-b", TO_FILBDEV }, - {"-c", TO_FILCDEV }, - {"-d", TO_FILID }, - {"-e", TO_FILEXST }, - {"-f", TO_FILREG }, - {"-G", TO_FILGID }, - {"-g", TO_FILSETG }, - {"-h", TO_FILSYM }, - {"-H", TO_FILCDF }, - {"-k", TO_FILSTCK }, - {"-L", TO_FILSYM }, - {"-n", TO_STNZE }, - {"-O", TO_FILUID }, - {"-o", TO_OPTION }, - {"-p", TO_FILFIFO }, - {"-r", TO_FILRD }, - {"-s", TO_FILGZ }, - {"-S", TO_FILSOCK }, - {"-t", TO_FILTT }, - {"-u", TO_FILSETU }, - {"-w", TO_FILWR }, - {"-x", TO_FILEX }, - {"-z", TO_STZER }, - {"", TO_NONOP } - }; -static const struct t_op b_ops [] = { - {"=", TO_STEQL }, -#ifdef KSH - {"==", TO_STEQL }, -#endif /* KSH */ - {"!=", TO_STNEQ }, - {"<", TO_STLT }, - {">", TO_STGT }, - {"-eq", TO_INTEQ }, - {"-ne", TO_INTNE }, - {"-gt", TO_INTGT }, - {"-ge", TO_INTGE }, - {"-lt", TO_INTLT }, - {"-le", TO_INTLE }, - {"-ef", TO_FILEQ }, - {"-nt", TO_FILNT }, - {"-ot", TO_FILOT }, - {"", TO_NONOP } - }; - -static int test_stat ARGS((const char *, struct stat *)); -static int test_eaccess ARGS((const char *, int)); -static int test_oexpr ARGS((Test_env *, int)); -static int test_aexpr ARGS((Test_env *, int)); -static int test_nexpr ARGS((Test_env *, int)); -static int test_primary ARGS((Test_env *, int)); -static int ptest_isa ARGS((Test_env *, Test_meta)); -static const char *ptest_getopnd ARGS((Test_env *, Test_op, int)); -static int ptest_eval ARGS((Test_env *, Test_op, const char *, - const char *, int)); -static void ptest_error ARGS((Test_env *, int, const char *)); - -int -c_test(wp) - char **wp; -{ - int argc; - int res; - Test_env te; - - te.flags = 0; - te.isa = ptest_isa; - te.getopnd = ptest_getopnd; - te.eval = ptest_eval; - te.error = ptest_error; - - for (argc = 0; wp[argc]; argc++) - ; - - if (strcmp(wp[0], "[") == 0) { - if (strcmp(wp[--argc], "]") != 0) { - bi_errorf("missing ]"); - return T_ERR_EXIT; - } - } - - te.pos.wp = wp + 1; - te.wp_end = wp + argc; - - /* - * Handle the special cases from POSIX.2, section 4.62.4. - * Implementation of all the rules isn't necessary since - * our parser does the right thing for the omitted steps. - */ - if (argc <= 5) { - char **owp = wp; - int invert = 0; - Test_op op; - const char *opnd1, *opnd2; - - while (--argc >= 0) { - if ((*te.isa)(&te, TM_END)) - return !0; - if (argc == 3) { - opnd1 = (*te.getopnd)(&te, TO_NONOP, 1); - if ((op = (Test_op) (*te.isa)(&te, TM_BINOP))) { - opnd2 = (*te.getopnd)(&te, op, 1); - res = (*te.eval)(&te, op, opnd1, opnd2, - 1); - if (te.flags & TEF_ERROR) - return T_ERR_EXIT; - if (invert & 1) - res = !res; - return !res; - } - /* back up to opnd1 */ - te.pos.wp--; - } - if (argc == 1) { - opnd1 = (*te.getopnd)(&te, TO_NONOP, 1); - /* Historically, -t by itself test if fd 1 - * is a file descriptor, but POSIX says its - * a string test... - */ - if (!Flag(FPOSIX) && strcmp(opnd1, "-t") == 0) - break; - res = (*te.eval)(&te, TO_STNZE, opnd1, - (char *) 0, 1); - if (invert & 1) - res = !res; - return !res; - } - if ((*te.isa)(&te, TM_NOT)) { - invert++; - } else - break; - } - te.pos.wp = owp + 1; - } - - return test_parse(&te); -} - -/* - * Generic test routines. - */ - -Test_op -test_isop(te, meta, s) - Test_env *te; - Test_meta meta; - const char *s; -{ - char sc1; - const struct t_op *otab; - - otab = meta == TM_UNOP ? u_ops : b_ops; - if (*s) { - sc1 = s[1]; - for (; otab->op_text[0]; otab++) - if (sc1 == otab->op_text[1] - && strcmp(s, otab->op_text) == 0 - && ((te->flags & TEF_DBRACKET) - || (otab->op_num != TO_STLT - && otab->op_num != TO_STGT))) - return otab->op_num; - } - return TO_NONOP; -} - -int -test_eval(te, op, opnd1, opnd2, do_eval) - Test_env *te; - Test_op op; - const char *opnd1; - const char *opnd2; - int do_eval; -{ - int res; - int not; - struct stat b1, b2; - - if (!do_eval) - return 0; - - switch ((int) op) { - /* - * Unary Operators - */ - case TO_STNZE: /* -n */ - return *opnd1 != '\0'; - case TO_STZER: /* -z */ - return *opnd1 == '\0'; - case TO_OPTION: /* -o */ - if ((not = *opnd1 == '!')) - opnd1++; - if ((res = option(opnd1)) < 0) - res = 0; - else { - res = Flag(res); - if (not) - res = !res; - } - return res; - case TO_FILRD: /* -r */ - return test_eaccess(opnd1, R_OK) == 0; - case TO_FILWR: /* -w */ - return test_eaccess(opnd1, W_OK) == 0; - case TO_FILEX: /* -x */ - return test_eaccess(opnd1, X_OK) == 0; - case TO_FILAXST: /* -a */ - return test_stat(opnd1, &b1) == 0; - case TO_FILEXST: /* -e */ - /* at&t ksh does not appear to do the /dev/fd/ thing for - * this (unless the os itself handles it) - */ - return stat(opnd1, &b1) == 0; - case TO_FILREG: /* -r */ - return test_stat(opnd1, &b1) == 0 && S_ISREG(b1.st_mode); - case TO_FILID: /* -d */ - return test_stat(opnd1, &b1) == 0 && S_ISDIR(b1.st_mode); - case TO_FILCDEV: /* -c */ -#ifdef S_ISCHR - return test_stat(opnd1, &b1) == 0 && S_ISCHR(b1.st_mode); -#else - return 0; -#endif - case TO_FILBDEV: /* -b */ -#ifdef S_ISBLK - return test_stat(opnd1, &b1) == 0 && S_ISBLK(b1.st_mode); -#else - return 0; -#endif - case TO_FILFIFO: /* -p */ -#ifdef S_ISFIFO - return test_stat(opnd1, &b1) == 0 && S_ISFIFO(b1.st_mode); -#else - return 0; -#endif - case TO_FILSYM: /* -h -L */ -#ifdef S_ISLNK - return lstat(opnd1, &b1) == 0 && S_ISLNK(b1.st_mode); -#else - return 0; -#endif - case TO_FILSOCK: /* -S */ -#ifdef S_ISSOCK - return test_stat(opnd1, &b1) == 0 && S_ISSOCK(b1.st_mode); -#else - return 0; -#endif - case TO_FILCDF:/* -H HP context dependent files (directories) */ -#ifdef S_ISCDF - { - /* Append a + to filename and check to see if result is a - * setuid directory. CDF stuff in general is hookey, since - * it breaks for the following sequence: echo hi > foo+; - * mkdir foo; echo bye > foo/default; chmod u+s foo - * (foo+ refers to the file with hi in it, there is no way - * to get at the file with bye in it - please correct me if - * I'm wrong about this). - */ - int len = strlen(opnd1); - char *p = str_nsave(opnd1, len + 1, ATEMP); - - p[len++] = '+'; - p[len] = '\0'; - return stat(p, &b1) == 0 && S_ISCDF(b1.st_mode); - } -#else - return 0; -#endif - case TO_FILSETU: /* -u */ -#ifdef S_ISUID - return test_stat(opnd1, &b1) == 0 - && (b1.st_mode & S_ISUID) == S_ISUID; -#else - return 0; -#endif - case TO_FILSETG: /* -g */ -#ifdef S_ISGID - return test_stat(opnd1, &b1) == 0 - && (b1.st_mode & S_ISGID) == S_ISGID; -#else - return 0; -#endif - case TO_FILSTCK: /* -k */ - return test_stat(opnd1, &b1) == 0 - && (b1.st_mode & S_ISVTX) == S_ISVTX; - case TO_FILGZ: /* -s */ - return test_stat(opnd1, &b1) == 0 && b1.st_size > 0L; - case TO_FILTT: /* -t */ - if (opnd1 && !bi_getn(opnd1, &res)) { - te->flags |= TEF_ERROR; - res = 0; - } else { - /* generate error if in FPOSIX mode? */ - res = isatty(opnd1 ? res : 0); - } - return res; - case TO_FILUID: /* -O */ - return test_stat(opnd1, &b1) == 0 && b1.st_uid == ksheuid; - case TO_FILGID: /* -G */ - return test_stat(opnd1, &b1) == 0 && b1.st_gid == getegid(); - /* - * Binary Operators - */ - case TO_STEQL: /* = */ - if (te->flags & TEF_DBRACKET) - return gmatch(opnd1, opnd2, FALSE); - return strcmp(opnd1, opnd2) == 0; - case TO_STNEQ: /* != */ - if (te->flags & TEF_DBRACKET) - return !gmatch(opnd1, opnd2, FALSE); - return strcmp(opnd1, opnd2) != 0; - case TO_STLT: /* < */ - return strcmp(opnd1, opnd2) < 0; - case TO_STGT: /* > */ - return strcmp(opnd1, opnd2) > 0; - case TO_INTEQ: /* -eq */ - case TO_INTNE: /* -ne */ - case TO_INTGE: /* -ge */ - case TO_INTGT: /* -gt */ - case TO_INTLE: /* -le */ - case TO_INTLT: /* -lt */ - { - long v1, v2; - - if (!evaluate(opnd1, &v1, KSH_RETURN_ERROR) - || !evaluate(opnd2, &v2, KSH_RETURN_ERROR)) - { - /* error already printed.. */ - te->flags |= TEF_ERROR; - return 1; - } - switch ((int) op) { - case TO_INTEQ: - return v1 == v2; - case TO_INTNE: - return v1 != v2; - case TO_INTGE: - return v1 >= v2; - case TO_INTGT: - return v1 > v2; - case TO_INTLE: - return v1 <= v2; - case TO_INTLT: - return v1 < v2; - } - } - case TO_FILNT: /* -nt */ - { - int s2; - /* ksh88/ksh93 succeed if file2 can't be stated - * (subtly different from `does not exist'). - */ - return stat(opnd1, &b1) == 0 - && (((s2 = stat(opnd2, &b2)) == 0 - && b1.st_mtime > b2.st_mtime) || s2 < 0); - } - case TO_FILOT: /* -ot */ - { - int s1; - /* ksh88/ksh93 succeed if file1 can't be stated - * (subtly different from `does not exist'). - */ - return stat(opnd2, &b2) == 0 - && (((s1 = stat(opnd1, &b1)) == 0 - && b1.st_mtime < b2.st_mtime) || s1 < 0); - } - case TO_FILEQ: /* -ef */ - return stat (opnd1, &b1) == 0 && stat (opnd2, &b2) == 0 - && b1.st_dev == b2.st_dev - && b1.st_ino == b2.st_ino; - } - (*te->error)(te, 0, "internal error: unknown op"); - return 1; -} - -/* Nasty kludge to handle Korn's bizarre /dev/fd hack */ -static int -test_stat(pathx, statb) - const char *pathx; - struct stat *statb; -{ -#if !defined(HAVE_DEV_FD) - int fd; - - if (strncmp(pathx, "/dev/fd/", 8) == 0 && getn(pathx + 8, &fd)) - return fstat(fd, statb); -#endif /* !HAVE_DEV_FD */ - - return stat(pathx, statb); -} - -/* Routine to handle Korn's /dev/fd hack, and to deal with X_OK on - * non-directories when running as root. - */ -static int -test_eaccess(pathx, mode) - const char *pathx; - int mode; -{ - int res; - -#if !defined(HAVE_DEV_FD) - int fd; - - /* Note: doesn't handle //dev/fd, etc.. (this is ok) */ - if (strncmp(pathx, "/dev/fd/", 8) == 0 && getn(pathx + 8, &fd)) { - int flags; - - if ((flags = fcntl(fd, F_GETFL, 0)) < 0 - || (mode & X_OK) - || ((mode & W_OK) && (flags & O_ACCMODE) == O_RDONLY) - || ((mode & R_OK) && (flags & O_ACCMODE) == O_WRONLY)) - return -1; - return 0; - } -#endif /* !HAVE_DEV_FD */ - - res = eaccess(pathx, mode); - /* - * On most (all?) unixes, access() says everything is executable for - * root - avoid this on files by using stat(). - */ - if (res == 0 && ksheuid == 0 && (mode & X_OK)) { - struct stat statb; - - if (stat(pathx, &statb) < 0) - res = -1; - else if (S_ISDIR(statb.st_mode)) - res = 0; - else - res = (statb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) - ? 0 : -1; - } - - return res; -} - -int -test_parse(te) - Test_env *te; -{ - int res; - - res = test_oexpr(te, 1); - - if (!(te->flags & TEF_ERROR) && !(*te->isa)(te, TM_END)) - (*te->error)(te, 0, "unexpected operator/operand"); - - return (te->flags & TEF_ERROR) ? T_ERR_EXIT : !res; -} - -static int -test_oexpr(te, do_eval) - Test_env *te; - int do_eval; -{ - int res; - - res = test_aexpr(te, do_eval); - if (res) - do_eval = 0; - if (!(te->flags & TEF_ERROR) && (*te->isa)(te, TM_OR)) - return test_oexpr(te, do_eval) || res; - return res; -} - -static int -test_aexpr(te, do_eval) - Test_env *te; - int do_eval; -{ - int res; - - res = test_nexpr(te, do_eval); - if (!res) - do_eval = 0; - if (!(te->flags & TEF_ERROR) && (*te->isa)(te, TM_AND)) - return test_aexpr(te, do_eval) && res; - return res; -} - -static int -test_nexpr(te, do_eval) - Test_env *te; - int do_eval; -{ - if (!(te->flags & TEF_ERROR) && (*te->isa)(te, TM_NOT)) - return !test_nexpr(te, do_eval); - return test_primary(te, do_eval); -} - -static int -test_primary(te, do_eval) - Test_env *te; - int do_eval; -{ - const char *opnd1, *opnd2; - int res; - Test_op op; - - if (te->flags & TEF_ERROR) - return 0; - if ((*te->isa)(te, TM_OPAREN)) { - res = test_oexpr(te, do_eval); - if (te->flags & TEF_ERROR) - return 0; - if (!(*te->isa)(te, TM_CPAREN)) { - (*te->error)(te, 0, "missing closing paren"); - return 0; - } - return res; - } - if ((op = (Test_op) (*te->isa)(te, TM_UNOP))) { - /* unary expression */ - opnd1 = (*te->getopnd)(te, op, do_eval); - if (!opnd1) { - (*te->error)(te, -1, "missing argument"); - return 0; - } - - return (*te->eval)(te, op, opnd1, (const char *) 0, do_eval); - } - opnd1 = (*te->getopnd)(te, TO_NONOP, do_eval); - if (!opnd1) { - (*te->error)(te, 0, "expression expected"); - return 0; - } - if ((op = (Test_op) (*te->isa)(te, TM_BINOP))) { - /* binary expression */ - opnd2 = (*te->getopnd)(te, op, do_eval); - if (!opnd2) { - (*te->error)(te, -1, "missing second argument"); - return 0; - } - - return (*te->eval)(te, op, opnd1, opnd2, do_eval); - } - if (te->flags & TEF_DBRACKET) { - (*te->error)(te, -1, "missing expression operator"); - return 0; - } - return (*te->eval)(te, TO_STNZE, opnd1, (const char *) 0, do_eval); -} - -/* - * Plain test (test and [ .. ]) specific routines. - */ - -/* Test if the current token is a whatever. Accepts the current token if - * it is. Returns 0 if it is not, non-zero if it is (in the case of - * TM_UNOP and TM_BINOP, the returned value is a Test_op). - */ -static int -ptest_isa(te, meta) - Test_env *te; - Test_meta meta; -{ - /* Order important - indexed by Test_meta values */ - static const char *const tokens[] = { - "-o", "-a", "!", "(", ")" - }; - int ret; - - if (te->pos.wp >= te->wp_end) - return meta == TM_END; - - if (meta == TM_UNOP || meta == TM_BINOP) - ret = (int) test_isop(te, meta, *te->pos.wp); - else if (meta == TM_END) - ret = 0; - else - ret = strcmp(*te->pos.wp, tokens[(int) meta]) == 0; - - /* Accept the token? */ - if (ret) - te->pos.wp++; - - return ret; -} - -static const char * -ptest_getopnd(te, op, do_eval) - Test_env *te; - Test_op op; - int do_eval; -{ - if (te->pos.wp >= te->wp_end) - return op == TO_FILTT ? "1" : (const char *) 0; - return *te->pos.wp++; -} - -static int -ptest_eval(te, op, opnd1, opnd2, do_eval) - Test_env *te; - Test_op op; - const char *opnd1; - const char *opnd2; - int do_eval; -{ - return test_eval(te, op, opnd1, opnd2, do_eval); -} - -static void -ptest_error(te, offset, msg) - Test_env *te; - int offset; - const char *msg; -{ - const char *op = te->pos.wp + offset >= te->wp_end ? - (const char *) 0 : te->pos.wp[offset]; - - te->flags |= TEF_ERROR; - if (op) - bi_errorf("%s: %s", op, msg); - else - bi_errorf("%s", msg); -} diff --git a/bin/ksh/c_test.h b/bin/ksh/c_test.h deleted file mode 100644 index f1182f3f6..000000000 --- a/bin/ksh/c_test.h +++ /dev/null @@ -1,55 +0,0 @@ -/* $NetBSD: c_test.h,v 1.3 2004/07/07 19:20:09 mycroft Exp $ */ - -/* Various types of operations. Keeping things grouped nicely - * (unary,binary) makes switch() statements more efficient. - */ -enum Test_op { - TO_NONOP = 0, /* non-operator */ - /* unary operators */ - TO_STNZE, TO_STZER, TO_OPTION, - TO_FILAXST, - TO_FILEXST, - TO_FILREG, TO_FILBDEV, TO_FILCDEV, TO_FILSYM, TO_FILFIFO, TO_FILSOCK, - TO_FILCDF, TO_FILID, TO_FILGID, TO_FILSETG, TO_FILSTCK, TO_FILUID, - TO_FILRD, TO_FILGZ, TO_FILTT, TO_FILSETU, TO_FILWR, TO_FILEX, - /* binary operators */ - TO_STEQL, TO_STNEQ, TO_STLT, TO_STGT, TO_INTEQ, TO_INTNE, TO_INTGT, - TO_INTGE, TO_INTLT, TO_INTLE, TO_FILEQ, TO_FILNT, TO_FILOT -}; -typedef enum Test_op Test_op; - -/* Used by Test_env.isa() (order important - used to index *_tokens[] arrays) */ -enum Test_meta { - TM_OR, /* -o or || */ - TM_AND, /* -a or && */ - TM_NOT, /* ! */ - TM_OPAREN, /* ( */ - TM_CPAREN, /* ) */ - TM_UNOP, /* unary operator */ - TM_BINOP, /* binary operator */ - TM_END /* end of input */ -}; -typedef enum Test_meta Test_meta; - -#define TEF_ERROR BIT(0) /* set if we've hit an error */ -#define TEF_DBRACKET BIT(1) /* set if [[ .. ]] test */ - -typedef struct test_env Test_env; -struct test_env { - int flags; /* TEF_* */ - union { - char **wp; /* used by ptest_* */ - XPtrV *av; /* used by dbtestp_* */ - } pos; - char **wp_end; /* used by ptest_* */ - int (*isa) ARGS((Test_env *te, Test_meta meta)); - const char *(*getopnd) ARGS((Test_env *te, Test_op op, int do_eval)); - int (*eval) ARGS((Test_env *te, Test_op op, const char *opnd1, - const char *opnd2, int do_eval)); - void (*error) ARGS((Test_env *te, int offset, const char *msg)); -}; - -Test_op test_isop ARGS((Test_env *te, Test_meta meta, const char *s)); -int test_eval ARGS((Test_env *te, Test_op op, const char *opnd1, - const char *opnd2, int do_eval)); -int test_parse ARGS((Test_env *te)); diff --git a/bin/ksh/c_ulimit.c b/bin/ksh/c_ulimit.c deleted file mode 100644 index 08da473bf..000000000 --- a/bin/ksh/c_ulimit.c +++ /dev/null @@ -1,292 +0,0 @@ -/* $NetBSD: c_ulimit.c,v 1.12 2015/05/09 13:26:06 christos Exp $ */ - -/* - ulimit -- handle "ulimit" builtin - - Reworked to use getrusage() and ulimit() at once (as needed on - some schizophrenic systems, eg, HP-UX 9.01), made argument parsing - conform to at&t ksh, added autoconf support. Michael Rendell, May, '94 - - Eric Gisin, September 1988 - Adapted to PD KornShell. Removed AT&T code. - - last edit: 06-Jun-1987 D A Gwyn - - This started out as the BRL UNIX System V system call emulation - for 4.nBSD, and was later extended by Doug Kingston to handle - the extended 4.nBSD resource limits. It now includes the code - that was originally under case SYSULIMIT in source file "xec.c". -*/ -#include - -#ifndef lint -__RCSID("$NetBSD: c_ulimit.c,v 1.12 2015/05/09 13:26:06 christos Exp $"); -#endif - - -#include "sh.h" -#include "ksh_time.h" -#ifdef HAVE_SYS_RESOURCE_H -# include -#endif /* HAVE_SYS_RESOURCE_H */ -#ifdef HAVE_ULIMIT_H -# include -#else /* HAVE_ULIMIT_H */ -# ifdef HAVE_ULIMIT -extern long ulimit(); -# endif /* HAVE_ULIMIT */ -#endif /* HAVE_ULIMIT_H */ - -#define SOFT 0x1 -#define HARD 0x2 - -#ifdef RLIM_INFINITY -# define KSH_RLIM_INFINITY RLIM_INFINITY -#else -# define KSH_RLIM_INFINITY ((rlim_t) 1 << (sizeof(rlim_t) * 8 - 1) - 1) -#endif /* RLIM_INFINITY */ - -int -c_ulimit(wp) - char **wp; -{ - static const struct limits { - const char *name; - enum { RLIMIT, ULIMIT } which; - int gcmd; /* get command */ - int scmd; /* set command (or -1, if no set command) */ - int factor; /* multiply by to get rlim_{cur,max} values */ - char option; - } limits[] = { - /* Do not use options -H, -S or -a */ -#ifdef RLIMIT_CPU - { "time(cpu-seconds)", RLIMIT, RLIMIT_CPU, RLIMIT_CPU, 1, 't' }, -#endif -#ifdef RLIMIT_FSIZE - { "file(blocks)", RLIMIT, RLIMIT_FSIZE, RLIMIT_FSIZE, 512, 'f' }, -#else /* RLIMIT_FSIZE */ -# ifdef UL_GETFSIZE /* x/open */ - { "file(blocks)", ULIMIT, UL_GETFSIZE, UL_SETFSIZE, 1, 'f' }, -# else /* UL_GETFSIZE */ -# ifdef UL_GFILLIM /* svr4/xenix */ - { "file(blocks)", ULIMIT, UL_GFILLIM, UL_SFILLIM, 1, 'f' }, -# else /* UL_GFILLIM */ - { "file(blocks)", ULIMIT, 1, 2, 1, 'f' }, -# endif /* UL_GFILLIM */ -# endif /* UL_GETFSIZE */ -#endif /* RLIMIT_FSIZE */ -#ifdef RLIMIT_CORE - { "coredump(blocks)", RLIMIT, RLIMIT_CORE, RLIMIT_CORE, 512, 'c' }, -#endif -#ifdef RLIMIT_DATA - { "data(kbytes)", RLIMIT, RLIMIT_DATA, RLIMIT_DATA, 1024, 'd' }, -#endif -#ifdef RLIMIT_STACK - { "stack(kbytes)", RLIMIT, RLIMIT_STACK, RLIMIT_STACK, 1024, 's' }, -#endif -#ifdef RLIMIT_MEMLOCK - { "lockedmem(kbytes)", RLIMIT, RLIMIT_MEMLOCK, RLIMIT_MEMLOCK, 1024, 'l' }, -#endif -#ifdef RLIMIT_RSS - { "memory(kbytes)", RLIMIT, RLIMIT_RSS, RLIMIT_RSS, 1024, 'm' }, -#endif -#ifdef RLIMIT_NOFILE - { "nofiles(descriptors)", RLIMIT, RLIMIT_NOFILE, RLIMIT_NOFILE, 1, 'n' }, -#else /* RLIMIT_NOFILE */ -# ifdef UL_GDESLIM /* svr4/xenix */ - { "nofiles(descriptors)", ULIMIT, UL_GDESLIM, -1, 1, 'n' }, -# endif /* UL_GDESLIM */ -#endif /* RLIMIT_NOFILE */ -#ifdef RLIMIT_NPROC - { "processes", RLIMIT, RLIMIT_NPROC, RLIMIT_NPROC, 1, 'p' }, -#endif -#ifdef RLIMIT_NTHR - { "threads", RLIMIT, RLIMIT_NTHR, RLIMIT_NTHR, 1, 'r' }, -#endif -#ifdef RLIMIT_VMEM - { "vmemory(kbytes)", RLIMIT, RLIMIT_VMEM, RLIMIT_VMEM, 1024, 'v' }, -#else /* RLIMIT_VMEM */ - /* These are not quite right - really should subtract etext or something */ -# ifdef UL_GMEMLIM /* svr4/xenix */ - { "vmemory(maxaddr)", ULIMIT, UL_GMEMLIM, -1, 1, 'v' }, -# else /* UL_GMEMLIM */ -# ifdef UL_GETBREAK /* osf/1 */ - { "vmemory(maxaddr)", ULIMIT, UL_GETBREAK, -1, 1, 'v' }, -# else /* UL_GETBREAK */ -# ifdef UL_GETMAXBRK /* hpux */ - { "vmemory(maxaddr)", ULIMIT, UL_GETMAXBRK, -1, 1, 'v' }, -# endif /* UL_GETMAXBRK */ -# endif /* UL_GETBREAK */ -# endif /* UL_GMEMLIM */ -#endif /* RLIMIT_VMEM */ -#ifdef RLIMIT_SWAP - { "swap(kbytes)", RLIMIT, RLIMIT_SWAP, RLIMIT_SWAP, 1024, 'w' }, -#endif -#ifdef RLIMIT_SBSIZE - { "sbsize(bytes)", RLIMIT, RLIMIT_SBSIZE, RLIMIT_SBSIZE, 1, 'b' }, -#endif - { .name = NULL } - }; - static char options[3 + NELEM(limits)]; - rlim_t UNINITIALIZED(val); - int how = SOFT | HARD; - const struct limits *l; - int set, all = 0; - int optc, what; -#ifdef HAVE_SETRLIMIT - struct rlimit limit; -#endif /* HAVE_SETRLIMIT */ - - if (!options[0]) { - /* build options string on first call - yuck */ - char *p = options; - - *p++ = 'H'; *p++ = 'S'; *p++ = 'a'; - for (l = limits; l->name; l++) - *p++ = l->option; - *p = '\0'; - } - what = 'f'; - while ((optc = ksh_getopt(wp, &builtin_opt, options)) != EOF) - switch (optc) { - case 'H': - how = HARD; - break; - case 'S': - how = SOFT; - break; - case 'a': - all = 1; - break; - case '?': - return 1; - default: - what = optc; - } - - for (l = limits; l->name && l->option != what; l++) - ; - if (!l->name) { - internal_errorf(0, "ulimit: %c", what); - return 1; - } - - wp += builtin_opt.optind; - set = *wp ? 1 : 0; - if (set) { - if (all || wp[1]) { - bi_errorf("too many arguments"); - return 1; - } - if (strcmp(wp[0], "unlimited") == 0) - val = KSH_RLIM_INFINITY; - else { - long rval; - - if (!evaluate(wp[0], &rval, KSH_RETURN_ERROR)) - return 1; - /* Avoid problems caused by typos that - * evaluate misses due to evaluating unset - * parameters to 0... - * If this causes problems, will have to - * add parameter to evaluate() to control - * if unset params are 0 or an error. - */ - if (!rval && !digit(wp[0][0])) { - bi_errorf("invalid limit: %s", wp[0]); - return 1; - } - val = (u_long)rval * l->factor; - } - } - if (all) { - for (l = limits; l->name; l++) { -#ifdef HAVE_SETRLIMIT - if (l->which == RLIMIT) { - if (getrlimit(l->gcmd, &limit) == -1) { - bi_errorf("can't get limit: %s", - strerror(errno)); - return 1; - } - if (how & SOFT) - val = limit.rlim_cur; - else if (how & HARD) - val = limit.rlim_max; - } else -#endif /* HAVE_SETRLIMIT */ -#ifdef HAVE_ULIMIT - { - val = ulimit(l->gcmd, (rlim_t) 0); - } -#else /* HAVE_ULIMIT */ - ; -#endif /* HAVE_ULIMIT */ - shprintf("%-20s ", l->name); -#ifdef RLIM_INFINITY - if (val == RLIM_INFINITY) - shprintf("unlimited\n"); - else -#endif /* RLIM_INFINITY */ - { - val /= l->factor; - shprintf("%ld\n", (long) val); - } - } - return 0; - } -#ifdef HAVE_SETRLIMIT - if (l->which == RLIMIT) { - if (getrlimit(l->gcmd, &limit) == -1) { - bi_errorf("can't get limit: %s", strerror(errno)); - return 1; - } - if (set) { - if (how & SOFT) - limit.rlim_cur = val; - if (how & HARD) - limit.rlim_max = val; - if (setrlimit(l->scmd, &limit) < 0) { - if (errno == EPERM) - bi_errorf("exceeds allowable limit"); - else - bi_errorf("bad limit: %s", - strerror(errno)); - return 1; - } - } else { - if (how & SOFT) - val = limit.rlim_cur; - else if (how & HARD) - val = limit.rlim_max; - } - } else -#endif /* HAVE_SETRLIMIT */ -#ifdef HAVE_ULIMIT - { - if (set) { - if (l->scmd == -1) { - bi_errorf("can't change limit"); - return 1; - } else if (ulimit(l->scmd, val) < 0) { - bi_errorf("bad limit: %s", strerror(errno)); - return 1; - } - } else - val = ulimit(l->gcmd, (rlim_t) 0); - } -#else /* HAVE_ULIMIT */ - ; -#endif /* HAVE_ULIMIT */ - if (!set) { -#ifdef RLIM_INFINITY - if (val == RLIM_INFINITY) - shprintf("unlimited\n"); - else -#endif /* RLIM_INFINITY */ - { - val /= l->factor; - shprintf("%ld\n", (long) val); - } - } - return 0; -} diff --git a/bin/ksh/conf-end.h b/bin/ksh/conf-end.h deleted file mode 100644 index 67451f1c9..000000000 --- a/bin/ksh/conf-end.h +++ /dev/null @@ -1,57 +0,0 @@ -/* $NetBSD: conf-end.h,v 1.2 1997/01/12 19:11:43 tls Exp $ */ - -/* - * End of configuration stuff for PD ksh. - * - * RCSid: $NetBSD: conf-end.h,v 1.2 1997/01/12 19:11:43 tls Exp $ - */ - -#if defined(EMACS) || defined(VI) -# define EDIT -#else -# undef EDIT -#endif - -/* Editing implies history */ -#if defined(EDIT) && !defined(HISTORY) -# define HISTORY -#endif /* EDIT */ - -/* - * if you don't have mmap() you can't use Peter Collinson's history - * mechanism. If that is the case, then define EASY_HISTORY - */ -#if defined(HISTORY) && (!defined(COMPLEX_HISTORY) || !defined(HAVE_MMAP) || !defined(HAVE_FLOCK)) -# undef COMPLEX_HISTORY -# define EASY_HISTORY /* sjg's trivial history file */ -#endif - -/* Can we safely catch sigchld and wait for processes? */ -#if (defined(HAVE_WAITPID) || defined(HAVE_WAIT3)) \ - && (defined(POSIX_SIGNALS) || defined(BSD42_SIGNALS)) -# define JOB_SIGS -#endif - -#if !defined(JOB_SIGS) || !(defined(POSIX_PGRP) || defined(BSD_PGRP)) -# undef JOBS /* if no JOB_SIGS, no job control support */ -#endif - -/* pdksh assumes system calls return EINTR if a signal happened (this so - * the signal handler doesn't have to longjmp()). I don't know if this - * happens (or can be made to happen) with sigset() et. al. (the bsd41 signal - * routines), so, the autoconf stuff checks what they do and defines - * SIGNALS_DONT_INTERRUPT if signals don't interrupt read(). - * If SIGNALS_DONT_INTERRUPT isn't defined and your compiler chokes on this, - * delete the hash in front of the error (and file a bug report). - */ -#ifdef SIGNALS_DONT_INTERRUPT - # error pdksh needs interruptable system calls. -#endif /* SIGNALS_DONT_INTERRUPT */ - -#ifdef HAVE_GCC_FUNC_ATTR -# define GCC_FUNC_ATTR(x) __attribute__((x)) -# define GCC_FUNC_ATTR2(x,y) __attribute__((x,y)) -#else -# define GCC_FUNC_ATTR(x) -# define GCC_FUNC_ATTR2(x,y) -#endif /* HAVE_GCC_FUNC_ATTR */ diff --git a/bin/ksh/config.h b/bin/ksh/config.h deleted file mode 100644 index 37bae4a28..000000000 --- a/bin/ksh/config.h +++ /dev/null @@ -1,365 +0,0 @@ -/* $NetBSD: config.h,v 1.8 2004/08/19 23:00:22 christos Exp $ */ - -/* config.h. Generated automatically by configure. */ -/* config.h.in. Generated automatically from configure.in by autoheader. */ -/* - * This file, acconfig.h, which is a part of pdksh (the public domain ksh), - * is placed in the public domain. It comes with no licence, warranty - * or guarantee of any kind (i.e., at your own risk). - */ - -#ifndef CONFIG_H -#define CONFIG_H - -/* Define if on AIX 3. - System headers sometimes define this. - We just want to avoid a redefinition error message. */ -#ifndef _ALL_SOURCE -/* #undef _ALL_SOURCE */ -#endif - -/* Define if the closedir function returns void instead of int. */ -/* #undef CLOSEDIR_VOID */ - -/* Define to empty if the keyword does not work. */ -/* #undef const */ - -/* Define to `int' if doesn't define. */ -/* #undef gid_t */ - -/* Define if you have a working `mmap' system call. */ -#define HAVE_MMAP 1 - -/* Define if your struct stat has st_rdev. */ -#define HAVE_ST_RDEV 1 - -/* Define if you have that is POSIX.1 compatible. */ -#define HAVE_SYS_WAIT_H 1 - -/* Define if you have . */ -#define HAVE_UNISTD_H 1 - -/* Define if on MINIX. */ -/* #undef _MINIX */ - -/* Define to `int' if doesn't define. */ -/* #undef mode_t */ - -/* Define to `long' if doesn't define. */ -/* #undef off_t */ - -/* Define to `int' if doesn't define. */ -/* #undef pid_t */ - -/* Define if the system does not provide POSIX.1 features except - with this defined. */ -/* #undef _POSIX_1_SOURCE */ - -/* Define if you need to in order for stat and other things to work. */ -/* #undef _POSIX_SOURCE */ - -/* Define as the return type of signal handlers (int or void). */ -#define RETSIGTYPE void - -/* Define if the `S_IS*' macros in do not work properly. */ -/* #undef STAT_MACROS_BROKEN */ - -/* Define if `sys_siglist' is declared by . */ -#define SYS_SIGLIST_DECLARED 1 - -/* Define if you can safely include both and . */ -#define TIME_WITH_SYS_TIME 1 - -/* Define to `int' if doesn't define. */ -/* #undef uid_t */ - -/* Define if the closedir function returns void instead of int. */ -/* #undef VOID_CLOSEDIR */ - -/* Define if your kernel doesn't handle scripts starting with #! */ -/* #undef SHARPBANG */ - -/* Define if dup2() preserves the close-on-exec flag (ultrix does this) */ -/* #undef DUP2_BROKEN */ - -/* Define as the return value of signal handlers (0 or ). */ -#define RETSIGVAL - -/* Define if you have posix signal routines (sigaction(), et. al.) */ -#define POSIX_SIGNALS 1 - -/* Define if you have BSD4.2 signal routines (sigsetmask(), et. al.) */ -/* #undef BSD42_SIGNALS */ - -/* Define if you have BSD4.1 signal routines (sigset(), et. al.) */ -/* #undef BSD41_SIGNALS */ - -/* Define if you have v7 signal routines (signal(), signal reset on delivery) */ -/* #undef V7_SIGNALS */ - -/* Define to use the fake posix signal routines (sigact.[ch]) */ -/* #undef USE_FAKE_SIGACT */ - -/* Define if signals don't interrupt read() */ -/* #undef SIGNALS_DONT_INTERRUPT */ - -/* Define if you have bsd versions of the setpgrp() and getpgrp() routines */ -/* #undef BSD_PGRP */ - -/* Define if you have POSIX versions of the setpgid() and getpgrp() routines */ -#define POSIX_PGRP 1 - -/* Define if you have sysV versions of the setpgrp() and getpgrp() routines */ -/* #undef SYSV_PGRP */ - -/* Define if you don't have setpgrp(), setpgid() or getpgrp() routines */ -/* #undef NO_PGRP */ - -/* Define to char if your compiler doesn't like the void keyword */ -/* #undef void */ - -/* Define to nothing if compiler doesn't like the volatile keyword */ -/* #undef volatile */ - -/* Define if C compiler groks function prototypes */ -#define HAVE_PROTOTYPES 1 - -/* Define if C compiler groks __attribute__((...)) (const, noreturn, format) */ -#define HAVE_GCC_FUNC_ATTR 1 - -/* Define to 32-bit signed integer type if doesn't define */ -/* #undef clock_t */ - -/* Define to the type of struct rlimit fields if the rlim_t type is missing */ -/* #undef rlim_t */ - -/* Define if time() is declared in */ -#define TIME_DECLARED 1 - -/* Define to `unsigned' if doesn't define */ -/* #undef sigset_t */ - -/* Define if sys_errlist[] and sys_nerr are in the C library */ -#define HAVE_SYS_ERRLIST 1 - -/* Define if sys_errlist[] and sys_nerr are defined in */ -#define SYS_ERRLIST_DECLARED 1 - -/* Define if sys_siglist[] is in the C library */ -#define HAVE_SYS_SIGLIST 1 - -/* Define if you have a sane header file */ -#define HAVE_TERMIOS_H 1 - -/* Define if you have a memset() function in your C library */ -#define HAVE_MEMSET 1 - -/* Define if you have a memmove() function in your C library */ -#define HAVE_MEMMOVE 1 - -/* Define if you have a bcopy() function in your C library */ -#define HAVE_BCOPY - -/* Define if you have a lstat() function in your C library */ -#define HAVE_LSTAT 1 - -/* Define if you have a sane header file */ -/* #undef HAVE_TERMIO_H */ - -/* Define if you don't have times() or if it always returns 0 */ -/* #undef TIMES_BROKEN */ - -/* Define if opendir() will open non-directory files */ -/* #undef OPENDIR_DOES_NONDIR */ - -/* Define if you have a dup2() function in your C library */ -#define HAVE_DUP2 1 - -/* Define if the pgrp of setpgrp() can't be the pid of a zombie process */ -/* #undef NEED_PGRP_SYNC */ - -/* Define if you arg running SCO unix */ -/* #undef OS_SCO */ - -/* Define if you arg running ISC unix */ -/* #undef OS_ISC */ - -/* Define if you arg running OS2 with the EMX library */ -/* #undef OS2 */ - -/* Define if you have a POSIX.1 compatible */ -#define POSIX_SYS_WAIT 1 - -/* Define if your OS maps references to /dev/fd/n to file descriptor n */ -/* #undef HAVE_DEV_FD */ - -/* Default PATH */ -#ifdef RESCUEDIR -#define DEFAULT_PATH RESCUEDIR ":/bin:/usr/bin:/sbin:/usr/sbin" -#else -#define DEFAULT_PATH "/bin:/usr/bin:/sbin:/usr/sbin" -#endif - -/* Define if your C library's getwd/getcwd function dumps core in unreadable - * directories. */ -/* #undef HPUX_GETWD_BUG */ - -/* Include ksh features? */ -#define KSH 1 - -/* Include emacs editing? */ -#define EMACS 1 - -/* Include vi editing? */ -#define VI 1 - -/* Include job control? */ -#define JOBS 1 - -/* Include brace-expansion? */ -#define BRACE_EXPAND 1 - -/* Include any history? */ -#define HISTORY 1 - -/* Include complex history? */ -/* #undef COMPLEX_HISTORY */ - -/* Strict POSIX behaviour? */ -#define POSIXLY_CORRECT 1 - -/* Specify default $ENV? */ -#define DEFAULT_ENV "$HOME/.kshrc" - -/* Include shl(1) support? */ -/* #undef SWTCH */ - -/* Include game-of-life? */ -/* #undef SILLY */ - -/* The number of bytes in a int. */ -#define SIZEOF_INT 4 - -/* The number of bytes in a long. */ -#define SIZEOF_LONG 4 - -/* Define if you have the _setjmp function. */ -#define HAVE__SETJMP - -/* Define if you have the confstr function. */ -/* #undef HAVE_CONFSTR */ - -/* Define if you have the flock function. */ -#define HAVE_FLOCK 1 - -/* Define if you have the getcwd function. */ -#define HAVE_GETCWD 1 - -/* Define if you have the getgroups function. */ -/* #undef HAVE_GETGROUPS */ - -/* Define if you have the getpagesize function. */ -#define HAVE_GETPAGESIZE 1 - -/* Define if you have the getrusage function. */ -#define HAVE_GETRUSAGE - -/* Define if you have the getwd function. */ -#define HAVE_GETWD 1 - -/* Define if you have the killpg function. */ -#define HAVE_KILLPG 1 - -/* Define if you have the nice function. */ -#define HAVE_NICE 1 - -/* Define if you have the setrlimit function. */ -#define HAVE_SETRLIMIT 1 - -/* Define if you have the sigsetjmp function. */ -#define HAVE_SIGSETJMP 1 - -/* Define if you have the strcasecmp function. */ -#define HAVE_STRCASECMP 1 - -/* Define if you have the strerror function. */ -#define HAVE_STRERROR 1 - -/* Define if you have the strstr function. */ -#define HAVE_STRSTR 1 - -/* Define if you have the sysconf function. */ -#define HAVE_SYSCONF 1 - -/* Define if you have the tcsetpgrp function. */ -#define HAVE_TCSETPGRP 1 - -/* Define if you have the ulimit function. */ -#define HAVE_ULIMIT - -/* Define if you have the valloc function. */ -#define HAVE_VALLOC 1 - -/* Define if you have the wait3 function. */ -#define HAVE_WAIT3 1 - -/* Define if you have the waitpid function. */ -#define HAVE_WAITPID 1 - -/* Define if you have the header file. */ -#define HAVE_DIRENT_H 1 - -/* Define if you have the header file. */ -#define HAVE_FCNTL_H 1 - -/* Define if you have the header file. */ -#define HAVE_LIMITS_H 1 - -/* Define if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define if you have the header file. */ -/* #undef HAVE_NDIR_H */ - -/* Define if you have the header file. */ -#define HAVE_PATHS_H 1 - -/* Define if you have the header file. */ -#define HAVE_STDDEF_H 1 - -/* Define if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define if you have the header file. */ -#define HAVE_SYS_DIR_H - -/* Define if you have the header file. */ -/* #undef HAVE_SYS_NDIR_H */ - -/* Define if you have the header file. */ -#define HAVE_SYS_PARAM_H 1 - -/* Define if you have the header file. */ -#define HAVE_SYS_RESOURCE_H 1 - -/* Define if you have the header file. */ -#define HAVE_SYS_TIME_H 1 - -/* Define if you have the header file. */ -#define HAVE_SYS_WAIT_H 1 - -/* Define if you have the header file. */ -#define HAVE_ULIMIT_H - -/* Define if you have the header file. */ -/* #undef HAVE_VALUES_H */ - -/* Need to use a separate file to keep the configure script from commenting - * out the undefs.... - */ -#include "conf-end.h" - -#endif /* CONFIG_H */ diff --git a/bin/ksh/edit.c b/bin/ksh/edit.c deleted file mode 100644 index 07a2f908e..000000000 --- a/bin/ksh/edit.c +++ /dev/null @@ -1,1095 +0,0 @@ -/* $NetBSD: edit.c,v 1.25 2010/06/05 03:02:37 sjg Exp $ */ - -/* - * Command line editing - common code - * - */ -#include - -#ifndef lint -__RCSID("$NetBSD: edit.c,v 1.25 2010/06/05 03:02:37 sjg Exp $"); -#endif - - -#include "config.h" -#ifdef EDIT - -#include "sh.h" -#include "tty.h" -#define EXTERN -#include "edit.h" -#undef EXTERN -#ifdef OS_SCO /* SCO Unix 3.2v4.1 */ -# include /* needed for */ -# include /* needed for struct winsize */ -#endif /* OS_SCO */ -#include -#include -#include "ksh_stat.h" - - -#if defined(TIOCGWINSZ) -static RETSIGTYPE x_sigwinch ARGS((int sig)); -static int got_sigwinch; -static void check_sigwinch ARGS((void)); -#endif /* TIOCGWINSZ */ - -static int x_file_glob ARGS((int flags, const char *str, int slen, - char ***wordsp)); -static int x_command_glob ARGS((int flags, const char *str, int slen, - char ***wordsp)); -static int x_locate_word ARGS((const char *buf, int buflen, int pos, - int *startp, int *is_command)); - -static char vdisable_c; - - -/* Called from main */ -void -x_init() -{ - /* set to -2 to force initial binding */ - edchars.erase = edchars.kill = edchars.intr = edchars.quit - = edchars.eof = -2; - /* default value for deficient systems */ - edchars.werase = 027; /* ^W */ - -#ifdef TIOCGWINSZ -# ifdef SIGWINCH - if (setsig(&sigtraps[SIGWINCH], x_sigwinch, SS_RESTORE_ORIG|SS_SHTRAP)) - sigtraps[SIGWINCH].flags |= TF_SHELL_USES; -# endif /* SIGWINCH */ - got_sigwinch = 1; /* force initial check */ - check_sigwinch(); -#endif /* TIOCGWINSZ */ - -#ifdef EMACS - x_init_emacs(); -#endif /* EMACS */ - - /* Bizarreness to figure out how to disable - * a struct termios.c_cc[] char - */ -#ifdef _POSIX_VDISABLE - if (_POSIX_VDISABLE >= 0) - vdisable_c = (char) _POSIX_VDISABLE; - else - /* `feature not available' */ - vdisable_c = (char) 0377; -#else -# if defined(HAVE_PATHCONF) && defined(_PC_VDISABLE) - vdisable_c = fpathconf(tty_fd, _PC_VDISABLE); -# else - vdisable_c = (char) 0377; /* default to old BSD value */ -# endif -#endif /* _POSIX_VDISABLE */ -} - -#if defined(TIOCGWINSZ) -static RETSIGTYPE -x_sigwinch(sig) - int sig; -{ - got_sigwinch = 1; - return RETSIGVAL; -} - -static void -check_sigwinch ARGS((void)) -{ - if (got_sigwinch) { - struct winsize ws; - - got_sigwinch = 0; - if (procpid == kshpid && ioctl(tty_fd, TIOCGWINSZ, &ws) >= 0) { - struct tbl *vp; - - /* Do NOT export COLUMNS/LINES. Many applications - * check COLUMNS/LINES before checking ws.ws_col/row, - * so if the app is started with C/L in the environ - * and the window is then resized, the app won't - * see the change cause the environ doesn't change. - */ - if (ws.ws_col) { - x_cols = ws.ws_col < MIN_COLS ? MIN_COLS - : ws.ws_col; - - if ((vp = typeset("COLUMNS", 0, 0, 0, 0))) - setint(vp, (long) ws.ws_col); - } - if (ws.ws_row - && (vp = typeset("LINES", 0, 0, 0, 0))) - setint(vp, (long) ws.ws_row); - } - } -} -#endif /* TIOCGWINSZ */ - -/* - * read an edited command line - */ -int -x_read(buf, len) - char *buf; - size_t len; -{ - int i; - - x_mode(TRUE); -#ifdef EMACS - if (Flag(FEMACS) || Flag(FGMACS)) - i = x_emacs(buf, len); - else -#endif -#ifdef VI - if (Flag(FVI)) - i = x_vi(buf, len); - else -#endif - i = -1; /* internal error */ - x_mode(FALSE); -#if defined(TIOCGWINSZ) - if (got_sigwinch) - check_sigwinch(); -#endif /* TIOCGWINSZ */ - - return i; -} - -/* tty I/O */ - -int -x_getc() -{ -#ifdef OS2 - unsigned char c = _read_kbd(0, 1, 0); - return c == 0 ? 0xE0 : c; -#else /* OS2 */ - char c; - int n; - - while ((n = blocking_read(0, &c, 1)) < 0 && errno == EINTR) - if (trap) { - x_mode(FALSE); - runtraps(0); - x_mode(TRUE); - } - if (n != 1) - return -1; - return (int) (unsigned char) c; -#endif /* OS2 */ -} - -void -x_flush() -{ - shf_flush(shl_out); -} - -void -x_putc(c) - int c; -{ - shf_putc(c, shl_out); -} - -void -x_puts(s) - const char *s; -{ - while (*s != 0) - shf_putc(*s++, shl_out); -} - -bool_t -x_mode(onoff) - bool_t onoff; -{ - static bool_t x_cur_mode; - bool_t prev; - - if (x_cur_mode == onoff) - return x_cur_mode; - prev = x_cur_mode; - x_cur_mode = onoff; - - if (onoff) { - TTY_state cb; - X_chars oldchars; - - oldchars = edchars; - cb = tty_state; - -#if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H) - edchars.erase = cb.c_cc[VERASE]; - edchars.kill = cb.c_cc[VKILL]; - edchars.intr = cb.c_cc[VINTR]; - edchars.quit = cb.c_cc[VQUIT]; - edchars.eof = cb.c_cc[VEOF]; -# ifdef VWERASE - edchars.werase = cb.c_cc[VWERASE]; -# endif -# ifdef _CRAY2 /* brain-damaged terminal handler */ - cb.c_lflag &= ~(ICANON|ECHO); - /* rely on print routine to map '\n' to CR,LF */ -# else - cb.c_iflag &= ~(INLCR|ICRNL); -# ifdef _BSD_SYSV /* need to force CBREAK instead of RAW (need CRMOD on output) */ - cb.c_lflag &= ~(ICANON|ECHO); -# else -# ifdef SWTCH /* need CBREAK to handle swtch char */ - cb.c_lflag &= ~(ICANON|ECHO); - cb.c_lflag |= ISIG; - cb.c_cc[VINTR] = vdisable_c; - cb.c_cc[VQUIT] = vdisable_c; -# else - cb.c_lflag &= ~(ISIG|ICANON|ECHO); -# endif -# endif -# ifdef VLNEXT - /* osf/1 processes lnext when ~icanon */ - cb.c_cc[VLNEXT] = vdisable_c; -# endif /* VLNEXT */ -# ifdef VDISCARD - /* sunos 4.1.x & osf/1 processes discard(flush) when ~icanon */ - cb.c_cc[VDISCARD] = vdisable_c; -# endif /* VDISCARD */ - cb.c_cc[VTIME] = 0; - cb.c_cc[VMIN] = 1; -# endif /* _CRAY2 */ -#else - /* Assume BSD tty stuff. */ - edchars.erase = cb.sgttyb.sg_erase; - edchars.kill = cb.sgttyb.sg_kill; - cb.sgttyb.sg_flags &= ~ECHO; - cb.sgttyb.sg_flags |= CBREAK; -# ifdef TIOCGATC - edchars.intr = cb.lchars.tc_intrc; - edchars.quit = cb.lchars.tc_quitc; - edchars.eof = cb.lchars.tc_eofc; - edchars.werase = cb.lchars.tc_werasc; - cb.lchars.tc_suspc = -1; - cb.lchars.tc_dsuspc = -1; - cb.lchars.tc_lnextc = -1; - cb.lchars.tc_statc = -1; - cb.lchars.tc_intrc = -1; - cb.lchars.tc_quitc = -1; - cb.lchars.tc_rprntc = -1; -# else - edchars.intr = cb.tchars.t_intrc; - edchars.quit = cb.tchars.t_quitc; - edchars.eof = cb.tchars.t_eofc; - cb.tchars.t_intrc = -1; - cb.tchars.t_quitc = -1; -# ifdef TIOCGLTC - edchars.werase = cb.ltchars.t_werasc; - cb.ltchars.t_suspc = -1; - cb.ltchars.t_dsuspc = -1; - cb.ltchars.t_lnextc = -1; - cb.ltchars.t_rprntc = -1; -# endif -# endif /* TIOCGATC */ -#endif /* HAVE_TERMIOS_H || HAVE_TERMIO_H */ - - set_tty(tty_fd, &cb, TF_WAIT); - -#ifdef __CYGWIN__ - if (edchars.eof == '\0') - edchars.eof = '\4'; -#endif /* __CYGWIN__ */ - - /* Convert unset values to internal `unset' value */ - if (edchars.erase == vdisable_c) - edchars.erase = -1; - if (edchars.kill == vdisable_c) - edchars.kill = -1; - if (edchars.intr == vdisable_c) - edchars.intr = -1; - if (edchars.quit == vdisable_c) - edchars.quit = -1; - if (edchars.eof == vdisable_c) - edchars.eof = -1; - if (edchars.werase == vdisable_c) - edchars.werase = -1; - if (memcmp(&edchars, &oldchars, sizeof(edchars)) != 0) { -#ifdef EMACS - x_emacs_keys(&edchars); -#endif - } - } else { - /* TF_WAIT doesn't seem to be necessary when leaving xmode */ - set_tty(tty_fd, &tty_state, TF_NONE); - } - - return prev; -} - -/* NAME: - * promptlen - calculate the length of PS1 etc. - * - * DESCRIPTION: - * This function is based on a fix from guy@demon.co.uk - * It fixes a bug in that if PS1 contains '!', the length - * given by strlen() is probably wrong. - * - * RETURN VALUE: - * length - */ -int -promptlen(cp, spp) - const char *cp; - const char **spp; -{ - int count = 0; - const char *sp = cp; - char delimiter = 0; - int indelimit = 0; - - /* Undocumented AT&T ksh feature: - * If the second char in the prompt string is \r then the first char - * is taken to be a non-printing delimiter and any chars between two - * instances of the delimiter are not considered to be part of the - * prompt length - */ - if (*cp && cp[1] == '\r') { - delimiter = *cp; - cp += 2; - } - - for (; *cp; cp++) { - if (indelimit && *cp != delimiter) - ; - else if (*cp == '\n' || *cp == '\r') { - count = 0; - sp = cp + 1; - } else if (*cp == '\t') { - count = (count | 7) + 1; - } else if (*cp == '\b') { - if (count > 0) - count--; - } else if (*cp == delimiter) - indelimit = !indelimit; - else - count++; - } - if (spp) - *spp = sp; - return count; -} - -void -set_editmode(ed) - const char *ed; -{ - static const enum sh_flag edit_flags[] = { -#ifdef EMACS - FEMACS, FGMACS, -#endif -#ifdef VI - FVI, -#endif - }; - char *rcp; - size_t i; - - if ((rcp = ksh_strrchr_dirsep(ed))) - ed = ++rcp; - for (i = 0; i < NELEM(edit_flags); i++) - if (strstr(ed, goptions[(int) edit_flags[i]].name)) { - change_flag(edit_flags[i], OF_SPECIAL, 1); - return; - } -} - -/* ------------------------------------------------------------------------- */ -/* Misc common code for vi/emacs */ - -/* Handle the commenting/uncommenting of a line. - * Returns: - * 1 if a carriage return is indicated (comment added) - * 0 if no return (comment removed) - * -1 if there is an error (not enough room for comment chars) - * If successful, *lenp contains the new length. Note: cursor should be - * moved to the start of the line after (un)commenting. - */ -int -x_do_comment(buf, bsize, lenp) - char *buf; - int bsize; - int *lenp; -{ - int i, j; - int len = *lenp; - - if (len == 0) - return 1; /* somewhat arbitrary - it's what at&t ksh does */ - - /* Already commented? */ - if (buf[0] == '#') { - int saw_nl = 0; - - for (j = 0, i = 1; i < len; i++) { - if (!saw_nl || buf[i] != '#') - buf[j++] = buf[i]; - saw_nl = buf[i] == '\n'; - } - *lenp = j; - return 0; - } else { - int n = 1; - - /* See if there's room for the #'s - 1 per \n */ - for (i = 0; i < len; i++) - if (buf[i] == '\n') - n++; - if (len + n >= bsize) - return -1; - /* Now add them... */ - for (i = len, j = len + n; --i >= 0; ) { - if (buf[i] == '\n') - buf[--j] = '#'; - buf[--j] = buf[i]; - } - buf[0] = '#'; - *lenp += n; - return 1; - } -} - -/* ------------------------------------------------------------------------- */ -/* Common file/command completion code for vi/emacs */ - - -static char *add_glob ARGS((const char *, int)); -static void glob_table ARGS((const char *, XPtrV *, struct table *)); -static void glob_path ARGS((int, const char *, XPtrV *, const char *)); - -#if 0 /* not used... */ -int x_complete_word ARGS((const char *, int, int, int *, char **)); -int -x_complete_word(str, slen, is_command, nwordsp, ret) - const char *str; - int slen; - int is_command; - int *nwordsp; - char **ret; -{ - int nwords; - int prefix_len; - char **words; - - nwords = (is_command ? x_command_glob : x_file_glob)(XCF_FULLPATH, - str, slen, &words); - *nwordsp = nwords; - if (nwords == 0) { - *ret = (char *) 0; - return -1; - } - - prefix_len = x_longest_prefix(nwords, words); - *ret = str_nsave(words[0], prefix_len, ATEMP); - x_free_words(nwords, words); - return prefix_len; -} -#endif /* 0 */ - -void -x_print_expansions(nwords, words, is_command) - int nwords; - char *const *words; - int is_command; -{ - int use_copy = 0; - int prefix_len; - XPtrV l; - - l.beg = NULL; - - /* Check if all matches are in the same directory (in this - * case, we want to omit the directory name) - */ - if (!is_command - && (prefix_len = x_longest_prefix(nwords, words)) > 0) - { - int i; - - /* Special case for 1 match (prefix is whole word) */ - if (nwords == 1) - prefix_len = x_basename(words[0], (char *) 0); - /* Any (non-trailing) slashes in non-common word suffixes? */ - for (i = 0; i < nwords; i++) - if (x_basename(words[i] + prefix_len, (char *) 0) - > prefix_len) - break; - /* All in same directory? */ - if (i == nwords) { - while (prefix_len > 0 - && !ISDIRSEP(words[0][prefix_len - 1])) - prefix_len--; - use_copy = 1; - XPinit(l, nwords + 1); - for (i = 0; i < nwords; i++) - XPput(l, words[i] + prefix_len); - XPput(l, (char *) 0); - } - } - - /* - * Enumerate expansions - */ - x_putc('\r'); - x_putc('\n'); - pr_list(use_copy ? (char **) XPptrv(l) : words); - - if (use_copy) - XPfree(l); /* not x_free_words() */ -} - -/* - * Do file globbing: - * - appends * to (copy of) str if no globbing chars found - * - does expansion, checks for no match, etc. - * - sets *wordsp to array of matching strings - * - returns number of matching strings - */ -static int -x_file_glob(flags, str, slen, wordsp) - int flags; - const char *str; - int slen; - char ***wordsp; -{ - char *toglob; - char **words; - int nwords, i, idx, escaping; - XPtrV w; - struct source *s, *sold; - - if (slen < 0) - return 0; - - toglob = add_glob(str, slen); - - /* remove all escaping backward slashes */ - escaping = 0; - for(i = 0, idx = 0; toglob[i]; i++) { - if (toglob[i] == '\\' && !escaping) { - escaping = 1; - continue; - } - - toglob[idx] = toglob[i]; - idx++; - if (escaping) escaping = 0; - } - toglob[idx] = '\0'; - - /* - * Convert "foo*" (toglob) to an array of strings (words) - */ - sold = source; - s = pushs(SWSTR, ATEMP); - s->start = s->str = toglob; - source = s; - if (yylex(ONEWORD) != LWORD) { - source = sold; - internal_errorf(0, "fileglob: substitute error"); - return 0; - } - source = sold; - XPinit(w, 32); - expand(yylval.cp, &w, DOGLOB|DOTILDE|DOMARKDIRS); - XPput(w, NULL); - words = (char **) XPclose(w); - - for (nwords = 0; words[nwords]; nwords++) - ; - if (nwords == 1) { - struct stat statb; - - /* Check if globbing failed (returned glob pattern), - * but be careful (E.g. toglob == "ab*" when the file - * "ab*" exists is not an error). - * Also, check for empty result - happens if we tried - * to glob something which evaluated to an empty - * string (e.g., "$FOO" when there is no FOO, etc). - */ - if ((strcmp(words[0], toglob) == 0 - && stat(words[0], &statb) < 0) - || words[0][0] == '\0') - { - x_free_words(nwords, words); - words = NULL; - nwords = 0; - } - } - afree(toglob, ATEMP); - - if (nwords) { - *wordsp = words; - } else if (words) { - x_free_words(nwords, words); - *wordsp = NULL; - } - return nwords; -} - -/* Data structure used in x_command_glob() */ -struct path_order_info { - char *word; - int base; - int path_order; -}; - -static int path_order_cmp(const void *aa, const void *bb); - -/* Compare routine used in x_command_glob() */ -static int -path_order_cmp(aa, bb) - const void *aa; - const void *bb; -{ - const struct path_order_info *a = (const struct path_order_info *) aa; - const struct path_order_info *b = (const struct path_order_info *) bb; - int t; - - t = FILECMP(a->word + a->base, b->word + b->base); - return t ? t : a->path_order - b->path_order; -} - -static int -x_command_glob(flags, str, slen, wordsp) - int flags; - const char *str; - int slen; - char ***wordsp; -{ - char *toglob; - char *pat; - char *fpath; - int nwords; - XPtrV w; - struct block *l; - - if (slen < 0) - return 0; - - toglob = add_glob(str, slen); - - /* Convert "foo*" (toglob) to a pattern for future use */ - pat = evalstr(toglob, DOPAT|DOTILDE); - afree(toglob, ATEMP); - - XPinit(w, 32); - - glob_table(pat, &w, &keywords); - glob_table(pat, &w, &aliases); - glob_table(pat, &w, &builtins); - for (l = e->loc; l; l = l->next) - glob_table(pat, &w, &l->funs); - - glob_path(flags, pat, &w, path); - if ((fpath = str_val(global("FPATH"))) != null) - glob_path(flags, pat, &w, fpath); - - nwords = XPsize(w); - - if (!nwords) { - *wordsp = (char **) 0; - XPfree(w); - return 0; - } - - /* Sort entries */ - if (flags & XCF_FULLPATH) { - /* Sort by basename, then path order */ - struct path_order_info *info; - struct path_order_info *last_info = 0; - char **words = (char **) XPptrv(w); - int path_order = 0; - int i; - - info = (struct path_order_info *) - alloc(sizeof(struct path_order_info) * nwords, ATEMP); - for (i = 0; i < nwords; i++) { - info[i].word = words[i]; - info[i].base = x_basename(words[i], (char *) 0); - if (!last_info || info[i].base != last_info->base - || FILENCMP(words[i], - last_info->word, info[i].base) != 0) - { - last_info = &info[i]; - path_order++; - } - info[i].path_order = path_order; - } - qsort(info, nwords, sizeof(struct path_order_info), - path_order_cmp); - for (i = 0; i < nwords; i++) - words[i] = info[i].word; - afree((void *) info, ATEMP); - } else { - /* Sort and remove duplicate entries */ - char **words = (char **) XPptrv(w); - int i, j; - - qsortp(XPptrv(w), (size_t) nwords, xstrcmp); - - for (i = j = 0; i < nwords - 1; i++) { - if (strcmp(words[i], words[i + 1])) - words[j++] = words[i]; - else - afree(words[i], ATEMP); - } - words[j++] = words[i]; - nwords = j; - w.cur = (void **) &words[j]; - } - - XPput(w, NULL); - *wordsp = (char **) XPclose(w); - - return nwords; -} - -#define IS_WORDC(c) !( ctype(c, C_LEX1) || (c) == '\'' || (c) == '"' \ - || (c) == '`' || (c) == '=' || (c) == ':' ) - -static int -x_locate_word(buf, buflen, pos, startp, is_commandp) - const char *buf; - int buflen; - int pos; - int *startp; - int *is_commandp; -{ - int p; - int start, end; - - /* Bad call? Probably should report error */ - if (pos < 0 || pos > buflen) { - *startp = pos; - *is_commandp = 0; - return 0; - } - /* The case where pos == buflen happens to take care of itself... */ - - start = pos; - /* Keep going backwards to start of word (has effect of allowing - * one blank after the end of a word) - */ - for (; (start > 0 && IS_WORDC(buf[start - 1])) - || (start > 1 && buf[start-2] == '\\'); start--) - ; - /* Go forwards to end of word */ - for (end = start; end < buflen && IS_WORDC(buf[end]); end++) { - if (buf[end] == '\\' && (end+1) < buflen) - end++; - } - - if (is_commandp) { - int iscmd; - - /* Figure out if this is a command */ - for (p = start - 1; p >= 0 && isspace((unsigned char)buf[p]); p--) - ; - iscmd = p < 0 || strchr(";|&()`", buf[p]); - if (iscmd) { - /* If command has a /, path, etc. is not searched; - * only current directory is searched, which is just - * like file globbing. - */ - for (p = start; p < end; p++) - if (ISDIRSEP(buf[p])) - break; - iscmd = p == end; - } - *is_commandp = iscmd; - } - - *startp = start; - - return end - start; -} - -int -x_cf_glob(flags, buf, buflen, pos, startp, endp, wordsp, is_commandp) - int flags; - const char *buf; - int buflen; - int pos; - int *startp; - int *endp; - char ***wordsp; - int *is_commandp; -{ - int len; - int nwords; - char **words; - int is_command; - - len = x_locate_word(buf, buflen, pos, startp, &is_command); - if (!(flags & XCF_COMMAND)) - is_command = 0; - /* Don't do command globing on zero length strings - it takes too - * long and isn't very useful. File globs are more likely to be - * useful, so allow these. - */ - if (len == 0 && is_command) - return 0; - - nwords = (is_command ? x_command_glob : x_file_glob)(flags, - buf + *startp, len, &words); - if (nwords == 0) { - *wordsp = (char **) 0; - return 0; - } - - if (is_commandp) - *is_commandp = is_command; - *wordsp = words; - *endp = *startp + len; - - return nwords; -} - -/* Given a string, copy it and possibly add a '*' to the end. The - * new string is returned. - */ -static char * -add_glob(str, slen) - const char *str; - int slen; -{ - char *toglob; - char *s; - bool_t saw_slash = FALSE; - - if (slen < 0) - return (char *) 0; - - toglob = str_nsave(str, slen + 1, ATEMP); /* + 1 for "*" */ - toglob[slen] = '\0'; - - /* - * If the pathname contains a wildcard (an unquoted '*', - * '?', or '['), or a ~username - * with no trailing slash, then it is globbed based on that - * value (i.e., without the appended '*'). - */ - for (s = toglob; *s; s++) { - if (*s == '\\' && s[1]) - s++; - else if (*s == '*' || *s == '[' || *s == '?' - || (s[1] == '(' /*)*/ && strchr("*+?@!", *s))) - break; - else if (ISDIRSEP(*s)) - saw_slash = TRUE; - } - if (!*s && (*toglob != '~' || saw_slash)) { - toglob[slen] = '*'; - toglob[slen + 1] = '\0'; - } - - return toglob; -} - -/* - * Find longest common prefix - */ -int -x_longest_prefix(nwords, words) - int nwords; - char *const *words; -{ - int i, j; - int prefix_len; - char *p; - - if (nwords <= 0) - return 0; - - prefix_len = strlen(words[0]); - for (i = 1; i < nwords; i++) - for (j = 0, p = words[i]; j < prefix_len; j++) - if (FILECHCONV((unsigned char)p[j]) - != FILECHCONV((unsigned char)words[0][j])) { - prefix_len = j; - break; - } - return prefix_len; -} - -void -x_free_words(nwords, words) - int nwords; - char **words; -{ - int i; - - for (i = 0; i < nwords; i++) - if (words[i]) - afree(words[i], ATEMP); - afree(words, ATEMP); -} - -/* Return the offset of the basename of string s (which ends at se - need not - * be null terminated). Trailing slashes are ignored. If s is just a slash, - * then the offset is 0 (actually, length - 1). - * s Return - * /etc 1 - * /etc/ 1 - * /etc// 1 - * /etc/fo 5 - * foo 0 - * /// 2 - * 0 - */ -int -x_basename(s, se) - const char *s; - const char *se; -{ - const char *p; - - if (se == (char *) 0) - se = s + strlen(s); - if (s == se) - return 0; - - /* Skip trailing slashes */ - for (p = se - 1; p > s && ISDIRSEP(*p); p--) - ; - for (; p > s && !ISDIRSEP(*p); p--) - ; - if (ISDIRSEP(*p) && p + 1 < se) - p++; - - return p - s; -} - -/* - * Apply pattern matching to a table: all table entries that match a pattern - * are added to wp. - */ -static void -glob_table(pat, wp, tp) - const char *pat; - XPtrV *wp; - struct table *tp; -{ - struct tstate ts; - struct tbl *te; - - for (twalk(&ts, tp); (te = tnext(&ts)); ) { - if (gmatch(te->name, pat, FALSE)) - XPput(*wp, str_save(te->name, ATEMP)); - } -} - -static void -glob_path(flags, pat, wp, xpath) - int flags; - const char *pat; - XPtrV *wp; - const char *xpath; -{ - const char *sp, *p; - char *xp; - int staterr; - int pathlen; - int patlen; - int oldsize, newsize, i, j; - char **words; - XString xs; - - patlen = strlen(pat) + 1; - sp = xpath; - Xinit(xs, xp, patlen + 128, ATEMP); - while (sp) { - xp = Xstring(xs, xp); - if (!(p = strchr(sp, PATHSEP))) - p = sp + strlen(sp); - pathlen = p - sp; - if (pathlen) { - /* Copy sp into xp, stuffing any MAGIC characters - * on the way - */ - const char *s = sp; - - XcheckN(xs, xp, pathlen * 2); - while (s < p) { - if (ISMAGIC(*s)) - *xp++ = MAGIC; - *xp++ = *s++; - } - *xp++ = DIRSEP; - pathlen++; - } - sp = p; - XcheckN(xs, xp, patlen); - memcpy(xp, pat, patlen); - - oldsize = XPsize(*wp); - glob_str(Xstring(xs, xp), wp, 1); /* mark dirs */ - newsize = XPsize(*wp); - - /* Check that each match is executable... */ - words = (char **) XPptrv(*wp); - for (i = j = oldsize; i < newsize; i++) { - staterr = 0; - if ((search_access(words[i], X_OK, &staterr) >= 0) - || (staterr == EISDIR)) { - words[j] = words[i]; - if (!(flags & XCF_FULLPATH)) - memmove(words[j], words[j] + pathlen, - strlen(words[j] + pathlen) + 1); - j++; - } else - afree(words[i], ATEMP); - } - wp->cur = (void **) &words[j]; - - if (!*sp++) - break; - } - Xfree(xs, xp); -} - -/* - * if argument string contains any special characters, they will - * be escaped and the result will be put into edit buffer by - * keybinding-specific function - */ -int -x_escape(s, len, putbuf_func) - const char *s; - size_t len; - int (*putbuf_func) ARGS((const char *, size_t)); -{ - size_t add, wlen; - const char *ifs = str_val(local("IFS", 0)); - int rval=0; - - for (add = 0, wlen = len; wlen - add > 0; add++) { - if (strchr("\\$(){}[]?*&;#|<>\"'`", s[add]) || strchr(ifs, s[add])) { - if (putbuf_func(s, add) != 0) { - rval = -1; - break; - } - - putbuf_func("\\", 1); - putbuf_func(&s[add], 1); - - add++; - wlen -= add; - s += add; - add = -1; /* after the increment it will go to 0 */ - } - } - if (wlen > 0 && rval == 0) - rval = putbuf_func(s, wlen); - - return (rval); -} -#endif /* EDIT */ diff --git a/bin/ksh/edit.h b/bin/ksh/edit.h deleted file mode 100644 index c0bc8c50f..000000000 --- a/bin/ksh/edit.h +++ /dev/null @@ -1,87 +0,0 @@ -/* $NetBSD: edit.h,v 1.3 1999/11/02 22:06:45 jdolecek Exp $ */ - -/* NAME: - * edit.h - globals for edit modes - * - * DESCRIPTION: - * This header defines various global edit objects. - * - * SEE ALSO: - * - * - * RCSid: - * $NetBSD: edit.h,v 1.3 1999/11/02 22:06:45 jdolecek Exp $ - * - */ - -/* some useful #defines */ -#ifdef EXTERN -# define I__(i) = i -#else -# define I__(i) -# define EXTERN extern -# define EXTERN_DEFINED -#endif - -#define BEL 0x07 - -/* tty driver characters we are interested in */ -typedef struct { - int erase; - int kill; - int werase; - int intr; - int quit; - int eof; -} X_chars; - -EXTERN X_chars edchars; - -/* x_fc_glob() flags */ -#define XCF_COMMAND BIT(0) /* Do command completion */ -#define XCF_FILE BIT(1) /* Do file completion */ -#define XCF_FULLPATH BIT(2) /* command completion: store full path */ -#define XCF_COMMAND_FILE (XCF_COMMAND|XCF_FILE) - -/* edit.c */ -int x_getc ARGS((void)); -void x_flush ARGS((void)); -void x_putc ARGS((int c)); -void x_puts ARGS((const char *s)); -bool_t x_mode ARGS((bool_t onoff)); -int promptlen ARGS((const char *cp, const char **spp)); -int x_do_comment ARGS((char *buf, int bsize, int *lenp)); -void x_print_expansions ARGS((int nwords, char *const *words, int is_command)); -int x_cf_glob ARGS((int flags, const char *buf, int buflen, int pos, int *startp, - int *endp, char ***wordsp, int *is_commandp)); -int x_longest_prefix ARGS((int nwords, char *const *words)); -int x_basename ARGS((const char *s, const char *se)); -void x_free_words ARGS((int nwords, char **words)); -int x_escape ARGS((const char *, size_t, int (*)(const char *s, size_t len))); -/* emacs.c */ -int x_emacs ARGS((char *buf, size_t len)); -void x_init_emacs ARGS((void)); -void x_emacs_keys ARGS((X_chars *ec)); -/* vi.c */ -int x_vi ARGS((char *buf, size_t len)); - - -#ifdef DEBUG -# define D__(x) x -#else -# define D__(x) -#endif - -/* This lot goes at the END */ -/* be sure not to interfere with anyone else's idea about EXTERN */ -#ifdef EXTERN_DEFINED -# undef EXTERN_DEFINED -# undef EXTERN -#endif -#undef I__ -/* - * Local Variables: - * version-control:t - * comment-column:40 - * End: - */ diff --git a/bin/ksh/emacs-gen.sh b/bin/ksh/emacs-gen.sh deleted file mode 100755 index 3a2de8a79..000000000 --- a/bin/ksh/emacs-gen.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/sh -# $NetBSD: emacs-gen.sh,v 1.4 2008/10/25 22:18:15 apb Exp $ - -: ${AWK:=awk} -: ${SED:=sed} - -case $# in -1) file=$1;; -*) - echo "$0: Usage: $0 path-to-emacs.c" 1>&2 - exit 1 -esac; - -if [ ! -r "$file" ] ;then - echo "$0: can't read $file" 1>&2 - exit 1 -fi - -cat << E_O_F || exit 1 -/* - * NOTE: THIS FILE WAS GENERATED AUTOMATICALLY FROM $file - * - * DO NOT BOTHER EDITING THIS FILE - */ -E_O_F - -# Pass 1: print out lines before @START-FUNC-TAB@ -# and generate defines and function declarations, -${SED} -e '1,/@START-FUNC-TAB@/d' -e '/@END-FUNC-TAB@/,$d' < $file | - ${AWK} 'BEGIN { nfunc = 0; } - /^[ ]*#/ { - print $0; - next; - } - { - fname = $2; - c = substr(fname, length(fname), 1); - if (c == ",") - fname = substr(fname, 1, length(fname) - 1); - if (fname != "0") { - printf "#define XFUNC_%s %d\n", substr(fname, 3, length(fname) - 2), nfunc; - printf "static int %s ARGS((int c));\n", fname; - nfunc++; - } - }' || exit 1 - -exit 0 diff --git a/bin/ksh/emacs.c b/bin/ksh/emacs.c deleted file mode 100644 index 2177da3ef..000000000 --- a/bin/ksh/emacs.c +++ /dev/null @@ -1,2221 +0,0 @@ -/* $NetBSD: emacs.c,v 1.32 2009/04/25 05:11:37 lukem Exp $ */ - -/* - * Emacs-like command line editing and history - * - * created by Ron Natalie at BRL - * modified by Doug Kingston, Doug Gwyn, and Lou Salkind - * adapted to PD ksh by Eric Gisin - */ -#include - -#ifndef lint -__RCSID("$NetBSD: emacs.c,v 1.32 2009/04/25 05:11:37 lukem Exp $"); -#endif - - -#include "config.h" -#ifdef EMACS - -#include "sh.h" -#include "ksh_stat.h" -#include "ksh_dir.h" -#include -#include -#include "edit.h" - -static Area aedit; -#define AEDIT &aedit /* area for kill ring and macro defns */ - -#undef CTRL /* _BSD brain damage */ -#define CTRL(x) ((x) == '?' ? 0x7F : (x) & 0x1F) /* ASCII */ -#define UNCTRL(x) ((x) == 0x7F ? '?' : (x) | 0x40) /* ASCII */ -#define META(x) ((x) & 0x7f) -#define ISMETA(x) (Flag(FEMACSUSEMETA) && ((x) & 0x80)) - - -/* values returned by keyboard functions */ -#define KSTD 0 -#define KEOL 1 /* ^M, ^J */ -#define KINTR 2 /* ^G, ^C */ - -struct x_ftab { - int (*xf_func) ARGS((int c)); - const char *xf_name; - short xf_flags; -}; - -/* index into struct x_ftab x_ftab[] - small is good */ -typedef unsigned char Findex; - -struct x_defbindings { - Findex xdb_func; /* XFUNC_* */ - unsigned char xdb_tab; - unsigned char xdb_char; -}; - -#define XF_ARG 1 /* command takes number prefix */ -#define XF_NOBIND 2 /* not allowed to bind to function */ -#define XF_PREFIX 4 /* function sets prefix */ - -/* Separator for completion */ -#define is_cfs(c) (c == ' ' || c == '\t' || c == '"' || c == '\'') -#define is_mfs(c) (!(isalnum((unsigned char)c) || c == '_' || c == '$')) /* Separator for motion */ - -#ifdef OS2 - /* Deal with 8 bit chars & an extra prefix for function key (these two - * changes increase memory usage from 9,216 bytes to 24,416 bytes...) - */ -# define CHARMASK 0xFF /* 8-bit ASCII character mask */ -# define X_NTABS 4 /* normal, meta1, meta2, meta3 */ -static int x_prefix3 = 0xE0; -#else /* OS2 */ -# define CHARMASK 0xFF /* 8-bit character mask */ -# define X_NTABS 3 /* normal, meta1, meta2 */ -#endif /* OS2 */ -#define X_TABSZ (CHARMASK+1) /* size of keydef tables etc */ - -/* Arguments for do_complete() - * 0 = enumerate M-= complete as much as possible and then list - * 1 = complete M-Esc - * 2 = list M-? - */ -typedef enum { CT_LIST, /* list the possible completions */ - CT_COMPLETE, /* complete to longest prefix */ - CT_COMPLIST /* complete and then list (if non-exact) */ - } Comp_type; - -/* { from 4.9 edit.h */ -/* - * The following are used for my horizontal scrolling stuff - */ -static char *xbuf; /* beg input buffer */ -static char *xend; /* end input buffer */ -static char *xcp; /* current position */ -static char *xep; /* current end */ -static char *xbp; /* start of visible portion of input buffer */ -static char *xlp; /* last char visible on screen */ -static int x_adj_ok; -/* - * we use x_adj_done so that functions can tell - * whether x_adjust() has been called while they are active. - */ -static int x_adj_done; - -static int xx_cols; -static int x_col; -static int x_displen; -static int x_arg; /* general purpose arg */ -static int x_arg_defaulted;/* x_arg not explicitly set; defaulted to 1 */ - -static int xlp_valid; -/* end from 4.9 edit.h } */ - -static int x_prefix1 = CTRL('['), x_prefix2 = CTRL('X'); -static char **x_histp; /* history position */ -static int x_nextcmd; /* for newline-and-next */ -static char *xmp; /* mark pointer */ -static Findex x_last_command; -static Findex (*x_tab)[X_TABSZ]; /* key definition */ -static char *(*x_atab)[X_TABSZ]; /* macro definitions */ -static unsigned char x_bound[(X_TABSZ * X_NTABS + 7) / 8]; -#define KILLSIZE 20 -static char *killstack[KILLSIZE]; -static int killsp, killtp; -static int x_curprefix; -static char *macroptr; -static int prompt_trunc; -static int prompt_skip; - -static int x_ins ARGS((char *cp)); -static void x_delete ARGS((int nc, int push)); -static int x_bword ARGS((void)); -static int x_fword ARGS((void)); -static void x_goto ARGS((char *cp)); -static void x_bs ARGS((int c)); -static int x_size_str ARGS((char *cp)); -static int x_size ARGS((int c)); -static void x_zots ARGS((char *str)); -static void x_zotc ARGS((int c)); -static void x_load_hist ARGS((char **hp)); -static int x_search ARGS((char *pat, int sameline, int offset)); -static int x_match ARGS((char *str, char *pat)); -static void x_redraw ARGS((int limit)); -static void x_push ARGS((int nchars)); -static char * x_mapin ARGS((const char *cp, Area *area)); -static char * x_mapout ARGS((int c)); -static void x_print ARGS((int prefix, int key)); -static void x_adjust ARGS((void)); -static void x_e_ungetc ARGS((int c)); -static int x_e_getc ARGS((void)); -static void x_e_putc ARGS((int c)); -static void x_e_puts ARGS((const char *s)); -static int x_comment ARGS((int c)); -static int x_fold_case ARGS((int c)); -static char *x_lastcp ARGS((void)); -static void do_complete ARGS((int flags, Comp_type type)); -static int x_emacs_putbuf ARGS((const char *s, size_t len)); - - -/* The lines between START-FUNC-TAB .. END-FUNC-TAB are run through a - * script (emacs-gen.sh) that generates emacs.out which contains: - * - function declarations for x_* functions - * - defines of the form XFUNC_ where is function - * name, sans leading x_. - * Note that the script treats #ifdef and { 0, 0, 0} specially - use with - * caution. - */ -#include "emacs.out" -static const struct x_ftab x_ftab[] = { -/* @START-FUNC-TAB@ */ - { x_abort, "abort", 0 }, - { x_beg_hist, "beginning-of-history", 0 }, - { x_comp_comm, "complete-command", 0 }, - { x_comp_file, "complete-file", 0 }, - { x_complete, "complete", 0 }, - { x_del_back, "delete-char-backward", XF_ARG }, - { x_del_bword, "delete-word-backward", XF_ARG }, - { x_del_char, "delete-char-forward", XF_ARG }, - { x_del_fword, "delete-word-forward", XF_ARG }, - { x_del_line, "kill-line", 0 }, - { x_draw_line, "redraw", 0 }, - { x_end_hist, "end-of-history", 0 }, - { x_end_of_text, "eot", 0 }, - { x_enumerate, "list", 0 }, - { x_eot_del, "eot-or-delete", XF_ARG }, - { x_error, "error", 0 }, - { x_goto_hist, "goto-history", XF_ARG }, - { x_ins_string, "macro-string", XF_NOBIND }, - { x_insert, "auto-insert", XF_ARG }, - { x_kill, "kill-to-eol", XF_ARG }, - { x_kill_region, "kill-region", 0 }, - { x_list_comm, "list-command", 0 }, - { x_list_file, "list-file", 0 }, - { x_literal, "quote", 0 }, - { x_meta1, "prefix-1", XF_PREFIX }, - { x_meta2, "prefix-2", XF_PREFIX }, - { x_meta_yank, "yank-pop", 0 }, - { x_mv_back, "backward-char", XF_ARG }, - { x_mv_begin, "beginning-of-line", 0 }, - { x_mv_bword, "backward-word", XF_ARG }, - { x_mv_end, "end-of-line", 0 }, - { x_mv_forw, "forward-char", XF_ARG }, - { x_mv_fword, "forward-word", XF_ARG }, - { x_newline, "newline", 0 }, - { x_next_com, "down-history", XF_ARG }, - { x_nl_next_com, "newline-and-next", 0 }, - { x_noop, "no-op", 0 }, - { x_prev_com, "up-history", XF_ARG }, - { x_prev_histword, "prev-hist-word", XF_ARG }, - { x_search_char_forw, "search-character-forward", XF_ARG }, - { x_search_char_back, "search-character-backward", XF_ARG }, - { x_search_hist, "search-history", 0 }, - { x_set_mark, "set-mark-command", 0 }, - { x_stuff, "stuff", 0 }, - { x_stuffreset, "stuff-reset", 0 }, - { x_transpose, "transpose-chars", 0 }, - { x_version, "version", 0 }, - { x_xchg_point_mark, "exchange-point-and-mark", 0 }, - { x_yank, "yank", 0 }, - { x_comp_list, "complete-list", 0 }, - { x_expand, "expand-file", 0 }, - { x_fold_capitalize, "capitalize-word", XF_ARG }, - { x_fold_lower, "downcase-word", XF_ARG }, - { x_fold_upper, "upcase-word", XF_ARG }, - { x_set_arg, "set-arg", XF_NOBIND }, - { x_comment, "comment", 0 }, -#ifdef SILLY - { x_game_of_life, "play-game-of-life", 0 }, -#else - { 0, 0, 0 }, -#endif -#ifdef DEBUG - { x_debug_info, "debug-info", 0 }, -#else - { 0, 0, 0 }, -#endif -#ifdef OS2 - { x_meta3, "prefix-3", XF_PREFIX }, -#else - { 0, 0, 0 }, -#endif -/* @END-FUNC-TAB@ */ - }; - -static struct x_defbindings const x_defbindings[] = { - { XFUNC_del_back, 0, CTRL('?') }, - { XFUNC_del_bword, 1, CTRL('?') }, - { XFUNC_eot_del, 0, CTRL('D') }, - { XFUNC_del_back, 0, CTRL('H') }, - { XFUNC_del_bword, 1, CTRL('H') }, - { XFUNC_del_bword, 1, 'h' }, - { XFUNC_mv_bword, 1, 'b' }, - { XFUNC_mv_fword, 1, 'f' }, - { XFUNC_del_fword, 1, 'd' }, - { XFUNC_mv_back, 0, CTRL('B') }, - { XFUNC_mv_forw, 0, CTRL('F') }, - { XFUNC_search_char_forw, 0, CTRL(']') }, - { XFUNC_search_char_back, 1, CTRL(']') }, - { XFUNC_newline, 0, CTRL('M') }, - { XFUNC_newline, 0, CTRL('J') }, - { XFUNC_end_of_text, 0, CTRL('_') }, - { XFUNC_abort, 0, CTRL('G') }, - { XFUNC_prev_com, 0, CTRL('P') }, - { XFUNC_next_com, 0, CTRL('N') }, - { XFUNC_nl_next_com, 0, CTRL('O') }, - { XFUNC_search_hist, 0, CTRL('R') }, - { XFUNC_beg_hist, 1, '<' }, - { XFUNC_end_hist, 1, '>' }, - { XFUNC_goto_hist, 1, 'g' }, - { XFUNC_mv_end, 0, CTRL('E') }, - { XFUNC_mv_begin, 0, CTRL('A') }, - { XFUNC_draw_line, 0, CTRL('L') }, - { XFUNC_meta1, 0, CTRL('[') }, - { XFUNC_meta2, 0, CTRL('X') }, - { XFUNC_kill, 0, CTRL('K') }, - { XFUNC_yank, 0, CTRL('Y') }, - { XFUNC_meta_yank, 1, 'y' }, - { XFUNC_literal, 0, CTRL('^') }, - { XFUNC_comment, 1, '#' }, -#if defined(BRL) && defined(TIOCSTI) - { XFUNC_stuff, 0, CTRL('T') }, -#else - { XFUNC_transpose, 0, CTRL('T') }, -#endif - { XFUNC_complete, 1, CTRL('[') }, - { XFUNC_comp_list, 0, CTRL('I') }, - { XFUNC_comp_list, 1, '=' }, - { XFUNC_enumerate, 1, '?' }, - { XFUNC_expand, 1, '*' }, - { XFUNC_comp_file, 1, CTRL('X') }, - { XFUNC_comp_comm, 2, CTRL('[') }, - { XFUNC_list_comm, 2, '?' }, - { XFUNC_list_file, 2, CTRL('Y') }, - { XFUNC_set_mark, 1, ' ' }, - { XFUNC_kill_region, 0, CTRL('W') }, - { XFUNC_xchg_point_mark, 2, CTRL('X') }, - { XFUNC_version, 0, CTRL('V') }, -#ifdef DEBUG - { XFUNC_debug_info, 1, CTRL('H') }, -#endif - { XFUNC_prev_histword, 1, '.' }, - { XFUNC_prev_histword, 1, '_' }, - { XFUNC_set_arg, 1, '0' }, - { XFUNC_set_arg, 1, '1' }, - { XFUNC_set_arg, 1, '2' }, - { XFUNC_set_arg, 1, '3' }, - { XFUNC_set_arg, 1, '4' }, - { XFUNC_set_arg, 1, '5' }, - { XFUNC_set_arg, 1, '6' }, - { XFUNC_set_arg, 1, '7' }, - { XFUNC_set_arg, 1, '8' }, - { XFUNC_set_arg, 1, '9' }, - { XFUNC_fold_upper, 1, 'U' }, - { XFUNC_fold_upper, 1, 'u' }, - { XFUNC_fold_lower, 1, 'L' }, - { XFUNC_fold_lower, 1, 'l' }, - { XFUNC_fold_capitalize, 1, 'C' }, - { XFUNC_fold_capitalize, 1, 'c' }, -#ifdef OS2 - { XFUNC_meta3, 0, 0xE0 }, - { XFUNC_mv_back, 3, 'K' }, - { XFUNC_mv_forw, 3, 'M' }, - { XFUNC_next_com, 3, 'P' }, - { XFUNC_prev_com, 3, 'H' }, -#endif /* OS2 */ - /* These for ansi arrow keys: arguablely shouldn't be here by - * default, but its simpler/faster/smaller than using termcap - * entries. - */ - { XFUNC_meta2, 1, '[' }, - { XFUNC_meta2, 1, 'O' }, - { XFUNC_prev_com, 2, 'A' }, - { XFUNC_next_com, 2, 'B' }, - { XFUNC_mv_forw, 2, 'C' }, - { XFUNC_mv_back, 2, 'D' }, -}; - -int -x_emacs(buf, len) - char *buf; - size_t len; -{ - int c; - const char *p; - int i; - Findex f; - - xbp = xbuf = buf; xend = buf + len; - xlp = xcp = xep = buf; - *xcp = 0; - xlp_valid = TRUE; - xmp = NULL; - x_curprefix = 0; - macroptr = (char *) 0; - x_histp = histptr + 1; - x_last_command = XFUNC_error; - - xx_cols = x_cols; - x_col = promptlen(prompt, &p); - prompt_skip = p - prompt; - prompt_trunc = x_col - (x_cols - 3 - MIN_EDIT_SPACE); - if (prompt_trunc > 0) - x_col -= prompt_trunc; - else - prompt_trunc = 0; - x_adj_ok = 1; - x_displen = xx_cols - 2 - x_col; - x_adj_done = 0; - - pprompt(prompt, prompt_trunc); - - if (x_nextcmd >= 0) { - int off = source->line - x_nextcmd; - if (histptr - histlist >= off) - x_load_hist(histptr - off); - x_nextcmd = -1; - } - - while (1) { - x_flush(); - if ((c = x_e_getc()) < 0) - return 0; - - if (ISMETA(c)) { - c = META(c); - x_curprefix = 1; - } - - f = x_curprefix == -1 ? XFUNC_insert - : x_tab[x_curprefix][c&CHARMASK]; - - if (!(x_ftab[f].xf_flags & XF_PREFIX) - && x_last_command != XFUNC_set_arg) - { - x_arg = 1; - x_arg_defaulted = 1; - } - i = c | (x_curprefix << 8); - x_curprefix = 0; - switch (i = (*x_ftab[f].xf_func)(i)) { - case KSTD: - if (!(x_ftab[f].xf_flags & XF_PREFIX)) - x_last_command = f; - break; - case KEOL: - i = xep - xbuf; - return i; - case KINTR: /* special case for interrupt */ - trapsig(SIGINT); - x_mode(FALSE); - unwind(LSHELL); - } - } -} - -static int -x_insert(c) - int c; -{ - char str[2]; - - /* - * Should allow tab and control chars. - */ - if (c == 0) { - x_e_putc(BEL); - return KSTD; - } - str[0] = c; - str[1] = '\0'; - while (x_arg--) - x_ins(str); - return KSTD; -} - -static int -x_ins_string(c) - int c; -{ - if (macroptr) { - x_e_putc(BEL); - return KSTD; - } - macroptr = x_atab[c>>8][c & CHARMASK]; - if (macroptr && !*macroptr) { - /* XXX bell? */ - macroptr = (char *) 0; - } - return KSTD; -} - -static int x_do_ins(const char *cp, int len); - -static int -x_do_ins(cp, len) - const char *cp; - int len; -{ - if (xep+len >= xend) { - x_e_putc(BEL); - return -1; - } - - memmove(xcp+len, xcp, xep - xcp + 1); - memmove(xcp, cp, len); - xcp += len; - xep += len; - return 0; -} - -static int -x_ins(s) - char *s; -{ - char *cp = xcp; - register int adj = x_adj_done; - - if (x_do_ins(s, strlen(s)) < 0) - return -1; - /* - * x_zots() may result in a call to x_adjust() - * we want xcp to reflect the new position. - */ - xlp_valid = FALSE; - x_lastcp(); - x_adj_ok = (xcp >= xlp); - x_zots(cp); - if (adj == x_adj_done) /* has x_adjust() been called? */ - { - /* no */ - for (cp = xlp; cp > xcp; ) - x_bs(*--cp); - } - - x_adj_ok = 1; - return 0; -} - -/* - * this is used for x_escape() in do_complete() - */ -static int -x_emacs_putbuf(s, len) - const char *s; - size_t len; -{ - int rval; - - if ((rval = x_do_ins(s, len)) != 0) - return (rval); - return (rval); -} - -static int -x_del_back(c) - int c; -{ - int col = xcp - xbuf; - - if (col == 0) { - x_e_putc(BEL); - return KSTD; - } - if (x_arg > col) - x_arg = col; - x_goto(xcp - x_arg); - x_delete(x_arg, FALSE); - return KSTD; -} - -static int -x_del_char(c) - int c; -{ - int nleft = xep - xcp; - - if (!nleft) { - x_e_putc(BEL); - return KSTD; - } - if (x_arg > nleft) - x_arg = nleft; - x_delete(x_arg, FALSE); - return KSTD; -} - -/* Delete nc chars to the right of the cursor (including cursor position) */ -static void -x_delete(nc, push) - int nc; - int push; -{ - int i,j; - char *cp; - - if (nc == 0) - return; - if (xmp != NULL && xmp > xcp) { - if (xcp + nc > xmp) - xmp = xcp; - else - xmp -= nc; - } - - /* - * This lets us yank a word we have deleted. - */ - if (push) - x_push(nc); - - xep -= nc; - cp = xcp; - j = 0; - i = nc; - while (i--) { - j += x_size(*cp++); - } - memmove(xcp, xcp+nc, xep - xcp + 1); /* Copies the null */ - x_adj_ok = 0; /* don't redraw */ - x_zots(xcp); - /* - * if we are already filling the line, - * there is no need to ' ','\b'. - * But if we must, make sure we do the minimum. - */ - if ((i = x_displen) > 0) - { - j = (j < i) ? j : i; - i = j; - while (i--) - x_e_putc(' '); - i = j; - while (i--) - x_e_putc('\b'); - } - /*x_goto(xcp);*/ - x_adj_ok = 1; - xlp_valid = FALSE; - for (cp = x_lastcp(); cp > xcp; ) - x_bs(*--cp); - - return; -} - -static int -x_del_bword(c) - int c; -{ - x_delete(x_bword(), TRUE); - return KSTD; -} - -static int -x_mv_bword(c) - int c; -{ - (void)x_bword(); - return KSTD; -} - -static int -x_mv_fword(c) - int c; -{ - x_goto(xcp + x_fword()); - return KSTD; -} - -static int -x_del_fword(c) - int c; -{ - x_delete(x_fword(), TRUE); - return KSTD; -} - -static int -x_bword() -{ - int nc = 0; - register char *cp = xcp; - - if (cp == xbuf) { - x_e_putc(BEL); - return 0; - } - while (x_arg--) - { - while (cp != xbuf && is_mfs(cp[-1])) - { - cp--; - nc++; - } - while (cp != xbuf && !is_mfs(cp[-1])) - { - cp--; - nc++; - } - } - x_goto(cp); - return nc; -} - -static int -x_fword() -{ - int nc = 0; - register char *cp = xcp; - - if (cp == xep) { - x_e_putc(BEL); - return 0; - } - while (x_arg--) - { - while (cp != xep && is_mfs(*cp)) - { - cp++; - nc++; - } - while (cp != xep && !is_mfs(*cp)) - { - cp++; - nc++; - } - } - return nc; -} - -static void -x_goto(cp) - register char *cp; -{ - if (cp < xbp || cp >= (xbp + x_displen)) - { - /* we are heading off screen */ - xcp = cp; - x_adjust(); - } - else - { - if (cp < xcp) /* move back */ - { - while (cp < xcp) - x_bs(*--xcp); - } - else - { - if (cp > xcp) /* move forward */ - { - while (cp > xcp) - x_zotc(*xcp++); - } - } - } -} - -static void -x_bs(c) - int c; -{ - register int i; - i = x_size(c); - while (i--) - x_e_putc('\b'); -} - -static int -x_size_str(cp) - register char *cp; -{ - register int size = 0; - while (*cp) - size += x_size(*cp++); - return size; -} - -static int -x_size(c) - int c; -{ - if (c=='\t') - return 4; /* Kludge, tabs are always four spaces. */ - if (iscntrl((unsigned char)c)) /* control char */ - return 2; - return 1; -} - -static void -x_zots(str) - register char *str; -{ - register int adj = x_adj_done; - - x_lastcp(); - while (*str && str < xlp && adj == x_adj_done) - x_zotc(*str++); -} - -static void -x_zotc(c) - int c; -{ - if (c == '\t') { - /* Kludge, tabs are always four spaces. */ - x_e_puts(" "); - } else if (iscntrl((unsigned char)c)) { - x_e_putc('^'); - x_e_putc(UNCTRL(c)); - } else - x_e_putc(c); -} - -static int -x_mv_back(c) - int c; -{ - int col = xcp - xbuf; - - if (col == 0) { - x_e_putc(BEL); - return KSTD; - } - if (x_arg > col) - x_arg = col; - x_goto(xcp - x_arg); - return KSTD; -} - -static int -x_mv_forw(c) - int c; -{ - int nleft = xep - xcp; - - if (!nleft) { - x_e_putc(BEL); - return KSTD; - } - if (x_arg > nleft) - x_arg = nleft; - x_goto(xcp + x_arg); - return KSTD; -} - -static int -x_search_char_forw(c) - int c; -{ - char *cp = xcp; - - *xep = '\0'; - c = x_e_getc(); - while (x_arg--) { - if (c < 0 - || ((cp = (cp == xep) ? NULL : strchr(cp + 1, c)) == NULL - && (cp = strchr(xbuf, c)) == NULL)) - { - x_e_putc(BEL); - return KSTD; - } - } - x_goto(cp); - return KSTD; -} - -static int -x_search_char_back(c) - int c; -{ - char *cp = xcp, *p; - - c = x_e_getc(); - for (; x_arg--; cp = p) - for (p = cp; ; ) { - if (p-- == xbuf) - p = xep; - if (c < 0 || p == cp) { - x_e_putc(BEL); - return KSTD; - } - if (*p == c) - break; - } - x_goto(cp); - return KSTD; -} - -static int -x_newline(c) - int c; -{ - x_e_putc('\r'); - x_e_putc('\n'); - x_flush(); - *xep++ = '\n'; - return KEOL; -} - -static int -x_end_of_text(c) - int c; -{ - return KEOL; -} - -static int x_beg_hist(c) int c; { x_load_hist(histlist); return KSTD;} - -static int x_end_hist(c) int c; { x_load_hist(histptr); return KSTD;} - -static int x_prev_com(c) int c; { x_load_hist(x_histp - x_arg); return KSTD;} - -static int x_next_com(c) int c; { x_load_hist(x_histp + x_arg); return KSTD;} - -/* Goto a particular history number obtained from argument. - * If no argument is given history 1 is probably not what you - * want so we'll simply go to the oldest one. - */ -static int -x_goto_hist(c) - int c; -{ - if (x_arg_defaulted) - x_load_hist(histlist); - else - x_load_hist(histptr + x_arg - source->line); - return KSTD; -} - -static void -x_load_hist(hp) - register char **hp; -{ - int oldsize; - - if (hp < histlist || hp > histptr) { - x_e_putc(BEL); - return; - } - x_histp = hp; - oldsize = x_size_str(xbuf); - strlcpy(xbuf, *hp, xend - xbuf); - xbp = xbuf; - xep = xcp = xbuf + strlen(xbuf); - xlp_valid = FALSE; - if (xep > x_lastcp()) - x_goto(xep); - else - x_redraw(oldsize); -} - -static int -x_nl_next_com(c) - int c; -{ - x_nextcmd = source->line - (histptr - x_histp) + 1; - return (x_newline(c)); -} - -static int -x_eot_del(c) - int c; -{ - if (xep == xbuf && x_arg_defaulted) - return (x_end_of_text(c)); - else - return (x_del_char(c)); -} - -/* reverse incremental history search */ -static int -x_search_hist(c) - int c; -{ - int offset = -1; /* offset of match in xbuf, else -1 */ - char pat [256+1]; /* pattern buffer */ - register char *p = pat; - Findex f; - - *p = '\0'; - while (1) { - if (offset < 0) { - x_e_puts("\nI-search: "); - x_e_puts(pat); - } - x_flush(); - if ((c = x_e_getc()) < 0) - return KSTD; - f = x_tab[0][c&CHARMASK]; - if (c == CTRL('[')) - break; - else if (f == XFUNC_search_hist) - offset = x_search(pat, 0, offset); - else if (f == XFUNC_del_back) { - if (p == pat) { - offset = -1; - break; - } - if (p > pat) - *--p = '\0'; - if (p == pat) - offset = -1; - else - offset = x_search(pat, 1, offset); - continue; - } else if (f == XFUNC_insert) { - /* add char to pattern */ - /* overflow check... */ - if (p >= &pat[sizeof(pat) - 1]) { - x_e_putc(BEL); - continue; - } - *p++ = c, *p = '\0'; - if (offset >= 0) { - /* already have partial match */ - offset = x_match(xbuf, pat); - if (offset >= 0) { - x_goto(xbuf + offset + (p - pat) - (*pat == '^')); - continue; - } - } - offset = x_search(pat, 0, offset); - } else { /* other command */ - x_e_ungetc(c); - break; - } - } - if (offset < 0) - x_redraw(-1); - return KSTD; -} - -/* search backward from current line */ -static int -x_search(pat, sameline, offset) - char *pat; - int sameline; - int offset; -{ - register char **hp; - int i; - - for (hp = x_histp - (sameline ? 0 : 1) ; hp >= histlist; --hp) { - i = x_match(*hp, pat); - if (i >= 0) { - if (offset < 0) - x_e_putc('\n'); - x_load_hist(hp); - x_goto(xbuf + i + strlen(pat) - (*pat == '^')); - return i; - } - } - x_e_putc(BEL); - x_histp = histptr; - return -1; -} - -/* return position of first match of pattern in string, else -1 */ -static int -x_match(str, pat) - char *str, *pat; -{ - if (*pat == '^') { - return (strncmp(str, pat+1, strlen(pat+1)) == 0) ? 0 : -1; - } else { - char *q = strstr(str, pat); - return (q == NULL) ? -1 : q - str; - } -} - -static int -x_del_line(c) - int c; -{ - int i, j; - - *xep = 0; - i = xep - xbuf; - j = x_size_str(xbuf); - xcp = xbuf; - x_push(i); - xlp = xbp = xep = xbuf; - xlp_valid = TRUE; - *xcp = 0; - xmp = NULL; - x_redraw(j); - return KSTD; -} - -static int -x_mv_end(c) - int c; -{ - x_goto(xep); - return KSTD; -} - -static int -x_mv_begin(c) - int c; -{ - x_goto(xbuf); - return KSTD; -} - -static int -x_draw_line(c) - int c; -{ - x_redraw(-1); - return KSTD; - -} - -/* Redraw (part of) the line. If limit is < 0, the everything is redrawn - * on a NEW line, otherwise limit is the screen column up to which needs - * redrawing. - */ -static void -x_redraw(limit) - int limit; -{ - int i, j; - char *cp; - - x_adj_ok = 0; - if (limit == -1) - x_e_putc('\n'); - else - x_e_putc('\r'); - x_flush(); - if (xbp == xbuf) - { - pprompt(prompt + prompt_skip, 0); - x_col = promptlen(prompt, (const char **) 0); - } - x_displen = xx_cols - 2 - x_col; - xlp_valid = FALSE; - cp = x_lastcp(); - x_zots(xbp); - if (xbp != xbuf || xep > xlp) - limit = xx_cols; - if (limit >= 0) - { - if (xep > xlp) - i = 0; /* we fill the line */ - else - i = limit - (xlp - xbp); - - for (j = 0; j < i && x_col < (xx_cols - 2); j++) - x_e_putc(' '); - i = ' '; - if (xep > xlp) /* more off screen */ - { - if (xbp > xbuf) - i = '*'; - else - i = '>'; - } - else - if (xbp > xbuf) - i = '<'; - x_e_putc(i); - j++; - while (j--) - x_e_putc('\b'); - } - for (cp = xlp; cp > xcp; ) - x_bs(*--cp); - x_adj_ok = 1; - D__(x_flush();) - return; -} - -static int -x_transpose(c) - int c; -{ - char tmp; - - /* What transpose is meant to do seems to be up for debate. This - * is a general summary of the options; the text is abcd with the - * upper case character or underscore indicating the cursor position: - * Who Before After Before After - * at&t ksh in emacs mode: abCd abdC abcd_ (bell) - * at&t ksh in gmacs mode: abCd baCd abcd_ abdc_ - * gnu emacs: abCd acbD abcd_ abdc_ - * Pdksh currently goes with GNU behavior since I believe this is the - * most common version of emacs, unless in gmacs mode, in which case - * it does the at&t ksh gmacs mode. - * This should really be broken up into 3 functions so users can bind - * to the one they want. - */ - if (xcp == xbuf) { - x_e_putc(BEL); - return KSTD; - } else if (xcp == xep || Flag(FGMACS)) { - if (xcp - xbuf == 1) { - x_e_putc(BEL); - return KSTD; - } - /* Gosling/Unipress emacs style: Swap two characters before the - * cursor, do not change cursor position - */ - x_bs(xcp[-1]); - x_bs(xcp[-2]); - x_zotc(xcp[-1]); - x_zotc(xcp[-2]); - tmp = xcp[-1]; - xcp[-1] = xcp[-2]; - xcp[-2] = tmp; - } else { - /* GNU emacs style: Swap the characters before and under the - * cursor, move cursor position along one. - */ - x_bs(xcp[-1]); - x_zotc(xcp[0]); - x_zotc(xcp[-1]); - tmp = xcp[-1]; - xcp[-1] = xcp[0]; - xcp[0] = tmp; - x_bs(xcp[0]); - x_goto(xcp + 1); - } - return KSTD; -} - -static int -x_literal(c) - int c; -{ - x_curprefix = -1; - return KSTD; -} - -static int -x_meta1(c) - int c; -{ - x_curprefix = 1; - return KSTD; -} - -static int -x_meta2(c) - int c; -{ - x_curprefix = 2; - return KSTD; -} - -#ifdef OS2 -static int -x_meta3(c) - int c; -{ - x_curprefix = 3; - return KSTD; -} -#endif /* OS2 */ - -static int -x_kill(c) - int c; -{ - int col = xcp - xbuf; - int lastcol = xep - xbuf; - int ndel; - - if (x_arg_defaulted) - x_arg = lastcol; - else if (x_arg > lastcol) - x_arg = lastcol; - ndel = x_arg - col; - if (ndel < 0) { - x_goto(xbuf + x_arg); - ndel = -ndel; - } - x_delete(ndel, TRUE); - return KSTD; -} - -static void -x_push(nchars) - int nchars; -{ - char *cp = str_nsave(xcp, nchars, AEDIT); - if (killstack[killsp]) - afree((void *)killstack[killsp], AEDIT); - killstack[killsp] = cp; - killsp = (killsp + 1) % KILLSIZE; -} - -static int -x_yank(c) - int c; -{ - if (killsp == 0) - killtp = KILLSIZE; - else - killtp = killsp; - killtp--; - if (killstack[killtp] == 0) { - x_e_puts("\nnothing to yank"); - x_redraw(-1); - return KSTD; - } - xmp = xcp; - x_ins(killstack[killtp]); - return KSTD; -} - -static int -x_meta_yank(c) - int c; -{ - int len; - if ((x_last_command != XFUNC_yank && x_last_command != XFUNC_meta_yank) - || killstack[killtp] == 0) { - killtp = killsp; - x_e_puts("\nyank something first"); - x_redraw(-1); - return KSTD; - } - len = strlen(killstack[killtp]); - x_goto(xcp - len); - x_delete(len, FALSE); - do { - if (killtp == 0) - killtp = KILLSIZE - 1; - else - killtp--; - } while (killstack[killtp] == 0); - x_ins(killstack[killtp]); - return KSTD; -} - -static int -x_abort(c) - int c; -{ - /* x_zotc(c); */ - xlp = xep = xcp = xbp = xbuf; - xlp_valid = TRUE; - *xcp = 0; - return KINTR; -} - -static int -x_error(c) - int c; -{ - x_e_putc(BEL); - return KSTD; -} - -static int -x_stuffreset(c) - int c; -{ -#ifdef TIOCSTI - (void)x_stuff(c); - return KINTR; -#else - x_zotc(c); - xlp = xcp = xep = xbp = xbuf; - xlp_valid = TRUE; - *xcp = 0; - x_redraw(-1); - return KSTD; -#endif -} - -static int -x_stuff(c) - int c; -{ -#if 0 || defined TIOCSTI - char ch = c; - bool_t savmode = x_mode(FALSE); - - (void)ioctl(TTY, TIOCSTI, &ch); - (void)x_mode(savmode); - x_redraw(-1); -#endif - return KSTD; -} - -static char * -x_mapin(cp, area) - const char *cp; - Area *area; -{ - char *new, *op; - - op = new = str_save(cp, area); - while (*cp) { - /* XXX -- should handle \^ escape? */ - if (*cp == '^') { - cp++; -#ifdef OS2 - if (*cp == '0') /* To define function keys */ - *op++ = 0xE0; - else -#endif /* OS2 */ - if (*cp >= '?') /* includes '?'; ASCII */ - *op++ = CTRL(*cp); - else { - *op++ = '^'; - cp--; - } - } else - *op++ = *cp; - cp++; - } - *op = '\0'; - - return new; -} - -static char * -x_mapout(c) - int c; -{ - static char buf[8]; - register char *p = buf; - -#ifdef OS2 - if (c == 0xE0) { - *p++ = '^'; - *p++ = '0'; - } else -#endif /* OS2 */ - if (iscntrl((unsigned char)c)) { - *p++ = '^'; - *p++ = UNCTRL(c); - } else - *p++ = c; - *p = 0; - return buf; -} - -static void -x_print(prefix, key) - int prefix, key; -{ - if (prefix == 1) - shprintf("%s", x_mapout(x_prefix1)); - if (prefix == 2) - shprintf("%s", x_mapout(x_prefix2)); -#ifdef OS2 - if (prefix == 3) - shprintf("%s", x_mapout(x_prefix3)); -#endif /* OS2 */ - shprintf("%s = ", x_mapout(key)); - if (x_tab[prefix][key] != XFUNC_ins_string) - shprintf("%s\n", x_ftab[x_tab[prefix][key]].xf_name); - else - shprintf("'%s'\n", x_atab[prefix][key]); -} - -int -x_bind(a1, a2, macro, list) - const char *a1, *a2; - int macro; /* bind -m */ - int list; /* bind -l */ -{ - Findex f; - int prefix, key; - char *sp = NULL; - char *m1, *m2; - - if (x_tab == NULL) { - bi_errorf("cannot bind, not a tty"); - return 1; - } - - /* List function names */ - if (list) { - for (f = 0; f < NELEM(x_ftab); f++) - if (x_ftab[f].xf_name - && !(x_ftab[f].xf_flags & XF_NOBIND)) - shprintf("%s\n", x_ftab[f].xf_name); - return 0; - } - - if (a1 == NULL) { - for (prefix = 0; prefix < X_NTABS; prefix++) - for (key = 0; key < X_TABSZ; key++) { - f = x_tab[prefix][key]; - if (f == XFUNC_insert || f == XFUNC_error - || (macro && f != XFUNC_ins_string)) - continue; - x_print(prefix, key); - } - return 0; - } - - m2 = m1 = x_mapin(a1, ATEMP); - prefix = key = 0; - for (;; m1++) { - key = *m1 & CHARMASK; - if (x_tab[prefix][key] == XFUNC_meta1) - prefix = 1; - else if (x_tab[prefix][key] == XFUNC_meta2) - prefix = 2; -#ifdef OS2 - else if (x_tab[prefix][key] == XFUNC_meta3) - prefix = 3; -#endif /* OS2 */ - else - break; - } - afree(m2, ATEMP); - - if (a2 == NULL) { - x_print(prefix, key); - return 0; - } - - if (*a2 == 0) - f = XFUNC_insert; - else if (!macro) { - for (f = 0; f < NELEM(x_ftab); f++) - if (x_ftab[f].xf_name - && strcmp(x_ftab[f].xf_name, a2) == 0) - break; - if (f == NELEM(x_ftab) || x_ftab[f].xf_flags & XF_NOBIND) { - bi_errorf("%s: no such function", a2); - return 1; - } -#if 0 /* This breaks the bind commands that map arrow keys */ - if (f == XFUNC_meta1) - x_prefix1 = key; - if (f == XFUNC_meta2) - x_prefix2 = key; -#endif /* 0 */ - } else { - f = XFUNC_ins_string; - sp = x_mapin(a2, AEDIT); - } - - if (x_tab[prefix][key] == XFUNC_ins_string && x_atab[prefix][key]) - afree((void *)x_atab[prefix][key], AEDIT); - x_tab[prefix][key] = f; - x_atab[prefix][key] = sp; - - /* Track what the user has bound so x_emacs_keys() won't toast things */ - if (f == XFUNC_insert) - x_bound[(prefix * X_TABSZ + key) / 8] &= - ~(1 << ((prefix * X_TABSZ + key) % 8)); - else - x_bound[(prefix * X_TABSZ + key) / 8] |= - (1 << ((prefix * X_TABSZ + key) % 8)); - - return 0; -} - -void -x_init_emacs() -{ - size_t i; - register int j; - char *locale; - - ainit(AEDIT); - x_nextcmd = -1; - - x_tab = (Findex (*)[X_TABSZ]) alloc(sizeofN(*x_tab, X_NTABS), AEDIT); - for (j = 0; j < X_TABSZ; j++) - x_tab[0][j] = XFUNC_insert; - for (i = 1; i < X_NTABS; i++) - for (j = 0; j < X_TABSZ; j++) - x_tab[i][j] = XFUNC_error; - for (i = 0; i < NELEM(x_defbindings); i++) - x_tab[(unsigned char)x_defbindings[i].xdb_tab][x_defbindings[i].xdb_char] - = x_defbindings[i].xdb_func; - - x_atab = (char *(*)[X_TABSZ]) alloc(sizeofN(*x_atab, X_NTABS), AEDIT); - for (i = 1; i < X_NTABS; i++) - for (j = 0; j < X_TABSZ; j++) - x_atab[i][j] = NULL; - - /* Determine if we can translate meta key or use 8-bit AscII - * XXX - It would be nice if there was a locale attribute to - * determine if the locale is 7-bit or not. - */ - locale = setlocale(LC_CTYPE, NULL); - if (locale == NULL || !strcmp(locale, "C") || !strcmp(locale, "POSIX")) - Flag(FEMACSUSEMETA) = 0; -} - -static void bind_if_not_bound(int p, int k, int func); - -static void -bind_if_not_bound(p, k, func) - int p, k; - int func; -{ - /* Has user already bound this key? If so, don't override it */ - if (x_bound[((p) * X_TABSZ + (k)) / 8] - & (1 << (((p) * X_TABSZ + (k)) % 8))) - return; - - x_tab[p][k] = func; -} - -void -x_emacs_keys(ec) - X_chars *ec; -{ - if (ec->erase >= 0) { - bind_if_not_bound(0, ec->erase, XFUNC_del_back); - bind_if_not_bound(1, ec->erase, XFUNC_del_bword); - } - if (ec->kill >= 0) - bind_if_not_bound(0, ec->kill, XFUNC_del_line); - if (ec->werase >= 0) - bind_if_not_bound(0, ec->werase, XFUNC_del_bword); - if (ec->intr >= 0) - bind_if_not_bound(0, ec->intr, XFUNC_abort); - if (ec->quit >= 0) - bind_if_not_bound(0, ec->quit, XFUNC_noop); -} - -static int -x_set_mark(c) - int c; -{ - xmp = xcp; - return KSTD; -} - -static int -x_kill_region(c) - int c; -{ - int rsize; - char *xr; - - if (xmp == NULL) { - x_e_putc(BEL); - return KSTD; - } - if (xmp > xcp) { - rsize = xmp - xcp; - xr = xcp; - } else { - rsize = xcp - xmp; - xr = xmp; - } - x_goto(xr); - x_delete(rsize, TRUE); - xmp = xr; - return KSTD; -} - -static int -x_xchg_point_mark(c) - int c; -{ - char *tmp; - - if (xmp == NULL) { - x_e_putc(BEL); - return KSTD; - } - tmp = xmp; - xmp = xcp; - x_goto( tmp ); - return KSTD; -} - -static int -x_version(c) - int c; -{ - char *o_xbuf = xbuf, *o_xend = xend; - char *o_xbp = xbp, *o_xep = xep, *o_xcp = xcp; - int lim = x_lastcp() - xbp; - - xbuf = xbp = xcp = ksh_version + 4; - xend = xep = ksh_version + 4 + strlen(ksh_version + 4); - x_redraw(lim); - x_flush(); - - c = x_e_getc(); - xbuf = o_xbuf; - xend = o_xend; - xbp = o_xbp; - xep = o_xep; - xcp = o_xcp; - x_redraw(strlen(ksh_version)); - - if (c < 0) - return KSTD; - /* This is what at&t ksh seems to do... Very bizarre */ - if (c != ' ') - x_e_ungetc(c); - - return KSTD; -} - -static int -x_noop(c) - int c; -{ - return KSTD; -} - -#ifdef SILLY -static int -x_game_of_life(c) - int c; -{ - char newbuf [256+1]; - register char *ip, *op; - int i, len; - - i = xep - xbuf; - *xep = 0; - len = x_size_str(xbuf); - xcp = xbp = xbuf; - memmove(newbuf+1, xbuf, i); - newbuf[0] = 'A'; - newbuf[i] = 'A'; - for (ip = newbuf+1, op = xbuf; --i >= 0; ip++, op++) { - /* Empty space */ - if (*ip < '@' || *ip == '_' || *ip == 0x7F) { - /* Two adults, make whoopee */ - if (ip[-1] < '_' && ip[1] < '_') { - /* Make kid look like parents. */ - *op = '`' + ((ip[-1] + ip[1])/2)%32; - if (*op == 0x7F) /* Birth defect */ - *op = '`'; - } - else - *op = ' '; /* nothing happens */ - continue; - } - /* Child */ - if (*ip > '`') { - /* All alone, dies */ - if (ip[-1] == ' ' && ip[1] == ' ') - *op = ' '; - else /* Gets older */ - *op = *ip-'`'+'@'; - continue; - } - /* Adult */ - /* Overcrowded, dies */ - if (ip[-1] >= '@' && ip[1] >= '@') { - *op = ' '; - continue; - } - *op = *ip; - } - *op = 0; - x_redraw(len); - return KSTD; -} -#endif - -/* - * File/command name completion routines - */ - - -static int -x_comp_comm(c) - int c; -{ - do_complete(XCF_COMMAND, CT_COMPLETE); - return KSTD; -} -static int -x_list_comm(c) - int c; -{ - do_complete(XCF_COMMAND, CT_LIST); - return KSTD; -} -static int -x_complete(c) - int c; -{ - do_complete(XCF_COMMAND_FILE, CT_COMPLETE); - return KSTD; -} -static int -x_enumerate(c) - int c; -{ - do_complete(XCF_COMMAND_FILE, CT_LIST); - return KSTD; -} -static int -x_comp_file(c) - int c; -{ - do_complete(XCF_FILE, CT_COMPLETE); - return KSTD; -} -static int -x_list_file(c) - int c; -{ - do_complete(XCF_FILE, CT_LIST); - return KSTD; -} -static int -x_comp_list(c) - int c; -{ - do_complete(XCF_COMMAND_FILE, CT_COMPLIST); - return KSTD; -} -static int -x_expand(c) - int c; -{ - char **words; - int nwords = 0; - int start, end; - int is_command; - int i; - - nwords = x_cf_glob(XCF_FILE, - xbuf, xep - xbuf, xcp - xbuf, - &start, &end, &words, &is_command); - - if (nwords == 0) { - x_e_putc(BEL); - return KSTD; - } - - x_goto(xbuf + start); - x_delete(end - start, FALSE); - for (i = 0; i < nwords;) { - if (x_escape(words[i], strlen(words[i]), x_emacs_putbuf) < 0 || - (++i < nwords && x_ins(space) < 0)) - { - x_e_putc(BEL); - return KSTD; - } - } - x_adjust(); - - return KSTD; -} - -/* type == 0 for list, 1 for complete and 2 for complete-list */ -static void -do_complete(flags, type) - int flags; /* XCF_{COMMAND,FILE,COMMAND_FILE} */ - Comp_type type; -{ - char **words; - int nwords; - int start, end, nlen, olen; - int is_command; - int completed = 0; - - nwords = x_cf_glob(flags, xbuf, xep - xbuf, xcp - xbuf, - &start, &end, &words, &is_command); - /* no match */ - if (nwords == 0) { - x_e_putc(BEL); - return; - } - - if (type == CT_LIST) { - x_print_expansions(nwords, words, is_command); - x_redraw(0); - x_free_words(nwords, words); - return; - } - - olen = end - start; - nlen = x_longest_prefix(nwords, words); - /* complete */ - if (nwords == 1 || nlen > olen) { - x_goto(xbuf + start); - x_delete(olen, FALSE); - x_escape(words[0], nlen, x_emacs_putbuf); - x_adjust(); - completed = 1; - } - /* add space if single non-dir match */ - if ((nwords == 1) && (!ISDIRSEP(words[0][nlen - 1]))) { - x_ins(space); - completed = 1; - } - - if (type == CT_COMPLIST && !completed) { - x_print_expansions(nwords, words, is_command); - completed = 1; - } - - if (completed) - x_redraw(0); - - x_free_words(nwords, words); -} - -/* NAME: - * x_adjust - redraw the line adjusting starting point etc. - * - * DESCRIPTION: - * This function is called when we have exceeded the bounds - * of the edit window. It increments x_adj_done so that - * functions like x_ins and x_delete know that we have been - * called and can skip the x_bs() stuff which has already - * been done by x_redraw. - * - * RETURN VALUE: - * None - */ - -static void -x_adjust() -{ - x_adj_done++; /* flag the fact that we were called. */ - /* - * we had a problem if the prompt length > xx_cols / 2 - */ - if ((xbp = xcp - (x_displen / 2)) < xbuf) - xbp = xbuf; - xlp_valid = FALSE; - x_redraw(xx_cols); - x_flush(); -} - -static int unget_char = -1; - -static void -x_e_ungetc(c) - int c; -{ - unget_char = c; -} - -static int -x_e_getc() -{ - int c; - - if (unget_char >= 0) { - c = unget_char; - unget_char = -1; - } else { - if (macroptr) { - c = (unsigned char) *macroptr++; - if (!*macroptr) - macroptr = (char *) 0; - } else - c = x_getc(); - } - - return c <= CHARMASK ? c : (c & CHARMASK); -} - -static void -x_e_putc(c) - int c; -{ - if (c == '\r' || c == '\n') - x_col = 0; - if (x_col < xx_cols) - { - x_putc(c); - switch(c) - { - case BEL: - break; - case '\r': - case '\n': - break; - case '\b': - x_col--; - break; - default: - x_col++; - break; - } - } - if (x_adj_ok && (x_col < 0 || x_col >= (xx_cols - 2))) - { - x_adjust(); - } -} - -#ifdef DEBUG -static int -x_debug_info(c) - int c; -{ - x_flush(); - shellf("\nksh debug:\n"); - shellf("\tx_col == %d,\t\tx_cols == %d,\tx_displen == %d\n", - x_col, xx_cols, x_displen); - shellf("\txcp == 0x%lx,\txep == 0x%lx\n", (long) xcp, (long) xep); - shellf("\txbp == 0x%lx,\txbuf == 0x%lx\n", (long) xbp, (long) xbuf); - shellf("\txlp == 0x%lx\n", (long) xlp); - shellf("\txlp == 0x%lx\n", (long) x_lastcp()); - shellf(newline); - x_redraw(-1); - return 0; -} -#endif - -static void -x_e_puts(s) - const char *s; -{ - register int adj = x_adj_done; - - while (*s && adj == x_adj_done) - x_e_putc(*s++); -} - -/* NAME: - * x_set_arg - set an arg value for next function - * - * DESCRIPTION: - * This is a simple implementation of M-[0-9]. - * - * RETURN VALUE: - * KSTD - */ - -static int -x_set_arg(c) - int c; -{ - int n = 0; - int first = 1; - - c &= CHARMASK; /* strip command prefix */ - for (; c >= 0 && isdigit(c); c = x_e_getc(), first = 0) - n = n * 10 + (c - '0'); - if (c < 0 || first) { - x_e_putc(BEL); - x_arg = 1; - x_arg_defaulted = 1; - } else { - x_e_ungetc(c); - x_arg = n; - x_arg_defaulted = 0; - } - return KSTD; -} - - -/* Comment or uncomment the current line. */ -static int -x_comment(c) - int c; -{ - int oldsize = x_size_str(xbuf); - int len = xep - xbuf; - int ret = x_do_comment(xbuf, xend - xbuf, &len); - - if (ret < 0) - x_e_putc(BEL); - else { - xep = xbuf + len; - *xep = '\0'; - xcp = xbp = xbuf; - x_redraw(oldsize); - if (ret > 0) - return x_newline('\n'); - } - return KSTD; -} - - -/* NAME: - * x_prev_histword - recover word from prev command - * - * DESCRIPTION: - * This function recovers the last word from the previous - * command and inserts it into the current edit line. If a - * numeric arg is supplied then the n'th word from the - * start of the previous command is used. - * - * Bound to M-. - * - * RETURN VALUE: - * KSTD - */ - -static int -x_prev_histword(c) - int c; -{ - register char *rcp; - char *cp; - - cp = *histptr; - if (!cp) - x_e_putc(BEL); - else if (x_arg_defaulted) { - rcp = &cp[strlen(cp) - 1]; - /* - * ignore white-space after the last word - */ - while (rcp > cp && is_cfs(*rcp)) - rcp--; - while (rcp > cp && !is_cfs(*rcp)) - rcp--; - if (is_cfs(*rcp)) - rcp++; - x_ins(rcp); - } else { - int i; - - rcp = cp; - /* - * ignore white-space at start of line - */ - while (*rcp && is_cfs(*rcp)) - rcp++; - while (x_arg-- > 1) - { - while (*rcp && !is_cfs(*rcp)) - rcp++; - while (*rcp && is_cfs(*rcp)) - rcp++; - } - cp = rcp; - while (*rcp && !is_cfs(*rcp)) - rcp++; - i = *rcp; - *rcp = '\0'; - x_ins(cp); - *rcp = i; - } - return KSTD; -} - -/* Uppercase N(1) words */ -static int -x_fold_upper(c) - int c; -{ - return x_fold_case('U'); -} - -/* Lowercase N(1) words */ -static int -x_fold_lower(c) - int c; -{ - return x_fold_case('L'); -} - -/* Lowercase N(1) words */ -static int -x_fold_capitalize(c) - int c; -{ - return x_fold_case('C'); -} - -/* NAME: - * x_fold_case - convert word to UPPER/lower/Capital case - * - * DESCRIPTION: - * This function is used to implement M-U,M-u,M-L,M-l,M-C and M-c - * to UPPER case, lower case or Capitalize words. - * - * RETURN VALUE: - * None - */ - -static int -x_fold_case(c) - int c; -{ - char *cp = xcp; - - if (cp == xep) { - x_e_putc(BEL); - return KSTD; - } - while (x_arg--) { - /* - * first skip over any white-space - */ - while (cp != xep && is_mfs(*cp)) - cp++; - /* - * do the first char on its own since it may be - * a different action than for the rest. - */ - if (cp != xep) { - if (c == 'L') { /* lowercase */ - if (isupper((unsigned char)*cp)) - *cp = tolower((unsigned char)*cp); - } else { /* uppercase, capitialize */ - if (islower((unsigned char)*cp)) - *cp = toupper((unsigned char)*cp); - } - cp++; - } - /* - * now for the rest of the word - */ - while (cp != xep && !is_mfs((unsigned char)*cp)) { - if (c == 'U') { /* uppercase */ - if (islower((unsigned char)*cp)) - *cp = toupper((unsigned char)*cp); - } else { /* lowercase, capitialize */ - if (isupper((unsigned char)*cp)) - *cp = tolower((unsigned char)*cp); - } - cp++; - } - } - x_goto(cp); - return KSTD; -} - -/* NAME: - * x_lastcp - last visible char - * - * SYNOPSIS: - * x_lastcp() - * - * DESCRIPTION: - * This function returns a pointer to that char in the - * edit buffer that will be the last displayed on the - * screen. The sequence: - * - * for (cp = x_lastcp(); cp > xcp; cp) - * x_bs(*--cp); - * - * Will position the cursor correctly on the screen. - * - * RETURN VALUE: - * cp or NULL - */ - -static char * -x_lastcp() -{ - register char *rcp; - register int i; - - if (!xlp_valid) - { - for (i = 0, rcp = xbp; rcp < xep && i < x_displen; rcp++) - i += x_size(*rcp); - xlp = rcp; - } - xlp_valid = TRUE; - return (xlp); -} - -#endif /* EDIT */ diff --git a/bin/ksh/eval.c b/bin/ksh/eval.c deleted file mode 100644 index 4c016ecdf..000000000 --- a/bin/ksh/eval.c +++ /dev/null @@ -1,1403 +0,0 @@ -/* $NetBSD: eval.c,v 1.15 2013/10/18 19:53:34 christos Exp $ */ - -/* - * Expansion - quoting, separation, substitution, globbing - */ -#include - -#ifndef lint -__RCSID("$NetBSD: eval.c,v 1.15 2013/10/18 19:53:34 christos Exp $"); -#endif - -#include -#include - -#include "sh.h" -#include "ksh_dir.h" -#include "ksh_stat.h" - -/* - * string expansion - * - * first pass: quoting, IFS separation, ~, ${}, $() and $(()) substitution. - * second pass: alternation ({,}), filename expansion (*?[]). - */ - -/* expansion generator state */ -typedef struct Expand { - /* int type; */ /* see expand() */ - const char *str; /* string */ - union { - const char **strv;/* string[] */ - struct shf *shf;/* file */ - } u; /* source */ - struct tbl *var; /* variable in ${var..} */ - short split; /* split "$@" / call waitlast $() */ -} Expand; - -#define XBASE 0 /* scanning original */ -#define XSUB 1 /* expanding ${} string */ -#define XARGSEP 2 /* ifs0 between "$*" */ -#define XARG 3 /* expanding $*, $@ */ -#define XCOM 4 /* expanding $() */ -#define XNULLSUB 5 /* "$@" when $# is 0 (don't generate word) */ - -/* States used for field splitting */ -#define IFS_WORD 0 /* word has chars (or quotes) */ -#define IFS_WS 1 /* have seen IFS white-space */ -#define IFS_NWS 2 /* have seen IFS non-white-space */ - -static int varsub ARGS((Expand *xp, char *sp, char *word, int *stypep, int *slenp)); -static int comsub ARGS((Expand *xp, char *cp)); -static char *trimsub ARGS((char *str, char *pat, int how)); -static void glob ARGS((char *cp, XPtrV *wp, int markdirs)); -static void globit ARGS((XString *xs, char **xpp, char *sp, XPtrV *wp, - int check)); -static char *maybe_expand_tilde ARGS((char *p, XString *dsp, char **dpp, - int isassign)); -static char *tilde ARGS((char *acp)); -static char *homedir ARGS((char *name)); -#ifdef BRACE_EXPAND -static void alt_expand ARGS((XPtrV *wp, char *start, char *exp_start, - char *end, int fdo)); -#endif - -/* compile and expand word */ -char * -substitute(cp, f) - const char *cp; - int f; -{ - struct source *s, *sold; - - sold = source; - s = pushs(SWSTR, ATEMP); - s->start = s->str = cp; - source = s; - if (yylex(ONEWORD) != LWORD) - internal_errorf(1, "substitute"); - source = sold; - afree(s, ATEMP); - return evalstr(yylval.cp, f); -} - -/* - * expand arg-list - */ -char ** -eval(ap, f) - register char **ap; - int f; -{ - XPtrV w; - - if (*ap == NULL) - return ap; - XPinit(w, 32); - XPput(w, NULL); /* space for shell name */ -#ifdef SHARPBANG - XPput(w, NULL); /* and space for one arg */ -#endif - while (*ap != NULL) - expand(*ap++, &w, f); - XPput(w, NULL); -#ifdef SHARPBANG - return (char **) XPclose(w) + 2; -#else - return (char **) XPclose(w) + 1; -#endif -} - -/* - * expand string - */ -char * -evalstr(cp, f) - char *cp; - int f; -{ - XPtrV w; - - XPinit(w, 1); - expand(cp, &w, f); - cp = (XPsize(w) == 0) ? null : (char*) *XPptrv(w); - XPfree(w); - return cp; -} - -/* - * expand string - return only one component - * used from iosetup to expand redirection files - */ -char * -evalonestr(cp, f) - register char *cp; - int f; -{ - XPtrV w; - - XPinit(w, 1); - expand(cp, &w, f); - switch (XPsize(w)) { - case 0: - cp = null; - break; - case 1: - cp = (char*) *XPptrv(w); - break; - default: - cp = evalstr(cp, f&~DOGLOB); - break; - } - XPfree(w); - return cp; -} - -/* for nested substitution: ${var:=$var2} */ -typedef struct SubType { - short stype; /* [=+-?%#] action after expanded word */ - short base; /* begin position of expanded word */ - short f; /* saved value of f (DOPAT, etc) */ - struct tbl *var; /* variable for ${var..} */ - short quote; /* saved value of quote (for ${..[%#]..}) */ - struct SubType *prev; /* old type */ - struct SubType *next; /* poped type (to avoid re-allocating) */ -} SubType; - -void -expand(cp, wp, f) - char *cp; /* input word */ - register XPtrV *wp; /* output words */ - int f; /* DO* flags */ -{ - register int UNINITIALIZED(c); - register int type; /* expansion type */ - register int quote = 0; /* quoted */ - XString ds; /* destination string */ - register char *dp, *sp; /* dest., source */ - int fdo, word; /* second pass flags; have word */ - int doblank; /* field splitting of parameter/command subst */ - Expand x; /* expansion variables */ - SubType st_head, *st; - int UNINITIALIZED(newlines); /* For trailing newlines in COMSUB */ - int saw_eq, tilde_ok; - int make_magic; - size_t len; - - x.split = 0; /* XXX gcc */ - x.str = NULL; /* XXX gcc */ - x.u.strv = NULL;/* XXX gcc */ - if (cp == NULL) - internal_errorf(1, "expand(NULL)"); - /* for alias, readonly, set, typeset commands */ - if ((f & DOVACHECK) && is_wdvarassign(cp)) { - f &= ~(DOVACHECK|DOBLANK|DOGLOB|DOTILDE); - f |= DOASNTILDE; - } - if (Flag(FNOGLOB)) - f &= ~DOGLOB; - if (Flag(FMARKDIRS)) - f |= DOMARKDIRS; -#ifdef BRACE_EXPAND - if (Flag(FBRACEEXPAND) && (f & DOGLOB)) - f |= DOBRACE_; -#endif /* BRACE_EXPAND */ - - Xinit(ds, dp, 128, ATEMP); /* init dest. string */ - type = XBASE; - sp = cp; - fdo = 0; - saw_eq = 0; - tilde_ok = (f & (DOTILDE|DOASNTILDE)) ? 1 : 0; /* must be 1/0 */ - doblank = 0; - make_magic = 0; - word = (f&DOBLANK) ? IFS_WS : IFS_WORD; - st_head.next = (SubType *) 0; - st = &st_head; - - while (1) { - Xcheck(ds, dp); - - switch (type) { - case XBASE: /* original prefixed string */ - c = *sp++; - switch (c) { - case EOS: - c = 0; - break; - case CHAR: - c = *sp++; - break; - case QCHAR: - quote |= 2; /* temporary quote */ - c = *sp++; - break; - case OQUOTE: - word = IFS_WORD; - tilde_ok = 0; - quote = 1; - continue; - case CQUOTE: - quote = 0; - continue; - case COMSUB: - tilde_ok = 0; - if (f & DONTRUNCOMMAND) { - word = IFS_WORD; - *dp++ = '$'; *dp++ = '('; - while (*sp != '\0') { - Xcheck(ds, dp); - *dp++ = *sp++; - } - *dp++ = ')'; - } else { - type = comsub(&x, sp); - if (type == XCOM && (f&DOBLANK)) - doblank++; - sp = strchr(sp, 0) + 1; - newlines = 0; - } - continue; - case EXPRSUB: - word = IFS_WORD; - tilde_ok = 0; - if (f & DONTRUNCOMMAND) { - *dp++ = '$'; *dp++ = '('; *dp++ = '('; - while (*sp != '\0') { - Xcheck(ds, dp); - *dp++ = *sp++; - } - *dp++ = ')'; *dp++ = ')'; - } else { - struct tbl v; - char *p; - - v.flag = DEFINED|ISSET|INTEGER; - v.type = 10; /* not default */ - v.name[0] = '\0'; - v_evaluate(&v, substitute(sp, 0), - KSH_UNWIND_ERROR); - sp = strchr(sp, 0) + 1; - for (p = str_val(&v); *p; ) { - Xcheck(ds, dp); - *dp++ = *p++; - } - } - continue; - case OSUBST: /* ${{#}var{:}[=+-?#%]word} */ - /* format is: - * OSUBST [{x] plain-variable-part \0 - * compiled-word-part CSUBST [}x] - * This is were all syntax checking gets done... - */ - { - char *varname = ++sp; /* skip the { or x (}) */ - int stype; - int slen; - - slen = -1; /* XXX gcc */ - sp = strchr(sp, '\0') + 1; /* skip variable */ - type = varsub(&x, varname, sp, &stype, &slen); - if (type < 0) { - char endc; - char *str, *end; - - end = (char *) wdscan(sp, CSUBST); - /* ({) the } or x is already skipped */ - endc = *end; - *end = EOS; - str = snptreef((char *) 0, 64, "%S", - varname - 1); - *end = endc; - errorf("%s: bad substitution", str); - } - if (f&DOBLANK) - doblank++; - tilde_ok = 0; - if (type == XBASE) { /* expand? */ - if (!st->next) { - SubType *newst; - - newst = (SubType *) alloc( - sizeof(SubType), ATEMP); - newst->next = (SubType *) 0; - newst->prev = st; - st->next = newst; - } - st = st->next; - st->stype = stype; - st->base = Xsavepos(ds, dp); - st->f = f; - st->var = x.var; - st->quote = quote; - /* skip qualifier(s) */ - if (stype) - sp += slen; - switch (stype & 0x7f) { - case '#': - case '%': - /* ! DOBLANK,DOBRACE_,DOTILDE */ - f = DOPAT | (f&DONTRUNCOMMAND) - | DOTEMP_; - quote = 0; - /* Prepend open pattern (so | - * in a trim will work as - * expected) - */ - *dp++ = MAGIC; - *dp++ = '@' + 0x80; - break; - case '=': - /* Enabling tilde expansion - * after :'s here is - * non-standard ksh, but is - * consistent with rules for - * other assignments. Not - * sure what POSIX thinks of - * this. - * Not doing tilde expansion - * for integer variables is a - * non-POSIX thing - makes - * sense though, since ~ is - * a arithmetic operator. - */ - if (!(x.var->flag & INTEGER)) - f |= DOASNTILDE|DOTILDE; - f |= DOTEMP_; - /* These will be done after the - * value has been assigned. - */ - f &= ~(DOBLANK|DOGLOB|DOBRACE_); - tilde_ok = 1; - break; - case '?': - f &= ~DOBLANK; - f |= DOTEMP_; - /* fall through */ - default: - /* Enable tilde expansion */ - tilde_ok = 1; - f |= DOTILDE; - } - } else - /* skip word */ - sp = (char *) wdscan(sp, CSUBST); - continue; - } - case CSUBST: /* only get here if expanding word */ - sp++; /* ({) skip the } or x */ - tilde_ok = 0; /* in case of ${unset:-} */ - *dp = '\0'; - quote = st->quote; - f = st->f; - if (f&DOBLANK) - doblank--; - switch (st->stype&0x7f) { - case '#': - case '%': - /* Append end-pattern */ - *dp++ = MAGIC; *dp++ = ')'; *dp = '\0'; - dp = Xrestpos(ds, dp, st->base); - /* Must use st->var since calling - * global would break things - * like x[i+=1]. - */ - x.str = trimsub(str_val(st->var), - dp, st->stype); - type = XSUB; - if (f&DOBLANK) - doblank++; - st = st->prev; - continue; - case '=': - /* Restore our position and substitute - * the value of st->var (may not be - * the assigned value in the presence - * of integer/right-adj/etc attributes). - */ - dp = Xrestpos(ds, dp, st->base); - /* Must use st->var since calling - * global would cause with things - * like x[i+=1] to be evaluated twice. - */ - /* Note: not exported by FEXPORT - * in at&t ksh. - */ - /* XXX POSIX says readonly is only - * fatal for special builtins (setstr - * does readonly check). - */ - len = strlen(dp) + 1; - setstr(st->var, - debunk((char *) alloc(len, ATEMP), - dp, len), - KSH_UNWIND_ERROR); - x.str = str_val(st->var); - type = XSUB; - if (f&DOBLANK) - doblank++; - st = st->prev; - continue; - case '?': - { - char *s = Xrestpos(ds, dp, st->base); - - errorf("%s: %s", st->var->name, - dp == s ? - "parameter null or not set" - : (debunk(s, s, strlen(s) + 1), s)); - } - } - st = st->prev; - type = XBASE; - continue; - - case OPAT: /* open pattern: *(foo|bar) */ - /* Next char is the type of pattern */ - make_magic = 1; - c = *sp++ + 0x80; - break; - - case SPAT: /* pattern separator (|) */ - make_magic = 1; - c = '|'; - break; - - case CPAT: /* close pattern */ - make_magic = 1; - c = /*(*/ ')'; - break; - } - break; - - case XNULLSUB: - /* Special case for "$@" (and "${foo[@]}") - no - * word is generated if $# is 0 (unless there is - * other stuff inside the quotes). - */ - type = XBASE; - if (f&DOBLANK) { - doblank--; - /* not really correct: x=; "$x$@" should - * generate a null argument and - * set A; "${@:+}" shouldn't. - */ - if (dp == Xstring(ds, dp)) - word = IFS_WS; - } - continue; - - case XSUB: - if ((c = *x.str++) == 0) { - type = XBASE; - if (f&DOBLANK) - doblank--; - continue; - } - break; - - case XARGSEP: - type = XARG; - quote = 1; - case XARG: - if ((c = *x.str++) == '\0') { - /* force null words to be created so - * set -- '' 2 ''; foo "$@" will do - * the right thing - */ - if (quote && x.split) - word = IFS_WORD; - if ((x.str = *x.u.strv++) == NULL) { - type = XBASE; - if (f&DOBLANK) - doblank--; - continue; - } - c = ifs0; - if (c == 0) { - if (quote && !x.split) - continue; - c = ' '; - } - if (quote && x.split) { - /* terminate word for "$@" */ - type = XARGSEP; - quote = 0; - } - } - break; - - case XCOM: - if (newlines) { /* Spit out saved nl's */ - c = '\n'; - --newlines; - } else { - while ((c = shf_getc(x.u.shf)) == 0 || c == '\n') - if (c == '\n') - newlines++; /* Save newlines */ - if (newlines && c != EOF) { - shf_ungetc(c, x.u.shf); - c = '\n'; - --newlines; - } - } - if (c == EOF) { - newlines = 0; - shf_close(x.u.shf); - if (x.split) - subst_exstat = waitlast(); - type = XBASE; - if (f&DOBLANK) - doblank--; - continue; - } - break; - } - - /* check for end of word or IFS separation */ - if (c == 0 || (!quote && (f & DOBLANK) && doblank && !make_magic - && ctype(c, C_IFS))) - { - /* How words are broken up: - * | value of c - * word | ws nws 0 - * ----------------------------------- - * IFS_WORD w/WS w/NWS w - * IFS_WS -/WS w/NWS - - * IFS_NWS -/NWS w/NWS w - * (w means generate a word) - * Note that IFS_NWS/0 generates a word (at&t ksh - * doesn't do this, but POSIX does). - */ - if (word == IFS_WORD - || (!ctype(c, C_IFSWS) && (c || word == IFS_NWS))) - { - char *p; - - *dp++ = '\0'; - p = Xclose(ds, dp); -#ifdef BRACE_EXPAND - if (fdo & DOBRACE_) - /* also does globbing */ - alt_expand(wp, p, p, - p + Xlength(ds, (dp - 1)), - fdo | (f & DOMARKDIRS)); - else -#endif /* BRACE_EXPAND */ - if (fdo & DOGLOB) - glob(p, wp, f & DOMARKDIRS); - else if ((f & DOPAT) || !(fdo & DOMAGIC_)) - XPput(*wp, p); - else - XPput(*wp, debunk(p, p, strlen(p) + 1)); - fdo = 0; - saw_eq = 0; - tilde_ok = (f & (DOTILDE|DOASNTILDE)) ? 1 : 0; - if (c != 0) - Xinit(ds, dp, 128, ATEMP); - } - if (c == 0) - return; - if (word != IFS_NWS) - word = ctype(c, C_IFSWS) ? IFS_WS : IFS_NWS; - } else { - /* age tilde_ok info - ~ code tests second bit */ - tilde_ok <<= 1; - /* mark any special second pass chars */ - if (!quote) - switch (c) { - case '[': - case NOT: - case '-': - case ']': - /* For character classes - doesn't hurt - * to have magic !,-,]'s outside of - * [...] expressions. - */ - if (f & (DOPAT | DOGLOB)) { - fdo |= DOMAGIC_; - if (c == '[') - fdo |= f & DOGLOB; - *dp++ = MAGIC; - } - break; - case '*': - case '?': - if (f & (DOPAT | DOGLOB)) { - fdo |= DOMAGIC_ | (f & DOGLOB); - *dp++ = MAGIC; - } - break; -#ifdef BRACE_EXPAND - case OBRACE: - case ',': - case CBRACE: - if ((f & DOBRACE_) && (c == OBRACE - || (fdo & DOBRACE_))) - { - fdo |= DOBRACE_|DOMAGIC_; - *dp++ = MAGIC; - } - break; -#endif /* BRACE_EXPAND */ - case '=': - /* Note first unquoted = for ~ */ - if (!(f & DOTEMP_) && !saw_eq) { - saw_eq = 1; - tilde_ok = 1; - } - break; - case PATHSEP: /* : */ - /* Note unquoted : for ~ */ - if (!(f & DOTEMP_) && (f & DOASNTILDE)) - tilde_ok = 1; - break; - case '~': - /* tilde_ok is reset whenever - * any of ' " $( $(( ${ } are seen. - * Note that tilde_ok must be preserved - * through the sequence ${A=a=}~ - */ - if (type == XBASE - && (f & (DOTILDE|DOASNTILDE)) - && (tilde_ok & 2)) - { - char *p, *dp_x; - - dp_x = dp; - p = maybe_expand_tilde(sp, - &ds, &dp_x, - f & DOASNTILDE); - if (p) { - if (dp != dp_x) - word = IFS_WORD; - dp = dp_x; - sp = p; - continue; - } - } - break; - } - else - quote &= ~2; /* undo temporary */ - - if (make_magic) { - make_magic = 0; - fdo |= DOMAGIC_ | (f & DOGLOB); - *dp++ = MAGIC; - } else if (ISMAGIC(c)) { - fdo |= DOMAGIC_; - *dp++ = MAGIC; - } - *dp++ = c; /* save output char */ - word = IFS_WORD; - } - } -} - -/* - * Prepare to generate the string returned by ${} substitution. - */ -static int -varsub(xp, sp, word, stypep, slenp) - Expand *xp; - char *sp; - char *word; - int *stypep; /* becomes qualifier type */ - int *slenp; /* " " len (=, :=, etc.) valid iff *stypep != 0 */ -{ - int c; - int state; /* next state: XBASE, XARG, XSUB, XNULLSUB */ - int stype; /* substitution type */ - int slen; - char *p; - struct tbl *vp; - - if (sp[0] == '\0') /* Bad variable name */ - return -1; - - xp->var = NULL; - - /* ${#var}, string length or array size */ - if (sp[0] == '#' && (c = sp[1]) != '\0') { - int zero_ok = 0; - - /* Can't have any modifiers for ${#...} */ - if (*word != CSUBST) - return -1; - sp++; - /* Check for size of array */ - if ((p=strchr(sp,'[')) && (p[1]=='*'||p[1]=='@') && p[2]==']') { - int n = 0; - vp = global(arrayname(sp)); - if (vp->flag & (ISSET|ARRAY)) - zero_ok = 1; - for (; vp; vp = vp->u.array) - if (vp->flag & ISSET) { - n++; - } - c = n; /* ksh88/ksh93 go for number, not max index */ - } else if (c == '*' || c == '@') - c = e->loc->argc; - else { - p = str_val(global(sp)); - zero_ok = p != null; - c = strlen(p); - } - if (Flag(FNOUNSET) && c == 0 && !zero_ok) - errorf("%s: parameter not set", sp); - *stypep = 0; /* unqualified variable/string substitution */ - xp->str = str_save(ulton((unsigned long)c, 10), ATEMP); - return XSUB; - } - - /* Check for qualifiers in word part */ - stype = 0; - c = word[slen = 0] == CHAR ? word[1] : 0; - if (c == ':') { - slen += 2; - stype = 0x80; - c = word[slen + 0] == CHAR ? word[slen + 1] : 0; - } - if (ctype(c, C_SUBOP1)) { - slen += 2; - stype |= c; - } else if (ctype(c, C_SUBOP2)) { /* Note: ksh88 allows :%, :%%, etc */ - slen += 2; - stype = c; - if (word[slen + 0] == CHAR && c == word[slen + 1]) { - stype |= 0x80; - slen += 2; - } - } else if (stype) /* : is not ok */ - return -1; - if (!stype && *word != CSUBST) - return -1; - *stypep = stype; - *slenp = slen; - - c = sp[0]; - if (c == '*' || c == '@') { - switch (stype & 0x7f) { - case '=': /* can't assign to a vector */ - case '%': /* can't trim a vector (yet) */ - case '#': - return -1; - } - if (e->loc->argc == 0) { - xp->u.strv = NULL; - xp->str = null; - state = c == '@' ? XNULLSUB : XSUB; - } else { - char **t = &e->loc->argv[1]; - xp->u.strv = (void *)(uintptr_t)t; - xp->str = *xp->u.strv++; - xp->split = c == '@'; /* $@ */ - state = XARG; - } - } else { - if ((p=strchr(sp,'[')) && (p[1]=='*'||p[1]=='@') && p[2]==']') { - XPtrV wv; - - switch (stype & 0x7f) { - case '=': /* can't assign to a vector */ - case '%': /* can't trim a vector (yet) */ - case '#': - return -1; - } - XPinit(wv, 32); - vp = global(arrayname(sp)); - for (; vp; vp = vp->u.array) { - if (!(vp->flag&ISSET)) - continue; - XPput(wv, str_val(vp)); - } - if (XPsize(wv) == 0) { - xp->str = null; - state = p[1] == '@' ? XNULLSUB : XSUB; - XPfree(wv); - } else { - XPput(wv, 0); - xp->u.strv = (const char **) XPptrv(wv); - xp->str = *xp->u.strv++; - xp->split = p[1] == '@'; /* ${foo[@]} */ - state = XARG; - } - } else { - /* Can't assign things like $! or $1 */ - if ((stype & 0x7f) == '=' - && (ctype(*sp, C_VAR1) || digit(*sp))) - return -1; - xp->var = global(sp); - xp->str = str_val(xp->var); - state = XSUB; - } - } - - c = stype&0x7f; - /* test the compiler's code generator */ - if (ctype(c, C_SUBOP2) || - (((stype&0x80) ? *xp->str=='\0' : xp->str==null) ? /* undef? */ - c == '=' || c == '-' || c == '?' : c == '+')) - state = XBASE; /* expand word instead of variable value */ - if (Flag(FNOUNSET) && xp->str == null - && (ctype(c, C_SUBOP2) || (state != XBASE && c != '+'))) - errorf("%s: parameter not set", sp); - return state; -} - -/* - * Run the command in $(...) and read its output. - */ -static int -comsub(xp, cp) - register Expand *xp; - char *cp; -{ - Source *s, *sold; - register struct op *t; - struct shf *shf; - - s = pushs(SSTRING, ATEMP); - s->start = s->str = cp; - sold = source; - t = compile(s); - afree(s, ATEMP); - source = sold; - - if (t == NULL) - return XBASE; - - if (t != NULL && t->type == TCOM && /* $(args == NULL && *t->vars == NULL && t->ioact != NULL) { - register struct ioword *io = *t->ioact; - char *name; - - if ((io->flag&IOTYPE) != IOREAD) - errorf("funny $() command: %s", - snptreef((char *) 0, 32, "%R", io)); - shf = shf_open(name = evalstr(io->name, DOTILDE), O_RDONLY, 0, - SHF_MAPHI|SHF_CLEXEC); - if (shf == NULL) - errorf("%s: cannot open $() input", name); - xp->split = 0; /* no waitlast() */ - } else { - int ofd1, pv[2]; - openpipe(pv); - shf = shf_fdopen(pv[0], SHF_RD, (struct shf *) 0); - ofd1 = savefd(1, 0); /* fd 1 may be closed... */ - if (pv[1] != 1) { - ksh_dup2(pv[1], 1, FALSE); - close(pv[1]); - } - execute(t, XFORK|XXCOM|XPIPEO); - restfd(1, ofd1); - startlast(); - xp->split = 1; /* waitlast() */ - } - - xp->u.shf = shf; - return XCOM; -} - -/* - * perform #pattern and %pattern substitution in ${} - */ - -static char * -trimsub(str, pat, how) - register char *str; - char *pat; - int how; -{ - register char *end = strchr(str, 0); - register char *p, c; - - switch (how&0xff) { /* UCHAR_MAX maybe? */ - case '#': /* shortest at beginning */ - for (p = str; p <= end; p++) { - c = *p; *p = '\0'; - if (gmatch(str, pat, FALSE)) { - *p = c; - return p; - } - *p = c; - } - break; - case '#'|0x80: /* longest match at beginning */ - for (p = end; p >= str; p--) { - c = *p; *p = '\0'; - if (gmatch(str, pat, FALSE)) { - *p = c; - return p; - } - *p = c; - } - break; - case '%': /* shortest match at end */ - for (p = end; p >= str; p--) { - if (gmatch(p, pat, FALSE)) - return str_nsave(str, p - str, ATEMP); - } - break; - case '%'|0x80: /* longest match at end */ - for (p = str; p <= end; p++) { - if (gmatch(p, pat, FALSE)) - return str_nsave(str, p - str, ATEMP); - } - break; - } - - return str; /* no match, return string */ -} - -/* - * glob - * Name derived from V6's /etc/glob, the program that expanded filenames. - */ - -/* XXX cp not const 'cause slashes are temporarily replaced with nulls... */ -static void -glob(cp, wp, markdirs) - char *cp; - register XPtrV *wp; - int markdirs; -{ - int oldsize = XPsize(*wp); - - if (glob_str(cp, wp, markdirs) == 0) - XPput(*wp, debunk(cp, cp, strlen(cp) + 1)); - else - qsortp(XPptrv(*wp) + oldsize, (size_t)(XPsize(*wp) - oldsize), - xstrcmp); -} - -#define GF_NONE 0 -#define GF_EXCHECK BIT(0) /* do existence check on file */ -#define GF_GLOBBED BIT(1) /* some globbing has been done */ -#define GF_MARKDIR BIT(2) /* add trailing / to directories */ - -/* Apply file globbing to cp and store the matching files in wp. Returns - * the number of matches found. - */ -int -glob_str(cp, wp, markdirs) - char *cp; - XPtrV *wp; - int markdirs; -{ - int oldsize = XPsize(*wp); - XString xs; - char *xp; - - Xinit(xs, xp, 256, ATEMP); - globit(&xs, &xp, cp, wp, markdirs ? GF_MARKDIR : GF_NONE); - Xfree(xs, xp); - - return XPsize(*wp) - oldsize; -} - -static void -globit(xs, xpp, sp, wp, check) - XString *xs; /* dest string */ - char **xpp; /* ptr to dest end */ - char *sp; /* source path */ - register XPtrV *wp; /* output list */ - int check; /* GF_* flags */ -{ - register char *np; /* next source component */ - char *xp = *xpp; - char *se; - char odirsep; - - /* This to allow long expansions to be interrupted */ - intrcheck(); - - if (sp == NULL) { /* end of source path */ - /* We only need to check if the file exists if a pattern - * is followed by a non-pattern (eg, foo*x/bar; no check - * is needed for foo* since the match must exist) or if - * any patterns were expanded and the markdirs option is set. - * Symlinks make things a bit tricky... - */ - if ((check & GF_EXCHECK) - || ((check & GF_MARKDIR) && (check & GF_GLOBBED))) - { -#define stat_check() (stat_done ? stat_done : \ - (stat_done = stat(Xstring(*xs, xp), &statb) < 0 \ - ? -1 : 1)) - struct stat lstatb, statb; - int stat_done = 0; /* -1: failed, 1 ok */ - - if (lstat(Xstring(*xs, xp), &lstatb) < 0) - return; - /* special case for systems which strip trailing - * slashes from regular files (eg, /etc/passwd/). - * SunOS 4.1.3 does this... - */ - if ((check & GF_EXCHECK) && xp > Xstring(*xs, xp) - && ISDIRSEP(xp[-1]) && !S_ISDIR(lstatb.st_mode) -#ifdef S_ISLNK - && (!S_ISLNK(lstatb.st_mode) - || stat_check() < 0 - || !S_ISDIR(statb.st_mode)) -#endif /* S_ISLNK */ - ) - return; - /* Possibly tack on a trailing / if there isn't already - * one and if the file is a directory or a symlink to a - * directory - */ - if (((check & GF_MARKDIR) && (check & GF_GLOBBED)) - && xp > Xstring(*xs, xp) && !ISDIRSEP(xp[-1]) - && (S_ISDIR(lstatb.st_mode) -#ifdef S_ISLNK - || (S_ISLNK(lstatb.st_mode) - && stat_check() > 0 - && S_ISDIR(statb.st_mode)) -#endif /* S_ISLNK */ - )) - { - *xp++ = DIRSEP; - *xp = '\0'; - } - } -#ifdef OS2 /* Done this way to avoid bug in gcc 2.7.2... */ - /* Ugly kludge required for command - * completion - see how search_access() - * is implemented for OS/2... - */ -# define KLUDGE_VAL 4 -#else /* OS2 */ -# define KLUDGE_VAL 0 -#endif /* OS2 */ - XPput(*wp, str_nsave(Xstring(*xs, xp), Xlength(*xs, xp) - + KLUDGE_VAL, ATEMP)); - return; - } - - if (xp > Xstring(*xs, xp)) - *xp++ = DIRSEP; - while (ISDIRSEP(*sp)) { - Xcheck(*xs, xp); - *xp++ = *sp++; - } - np = ksh_strchr_dirsep(sp); - if (np != NULL) { - se = np; - odirsep = *np; /* don't assume DIRSEP, can be multiple kinds */ - *np++ = '\0'; - } else { - odirsep = '\0'; /* keep gcc quiet */ - se = sp + strlen(sp); - } - - - /* Check if sp needs globbing - done to avoid pattern checks for strings - * containing MAGIC characters, open ['s without the matching close ], - * etc. (otherwise opendir() will be called which may fail because the - * directory isn't readable - if no globbing is needed, only execute - * permission should be required (as per POSIX)). - */ - if (!has_globbing(sp, se)) { - XcheckN(*xs, xp, se - sp + 1); - debunk(xp, sp, Xnleft(*xs, xp)); - xp += strlen(xp); - *xpp = xp; - globit(xs, xpp, np, wp, check); - } else { - DIR *dirp; - struct dirent *d; - char *name; - int len; - int prefix_len; - - /* xp = *xpp; copy_non_glob() may have re-alloc'd xs */ - *xp = '\0'; - prefix_len = Xlength(*xs, xp); - dirp = ksh_opendir(prefix_len ? Xstring(*xs, xp) : "."); - if (dirp == NULL) - goto Nodir; - while ((d = readdir(dirp)) != NULL) { - name = d->d_name; - if ((*name == '.' && *sp != '.') - || !gmatch(name, sp, TRUE)) - continue; - - len = NLENGTH(d) + 1; - XcheckN(*xs, xp, len); - memcpy(xp, name, len); - *xpp = xp + len - 1; - globit(xs, xpp, np, wp, - (check & GF_MARKDIR) | GF_GLOBBED - | (np ? GF_EXCHECK : GF_NONE)); - xp = Xstring(*xs, xp) + prefix_len; - } - closedir(dirp); - Nodir:; - } - - if (np != NULL) - *--np = odirsep; -} - -#if 0 -/* Check if p contains something that needs globbing; if it does, 0 is - * returned; if not, p is copied into xs/xp after stripping any MAGICs - */ -static int copy_non_glob ARGS((XString *xs, char **xpp, char *p)); -static int -copy_non_glob(xs, xpp, p) - XString *xs; - char **xpp; - char *p; -{ - char *xp; - int len = strlen(p); - - XcheckN(*xs, *xpp, len); - xp = *xpp; - for (; *p; p++) { - if (ISMAGIC(*p)) { - int c = *++p; - - if (c == '*' || c == '?') - return 0; - if (*p == '[') { - char *q = p + 1; - - if (ISMAGIC(*q) && q[1] == NOT) - q += 2; - if (ISMAGIC(*q) && q[1] == ']') - q += 2; - for (; *q; q++) - if (ISMAGIC(*q) && *++q == ']') - return 0; - /* pass a literal [ through */ - } - /* must be a MAGIC-MAGIC, or MAGIC-!, MAGIC--, etc. */ - } - *xp++ = *p; - } - *xp = '\0'; - *xpp = xp; - return 1; -} -#endif /* 0 */ - -/* remove MAGIC from string */ -char * -debunk(dp, sp, dlen) - char *dp; - const char *sp; - size_t dlen; -{ - char *d, *s; - - if ((s = strchr(sp, MAGIC))) { - if (s - sp >= (ptrdiff_t)dlen) - return dp; - memcpy(dp, sp, s - sp); - for (d = dp + (s - sp); *s && (d - dp < (ptrdiff_t)dlen); s++) - if (!ISMAGIC(*s) || !(*++s & 0x80) - || !strchr("*+?@! ", *s & 0x7f)) - *d++ = *s; - else { - /* extended pattern operators: *+?@! */ - if ((*s & 0x7f) != ' ') - *d++ = *s & 0x7f; - if (d - dp < (ptrdiff_t)dlen) - *d++ = '('; - } - *d = '\0'; - } else if (dp != sp) - strlcpy(dp, sp, dlen); - return dp; -} - -/* Check if p is an unquoted name, possibly followed by a / or :. If so - * puts the expanded version in *dcp,dp and returns a pointer in p just - * past the name, otherwise returns 0. - */ -static char * -maybe_expand_tilde(p, dsp, dpp, isassign) - char *p; - XString *dsp; - char **dpp; - int isassign; -{ - XString ts; - char *dp = *dpp; - char *tp, *r; - - Xinit(ts, tp, 16, ATEMP); - /* : only for DOASNTILDE form */ - while (p[0] == CHAR && !ISDIRSEP(p[1]) - && (!isassign || p[1] != PATHSEP)) - { - Xcheck(ts, tp); - *tp++ = p[1]; - p += 2; - } - *tp = '\0'; - r = (p[0] == EOS || p[0] == CHAR || p[0] == CSUBST) ? tilde(Xstring(ts, tp)) : (char *) 0; - Xfree(ts, tp); - if (r) { - while (*r) { - Xcheck(*dsp, dp); - if (ISMAGIC(*r)) - *dp++ = MAGIC; - *dp++ = *r++; - } - *dpp = dp; - r = p; - } - return r; -} - -/* - * tilde expansion - * - * based on a version by Arnold Robbins - */ - -static char * -tilde(cp) - char *cp; -{ - char *dp; - - if (cp[0] == '\0') - dp = str_val(global("HOME")); - else if (cp[0] == '+' && cp[1] == '\0') - dp = str_val(global("PWD")); - else if (cp[0] == '-' && cp[1] == '\0') - dp = str_val(global("OLDPWD")); - else - dp = homedir(cp); - /* If HOME, PWD or OLDPWD are not set, don't expand ~ */ - if (dp == null) - dp = (char *) 0; - return dp; -} - -/* - * map userid to user's home directory. - * note that 4.3's getpw adds more than 6K to the shell, - * and the YP version probably adds much more. - * we might consider our own version of getpwnam() to keep the size down. - */ - -static char * -homedir(name) - char *name; -{ - register struct tbl *ap; - - ap = tenter(&homedirs, name, hash(name)); - if (!(ap->flag & ISSET)) { -#ifdef OS2 - /* No usernames in OS2 - punt */ - return NULL; -#else /* OS2 */ - struct passwd *pw; - size_t n; - - pw = getpwnam(name); - if (pw == NULL) - return NULL; - n = strlen(pw->pw_dir); - if (n > 0 && '/' != pw->pw_dir[n - 1]) { - ap->val.s = str_nsave(pw->pw_dir, n + 1, APERM); - ap->val.s[n] = '/'; - ap->val.s[n + 1] = '\0'; - } else { - ap->val.s = str_save(pw->pw_dir, APERM); - } - ap->flag |= DEFINED|ISSET|ALLOC; -#endif /* OS2 */ - } - return ap->val.s; -} - -#ifdef BRACE_EXPAND -static void -alt_expand(wp, start, exp_start, end, fdo) - XPtrV *wp; - char *start, *exp_start; - char *end; - int fdo; -{ - int UNINITIALIZED(count); - char *brace_start, *brace_end, *UNINITIALIZED(comma); - char *field_start; - char *p; - - /* search for open brace */ - for (p = exp_start; (p = strchr(p, MAGIC)) && p[1] != OBRACE; p += 2) - ; - brace_start = p; - - /* find matching close brace, if any */ - if (p) { - comma = (char *) 0; - count = 1; - for (p += 2; *p && count; p++) { - if (ISMAGIC(*p)) { - if (*++p == OBRACE) - count++; - else if (*p == CBRACE) - --count; - else if (*p == ',' && count == 1) - comma = p; - } - } - } - /* no valid expansions... */ - if (!p || count != 0) { - /* Note that given a{{b,c} we do not expand anything (this is - * what at&t ksh does. This may be changed to do the {b,c} - * expansion. } - */ - if (fdo & DOGLOB) - glob(start, wp, fdo & DOMARKDIRS); - else - XPput(*wp, debunk(start, start, end - start)); - return; - } - brace_end = p; - if (!comma) { - alt_expand(wp, start, brace_end, end, fdo); - return; - } - - /* expand expression */ - field_start = brace_start + 2; - count = 1; - for (p = brace_start + 2; p != brace_end; p++) { - if (ISMAGIC(*p)) { - if (*++p == OBRACE) - count++; - else if ((*p == CBRACE && --count == 0) - || (*p == ',' && count == 1)) - { - char *new; - int l1, l2, l3; - - l1 = brace_start - start; - l2 = (p - 1) - field_start; - l3 = end - brace_end; - new = (char *) alloc(l1 + l2 + l3 + 1, ATEMP); - memcpy(new, start, l1); - memcpy(new + l1, field_start, l2); - memcpy(new + l1 + l2, brace_end, l3); - new[l1 + l2 + l3] = '\0'; - alt_expand(wp, new, new + l1, - new + l1 + l2 + l3, fdo); - field_start = p + 1; - } - } - } - return; -} -#endif /* BRACE_EXPAND */ diff --git a/bin/ksh/exec.c b/bin/ksh/exec.c deleted file mode 100644 index 93c1aa257..000000000 --- a/bin/ksh/exec.c +++ /dev/null @@ -1,1749 +0,0 @@ -/* $NetBSD: exec.c,v 1.15 2012/03/25 17:23:48 christos Exp $ */ - -/* - * execute command tree - */ -#include - -#ifndef lint -__RCSID("$NetBSD: exec.c,v 1.15 2012/03/25 17:23:48 christos Exp $"); -#endif - - -#include "sh.h" -#include "c_test.h" -#include -#include "ksh_stat.h" - -/* Does ps4 get parameter substitutions done? */ -#ifdef KSH -# define PS4_SUBSTITUTE(s) substitute((s), 0) -#else -# define PS4_SUBSTITUTE(s) (s) -#endif /* KSH */ - -static int comexec ARGS((struct op *, struct tbl *volatile, char **, - int volatile)); -static void scriptexec ARGS((struct op *, char **)); -static int call_builtin ARGS((struct tbl *, char **)); -static int iosetup ARGS((struct ioword *, struct tbl *)); -static int herein ARGS((const char *, int)); -#ifdef KSH -static char *do_selectargs ARGS((char **, bool_t)); -#endif /* KSH */ -#ifdef KSH -static int dbteste_isa ARGS((Test_env *, Test_meta)); -static const char *dbteste_getopnd ARGS((Test_env *, Test_op, int)); -static int dbteste_eval ARGS((Test_env *, Test_op, const char *, - const char *, int)); -static void dbteste_error ARGS((Test_env *, int, const char *)); -#endif /* KSH */ -#ifdef OS2 -static int search_access1 ARGS((const char *, int, int *)); -#endif /* OS2 */ - - -/* - * handle systems that don't have F_SETFD - */ -#ifndef F_SETFD -# ifndef MAXFD -# define MAXFD 64 -# endif -/* a bit field would be smaller, but this will work */ -static char clexec_tab[MAXFD+1]; -#endif - -/* - * we now use this function always. - */ -int -fd_clexec(fd) - int fd; -{ -#ifndef F_SETFD - if (fd >= 0 && fd < sizeof(clexec_tab)) { - clexec_tab[fd] = 1; - return 0; - } - return -1; -#else - return fcntl(fd, F_SETFD, 1); -#endif -} - - -/* - * execute command tree - */ -int -execute(t, flags) - struct op * volatile t; - volatile int flags; /* if XEXEC don't fork */ -{ - int i; - volatile int rv = 0; - int pv[2]; - char ** volatile ap; - char *s, *cp; - struct ioword **iowp; - struct tbl *tp = NULL; - - if (t == NULL) - return 0; - - /* Is this the end of a pipeline? If so, we want to evaluate the - * command arguments - bool_t eval_done = FALSE; - if ((flags&XFORK) && !(flags&XEXEC) && (flags&XPCLOSE)) { - eval_done = TRUE; - tp = eval_execute_args(t, &ap); - } - */ - if ((flags&XFORK) && !(flags&XEXEC) && t->type != TPIPE) - return exchild(t, flags & ~XTIME, -1); /* run in sub-process */ - - newenv(E_EXEC); - if (trap) - runtraps(0); - - if (t->type == TCOM) { - /* Clear subst_exstat before argument expansion. Used by - * null commands (see comexec() and c_eval()) and by c_set(). - */ - subst_exstat = 0; - - current_lineno = t->lineno; /* for $LINENO */ - - /* POSIX says expand command words first, then redirections, - * and assignments last.. - */ - ap = eval(t->args, t->u.evalflags | DOBLANK | DOGLOB | DOTILDE); - if (flags & XTIME) - /* Allow option parsing (bizarre, but POSIX) */ - timex_hook(t, &ap); - if (Flag(FXTRACE) && ap[0]) { - shf_fprintf(shl_out, "%s", - PS4_SUBSTITUTE(str_val(global("PS4")))); - for (i = 0; ap[i]; i++) - shf_fprintf(shl_out, "%s%s", ap[i], - ap[i + 1] ? space : newline); - shf_flush(shl_out); - } - if (ap[0]) - tp = findcom(ap[0], FC_BI|FC_FUNC); - } - flags &= ~XTIME; - - if (t->ioact != NULL || t->type == TPIPE || t->type == TCOPROC) { - e->savefd = (short *) alloc(sizeofN(short, NUFILE), ATEMP); - /* initialize to not redirected */ - memset(e->savefd, 0, sizeofN(short, NUFILE)); - } - - /* do redirection, to be restored in quitenv() */ - if (t->ioact != NULL) - for (iowp = t->ioact; *iowp != NULL; iowp++) { - if (iosetup(*iowp, tp) < 0) { - exstat = rv = 1; - /* Redirection failures for special commands - * cause (non-interactive) shell to exit. - */ - if (tp && tp->type == CSHELL - && (tp->flag & SPEC_BI)) - errorf("%s", null); - /* Deal with FERREXIT, quitenv(), etc. */ - goto Break; - } - } - - switch(t->type) { - case TCOM: - rv = comexec(t, tp, ap, flags); - break; - - case TPAREN: - rv = execute(t->left, flags|XFORK); - break; - - case TPIPE: - flags |= XFORK; - flags &= ~XEXEC; - e->savefd[0] = savefd(0, 0); - (void) ksh_dup2(e->savefd[0], 0, FALSE); /* stdin of first */ - e->savefd[1] = savefd(1, 0); - while (t->type == TPIPE) { - openpipe(pv); - (void) ksh_dup2(pv[1], 1, FALSE); /* stdout of curr */ - /* Let exchild() close pv[0] in child - * (if this isn't done, commands like - * (: ; cat /etc/termcap) | sleep 1 - * will hang forever). - */ - exchild(t->left, flags|XPIPEO|XCCLOSE, pv[0]); - (void) ksh_dup2(pv[0], 0, FALSE); /* stdin of next */ - closepipe(pv); - flags |= XPIPEI; - t = t->right; - } - restfd(1, e->savefd[1]); /* stdout of last */ - e->savefd[1] = 0; /* no need to re-restore this */ - /* Let exchild() close 0 in parent, after fork, before wait */ - i = exchild(t, flags|XPCLOSE, 0); - if (!(flags&XBGND) && !(flags&XXCOM)) - rv = i; - break; - - case TLIST: - while (t->type == TLIST) { - execute(t->left, flags & XERROK); - t = t->right; - } - rv = execute(t, flags & XERROK); - break; - -#ifdef KSH - case TCOPROC: - { -# ifdef JOB_SIGS - sigset_t omask; -# endif /* JOB_SIGS */ - -# ifdef JOB_SIGS - /* Block sigchild as we are using things changed in the - * signal handler - */ - sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); - e->type = E_ERRH; - i = ksh_sigsetjmp(e->jbuf, 0); - if (i) { - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); - quitenv(); - unwind(i); - /*NOTREACHED*/ - } -# endif /* JOB_SIGS */ - /* Already have a (live) co-process? */ - if (coproc.job && coproc.write >= 0) - errorf("coprocess already exists"); - - /* Can we re-use the existing co-process pipe? */ - coproc_cleanup(TRUE); - - /* do this before opening pipes, in case these fail */ - e->savefd[0] = savefd(0, 0); - e->savefd[1] = savefd(1, 0); - - openpipe(pv); - if (pv[0] != 0) { - ksh_dup2(pv[0], 0, FALSE); - close(pv[0]); - } - coproc.write = pv[1]; - coproc.job = (void *) 0; - - if (coproc.readw >= 0) - ksh_dup2(coproc.readw, 1, FALSE); - else { - openpipe(pv); - coproc.read = pv[0]; - ksh_dup2(pv[1], 1, FALSE); - coproc.readw = pv[1]; /* closed before first read */ - coproc.njobs = 0; - /* create new coprocess id */ - ++coproc.id; - } -# ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); - e->type = E_EXEC; /* no more need for error handler */ -# endif /* JOB_SIGS */ - - /* exchild() closes coproc.* in child after fork, - * will also increment coproc.njobs when the - * job is actually created. - */ - flags &= ~XEXEC; - exchild(t->left, flags|XBGND|XFORK|XCOPROC|XCCLOSE, - coproc.readw); - break; - } -#endif /* KSH */ - - case TASYNC: - /* XXX non-optimal, I think - "(foo &)", forks for (), - * forks again for async... parent should optimize - * this to "foo &"... - */ - rv = execute(t->left, (flags&~XEXEC)|XBGND|XFORK); - break; - - case TOR: - case TAND: - rv = execute(t->left, XERROK); - if (t->right != NULL && (rv == 0) == (t->type == TAND)) - rv = execute(t->right, flags & XERROK); - else - flags |= XERROK; - break; - - case TBANG: - rv = !execute(t->right, XERROK); - break; - -#ifdef KSH - case TDBRACKET: - { - Test_env te; - - te.flags = TEF_DBRACKET; - te.pos.wp = t->args; - te.isa = dbteste_isa; - te.getopnd = dbteste_getopnd; - te.eval = dbteste_eval; - te.error = dbteste_error; - - rv = test_parse(&te); - break; - } -#endif /* KSH */ - - case TFOR: -#ifdef KSH - case TSELECT: - { - volatile bool_t is_first = TRUE; -#endif /* KSH */ - ap = (t->vars != NULL) ? - eval(t->vars, DOBLANK|DOGLOB|DOTILDE) - : e->loc->argv + 1; - e->type = E_LOOP; - while (1) { - i = ksh_sigsetjmp(e->jbuf, 0); - if (!i) - break; - if ((e->flags&EF_BRKCONT_PASS) - || (i != LBREAK && i != LCONTIN)) - { - quitenv(); - unwind(i); - } else if (i == LBREAK) { - rv = 0; - goto Break; - } - } - rv = 0; /* in case of a continue */ - if (t->type == TFOR) { - while (*ap != NULL) { - setstr(global(t->str), *ap++, KSH_UNWIND_ERROR); - rv = execute(t->left, flags & XERROK); - } - } -#ifdef KSH - else { /* TSELECT */ - for (;;) { - if (!(cp = do_selectargs(ap, is_first))) { - rv = 1; - break; - } - is_first = FALSE; - setstr(global(t->str), cp, KSH_UNWIND_ERROR); - rv = execute(t->left, flags & XERROK); - } - } - } -#endif /* KSH */ - break; - - case TWHILE: - case TUNTIL: - e->type = E_LOOP; - while (1) { - i = ksh_sigsetjmp(e->jbuf, 0); - if (!i) - break; - if ((e->flags&EF_BRKCONT_PASS) - || (i != LBREAK && i != LCONTIN)) - { - quitenv(); - unwind(i); - } else if (i == LBREAK) { - rv = 0; - goto Break; - } - } - rv = 0; /* in case of a continue */ - while ((execute(t->left, XERROK) == 0) == (t->type == TWHILE)) - rv = execute(t->right, flags & XERROK); - break; - - case TIF: - case TELIF: - if (t->right == NULL) - break; /* should be error */ - rv = execute(t->left, XERROK) == 0 ? - execute(t->right->left, flags & XERROK) : - execute(t->right->right, flags & XERROK); - break; - - case TCASE: - cp = evalstr(t->str, DOTILDE); - for (t = t->left; t != NULL && t->type == TPAT; t = t->right) - for (ap = t->vars; *ap; ap++) - if ((s = evalstr(*ap, DOTILDE|DOPAT)) - && gmatch(cp, s, FALSE)) - goto Found; - break; - Found: - rv = execute(t->left, flags & XERROK); - break; - - case TBRACE: - rv = execute(t->left, flags & XERROK); - break; - - case TFUNCT: - rv = define(t->str, t); - break; - - case TTIME: - /* Clear XEXEC so nested execute() call doesn't exit - * (allows "ls -l | time grep foo"). - */ - rv = timex(t, flags & ~XEXEC); - break; - - case TEXEC: /* an eval'd TCOM */ - s = t->args[0]; - ap = makenv(); -#ifndef F_SETFD - for (i = 0; i < sizeof(clexec_tab); i++) - if (clexec_tab[i]) { - close(i); - clexec_tab[i] = 0; - } -#endif - restoresigs(); - cleanup_proc_env(); - /* XINTACT bit is for OS2 */ - ksh_execve(t->str, t->args, ap, (flags & XINTACT) ? 1 : 0); - if (errno == ENOEXEC) - scriptexec(t, ap); - else - errorf("%s: %s", s, strerror(errno)); - } - Break: - exstat = rv; - - quitenv(); /* restores IO */ - if ((flags&XEXEC)) - unwind(LEXIT); /* exit child */ - if (rv != 0 && !(flags & XERROK)) { - if (Flag(FERREXIT)) - unwind(LERROR); - trapsig(SIGERR_); - } - return rv; -} - -/* - * execute simple command - */ - -static int -comexec(t, tp, ap, flags) - struct op *t; - struct tbl *volatile tp; - register char **ap; - int volatile flags; -{ - int i; - int leave = LLEAVE; - volatile int rv = 0; - register char *cp; - register char **lastp; - static struct op texec; /* Must be static (XXX but why?) */ - int type_flags; - int keepasn_ok; - int fcflags = FC_BI|FC_FUNC|FC_PATH; - int bourne_function_call = 0; - -#ifdef KSH - /* snag the last argument for $_ XXX not the same as at&t ksh, - * which only seems to set $_ after a newline (but not in - * functions/dot scripts, but in interactive and script) - - * perhaps save last arg here and set it in shell()?. - */ - if (Flag(FTALKING) && *(lastp = ap)) { - while (*++lastp) - ; - /* setstr() can't fail here */ - setstr(typeset("_", LOCAL, 0, INTEGER, 0), *--lastp, - KSH_RETURN_ERROR); - } -#endif /* KSH */ - - /* Deal with the shell builtins builtin, exec and command since - * they can be followed by other commands. This must be done before - * we know if we should create a local block, which must be done - * before we can do a path search (in case the assignments change - * PATH). - * Odd cases: - * FOO=bar exec > /dev/null FOO is kept but not exported - * FOO=bar exec foobar FOO is exported - * FOO=bar command exec > /dev/null FOO is neither kept nor exported - * FOO=bar command FOO is neither kept nor exported - * PATH=... foobar use new PATH in foobar search - */ - keepasn_ok = 1; - while (tp && tp->type == CSHELL) { - fcflags = FC_BI|FC_FUNC|FC_PATH;/* undo effects of command */ - if (tp->val.f == c_builtin) { - if ((cp = *++ap) == NULL) { - tp = NULL; - break; - } - tp = findcom(cp, FC_BI); - if (tp == NULL) - errorf("builtin: %s: not a builtin", cp); - continue; - } else if (tp->val.f == c_exec) { - if (ap[1] == NULL) - break; - ap++; - flags |= XEXEC; - } else if (tp->val.f == c_command) { - int optc, saw_p = 0; - - /* Ugly dealing with options in two places (here and - * in c_command(), but such is life) - */ - ksh_getopt_reset(&builtin_opt, 0); - while ((optc = ksh_getopt(ap, &builtin_opt, ":p")) - == 'p') - saw_p = 1; - if (optc != EOF) - break; /* command -vV or something */ - /* don't look for functions */ - fcflags = FC_BI|FC_PATH; - if (saw_p) { - if (Flag(FRESTRICTED)) { - warningf(TRUE, - "command -p: restricted"); - rv = 1; - goto Leave; - } - fcflags |= FC_DEFPATH; - } - ap += builtin_opt.optind; - /* POSIX says special builtins lose their status - * if accessed using command. - */ - keepasn_ok = 0; - if (!ap[0]) { - /* ensure command with no args exits with 0 */ - subst_exstat = 0; - break; - } - } else - break; - tp = findcom(ap[0], fcflags & (FC_BI|FC_FUNC)); - } - if (keepasn_ok && (!ap[0] || (tp && (tp->flag & KEEPASN)))) - type_flags = 0; - else { - /* create new variable/function block */ - newblock(); - /* ksh functions don't keep assignments, POSIX functions do. */ - if (keepasn_ok && tp && tp->type == CFUNC - && !(tp->flag & FKSH)) { - bourne_function_call = 1; - type_flags = 0; - } else - type_flags = LOCAL|LOCAL_COPY|EXPORT; - } - if (Flag(FEXPORT)) - type_flags |= EXPORT; - for (i = 0; t->vars[i]; i++) { - cp = evalstr(t->vars[i], DOASNTILDE); - if (Flag(FXTRACE)) { - if (i == 0) - shf_fprintf(shl_out, "%s", - PS4_SUBSTITUTE(str_val(global("PS4")))); - shf_fprintf(shl_out, "%s%s", cp, - t->vars[i + 1] ? space : newline); - if (!t->vars[i + 1]) - shf_flush(shl_out); - } - typeset(cp, type_flags, 0, 0, 0); - if (bourne_function_call && !(type_flags & EXPORT)) - typeset(cp, LOCAL|LOCAL_COPY|EXPORT, 0, 0, 0); - } - - if ((cp = *ap) == NULL) { - rv = subst_exstat; - goto Leave; - } else if (!tp) { - if (Flag(FRESTRICTED) && ksh_strchr_dirsep(cp)) { - warningf(TRUE, "%s: restricted", cp); - rv = 1; - goto Leave; - } - tp = findcom(cp, fcflags); - } - - switch (tp->type) { - case CSHELL: /* shell built-in */ - rv = call_builtin(tp, ap); - break; - - case CFUNC: /* function call */ - { - volatile int old_xflag; - volatile Tflag old_inuse; - const char *volatile old_kshname; - - if (!(tp->flag & ISSET)) { - struct tbl *ftp; - - if (!tp->u.fpath) { - if (tp->u2.errno_) { - warningf(TRUE, - "%s: can't find function definition file - %s", - cp, strerror(tp->u2.errno_)); - rv = 126; - } else { - warningf(TRUE, - "%s: can't find function definition file", cp); - rv = 127; - } - break; - } - if (include(tp->u.fpath, 0, (char **) 0, 0) < 0) { - warningf(TRUE, - "%s: can't open function definition file %s - %s", - cp, tp->u.fpath, strerror(errno)); - rv = 127; - break; - } - if (!(ftp = findfunc(cp, hash(cp), FALSE)) - || !(ftp->flag & ISSET)) - { - warningf(TRUE, - "%s: function not defined by %s", - cp, tp->u.fpath); - rv = 127; - break; - } - tp = ftp; - } - - /* ksh functions set $0 to function name, POSIX functions leave - * $0 unchanged. - */ - old_kshname = kshname; - if (tp->flag & FKSH) - kshname = ap[0]; - else - ap[0] = (char *) __UNCONST(kshname); - e->loc->argv = ap; - for (i = 0; *ap++ != NULL; i++) - ; - e->loc->argc = i - 1; - /* ksh-style functions handle getopts sanely, - * bourne/posix functions are insane... - */ - if (tp->flag & FKSH) { - e->loc->flags |= BF_DOGETOPTS; - e->loc->getopts_state = user_opt; - getopts_reset(1); - } - - old_xflag = Flag(FXTRACE); - Flag(FXTRACE) = tp->flag & TRACE ? TRUE : FALSE; - - old_inuse = tp->flag & FINUSE; - tp->flag |= FINUSE; - - e->type = E_FUNC; - i = ksh_sigsetjmp(e->jbuf, 0); - if (i == 0) { - /* seems odd to pass XERROK here, but at&t ksh does */ - exstat = execute(tp->val.t, flags & XERROK); - i = LRETURN; - } - kshname = old_kshname; - Flag(FXTRACE) = old_xflag; - tp->flag = (tp->flag & ~FINUSE) | old_inuse; - /* Were we deleted while executing? If so, free the execution - * tree. todo: Unfortunately, the table entry is never re-used - * until the lookup table is expanded. - */ - if ((tp->flag & (FDELETE|FINUSE)) == FDELETE) { - if (tp->flag & ALLOC) { - tp->flag &= ~ALLOC; - tfree(tp->val.t, tp->areap); - } - tp->flag = 0; - } - switch (i) { - case LRETURN: - case LERROR: - rv = exstat; - break; - case LINTR: - case LEXIT: - case LLEAVE: - case LSHELL: - quitenv(); - unwind(i); - /*NOTREACHED*/ - default: - quitenv(); - internal_errorf(1, "CFUNC %d", i); - } - break; - } - - case CEXEC: /* executable command */ - case CTALIAS: /* tracked alias */ - if (!(tp->flag&ISSET)) { - /* errno_ will be set if the named command was found - * but could not be executed (permissions, no execute - * bit, directory, etc). Print out a (hopefully) - * useful error message and set the exit status to 126. - */ - if (tp->u2.errno_) { - warningf(TRUE, "%s: cannot execute - %s", cp, - strerror(tp->u2.errno_)); - rv = 126; /* POSIX */ - } else { - warningf(TRUE, "%s: not found", cp); - rv = 127; - } - break; - } - -#ifdef KSH - /* set $_ to program's full path */ - /* setstr() can't fail here */ - setstr(typeset("_", LOCAL|EXPORT, 0, INTEGER, 0), - tp->val.s, KSH_RETURN_ERROR); -#endif /* KSH */ - - if (flags&XEXEC) { - j_exit(); - if (!(flags&XBGND) || Flag(FMONITOR)) { - setexecsig(&sigtraps[SIGINT], SS_RESTORE_ORIG); - setexecsig(&sigtraps[SIGQUIT], SS_RESTORE_ORIG); - } - } - - /* to fork we set up a TEXEC node and call execute */ - texec.type = TEXEC; - texec.left = t; /* for tprint */ - texec.str = tp->val.s; - texec.args = ap; - rv = exchild(&texec, flags, -1); - break; - } - leave = LEXIT; - Leave: - if (flags & XEXEC) { - exstat = rv; - unwind(leave); - } - return rv; -} - -static void -scriptexec(tp, ap) - register struct op *tp; - register char **ap; -{ - char *shellv; - - shellv = str_val(global(EXECSHELL_STR)); - if (shellv && *shellv) - shellv = search(shellv, path, X_OK, (int *) 0); - if (!shellv || !*shellv) - shellv = __UNCONST(EXECSHELL); - - *tp->args-- = tp->str; -#ifdef SHARPBANG - { - char buf[LINE]; - register char *cp; - register int fd, n; - - buf[0] = '\0'; - if ((fd = open(tp->str, O_RDONLY)) >= 0) { - if ((n = read(fd, buf, LINE - 1)) > 0) - buf[n] = '\0'; - (void) close(fd); - } - if ((buf[0] == '#' && buf[1] == '!' && (cp = &buf[2])) -# ifdef OS2 - || (strncmp(buf, "extproc", 7) == 0 && isspace((unsigned char)buf[7]) - && (cp = &buf[7])) -# endif /* OS2 */ - ) - { - while (*cp && (*cp == ' ' || *cp == '\t')) - cp++; - if (*cp && *cp != '\n') { - char *a0 = cp, *a1 = (char *) 0; -# ifdef OS2 - char *a2 = cp; -# endif /* OS2 */ - - while (*cp && *cp != '\n' && *cp != ' ' - && *cp != '\t') - { -# ifdef OS2 - /* Allow shell search without prepended path - * if shell with / in pathname cannot be found. - * Use / explicitly so \ can be used if explicit - * needs to be forced. - */ - if (*cp == '/') - a2 = cp + 1; -# endif /* OS2 */ - cp++; - } - if (*cp && *cp != '\n') { - *cp++ = '\0'; - while (*cp - && (*cp == ' ' || *cp == '\t')) - cp++; - if (*cp && *cp != '\n') { - a1 = cp; - /* all one argument */ - while (*cp && *cp != '\n') - cp++; - } - } - if (*cp == '\n') { - *cp = '\0'; - if (a1) - *tp->args-- = a1; -# ifdef OS2 - if (a0 != a2) { - char *tmp_a0 = str_nsave(a0, - strlen(a0) + 5, ATEMP); - if (search_access(tmp_a0, X_OK, - (int *) 0)) - a0 = a2; - afree(tmp_a0, ATEMP); - } -# endif /* OS2 */ - shellv = a0; - } - } -# ifdef OS2 - } else { - /* Use ksh documented shell default if present - * else use OS2_SHELL which is assumed to need - * the /c option and '\' as dir separator. - */ - char *p = shellv; - - shellv = str_val(global("EXECSHELL")); - if (shellv && *shellv) - shellv = search(shellv, path, X_OK, (int *) 0); - if (!shellv || !*shellv) { - shellv = p; - *tp->args-- = "/c"; - for (p = tp->str; *p; p++) - if (*p == '/') - *p = '\\'; - } -# endif /* OS2 */ - } - } -#endif /* SHARPBANG */ - *tp->args = shellv; - - ksh_execve(tp->args[0], tp->args, ap, 0); - - /* report both the program that was run and the bogus shell */ - errorf("%s: %s: %s", tp->str, shellv, strerror(errno)); -} - -int -shcomexec(wp) - register char **wp; -{ - register struct tbl *tp; - - tp = tsearch(&builtins, *wp, hash(*wp)); - if (tp == NULL) - internal_errorf(1, "shcomexec: %s", *wp); - return call_builtin(tp, wp); -} - -/* - * Search function tables for a function. If create set, a table entry - * is created if none is found. - */ -struct tbl * -findfunc(name, h, create) - const char *name; - unsigned int h; - int create; -{ - struct block *l; - struct tbl *tp = (struct tbl *) 0; - - for (l = e->loc; l; l = l->next) { - tp = tsearch(&l->funs, name, h); - if (tp) - break; - if (!l->next && create) { - tp = tenter(&l->funs, name, h); - tp->flag = DEFINED; - tp->type = CFUNC; - tp->val.t = (struct op *) 0; - break; - } - } - return tp; -} - -/* - * define function. Returns 1 if function is being undefined (t == 0) and - * function did not exist, returns 0 otherwise. - */ -int -define(name, t) - const char *name; - struct op *t; -{ - struct tbl *tp; - int was_set = 0; - - while (1) { - tp = findfunc(name, hash(name), TRUE); - - if (tp->flag & ISSET) - was_set = 1; - /* If this function is currently being executed, we zap this - * table entry so findfunc() won't see it - */ - if (tp->flag & FINUSE) { - tp->name[0] = '\0'; - tp->flag &= ~DEFINED; /* ensure it won't be found */ - tp->flag |= FDELETE; - } else - break; - } - - if (tp->flag & ALLOC) { - tp->flag &= ~(ISSET|ALLOC); - tfree(tp->val.t, tp->areap); - } - - if (t == NULL) { /* undefine */ - tdelete(tp); - return was_set ? 0 : 1; - } - - tp->val.t = tcopy(t->left, tp->areap); - tp->flag |= (ISSET|ALLOC); - if (t->u.ksh_func) - tp->flag |= FKSH; - - return 0; -} - -/* - * add builtin - */ -void -builtin(name, func) - const char *name; - int (*func) ARGS((char **)); -{ - register struct tbl *tp; - Tflag flag; - - /* see if any flags should be set for this builtin */ - for (flag = 0; ; name++) { - if (*name == '=') /* command does variable assignment */ - flag |= KEEPASN; - else if (*name == '*') /* POSIX special builtin */ - flag |= SPEC_BI; - else if (*name == '+') /* POSIX regular builtin */ - flag |= REG_BI; - else - break; - } - - tp = tenter(&builtins, name, hash(name)); - tp->flag = DEFINED | flag; - tp->type = CSHELL; - tp->val.f = func; -} - -/* - * find command - * either function, hashed command, or built-in (in that order) - */ -struct tbl * -findcom(name, flags) - const char *name; - int flags; /* FC_* */ -{ - static struct tbl temp; - unsigned int h = hash(name); - struct tbl *tp = NULL, *tbi; - int insert = Flag(FTRACKALL); /* insert if not found */ - char *fpath; /* for function autoloading */ - char *npath; - - if (ksh_strchr_dirsep(name) != NULL) { - insert = 0; - /* prevent FPATH search below */ - flags &= ~FC_FUNC; - goto Search; - } - tbi = (flags & FC_BI) ? tsearch(&builtins, name, h) : NULL; - /* POSIX says special builtins first, then functions, then - * POSIX regular builtins, then search path... - */ - if ((flags & FC_SPECBI) && tbi && (tbi->flag & SPEC_BI)) - tp = tbi; - if (!tp && (flags & FC_FUNC)) { - tp = findfunc(name, h, FALSE); - if (tp && !(tp->flag & ISSET)) { - if ((fpath = str_val(global("FPATH"))) == null) { - tp->u.fpath = (char *) 0; - tp->u2.errno_ = 0; - } else - tp->u.fpath = search(name, fpath, R_OK, - &tp->u2.errno_); - } - } - if (!tp && (flags & FC_REGBI) && tbi && (tbi->flag & REG_BI)) - tp = tbi; - /* todo: posix says non-special/non-regular builtins must - * be triggered by some user-controllable means like a - * special directory in PATH. Requires modifications to - * the search() function. Tracked aliases should be - * modified to allow tracking of builtin commands. - * This should be under control of the FPOSIX flag. - * If this is changed, also change c_whence... - */ - if (!tp && (flags & FC_UNREGBI) && tbi) - tp = tbi; - if (!tp && (flags & FC_PATH) && !(flags & FC_DEFPATH)) { - tp = tsearch(&taliases, name, h); - if (tp && (tp->flag & ISSET) && eaccess(tp->val.s, X_OK) != 0) { - if (tp->flag & ALLOC) { - tp->flag &= ~ALLOC; - afree(tp->val.s, APERM); - } - tp->flag &= ~ISSET; - } - } - - Search: - if ((!tp || (tp->type == CTALIAS && !(tp->flag&ISSET))) - && (flags & FC_PATH)) - { - if (!tp) { - if (insert && !(flags & FC_DEFPATH)) { - tp = tenter(&taliases, name, h); - tp->type = CTALIAS; - } else { - tp = &temp; - tp->type = CEXEC; - } - tp->flag = DEFINED; /* make ~ISSET */ - } - npath = search(name, flags & FC_DEFPATH ? def_path : path, - X_OK, &tp->u2.errno_); - if (npath) { - if (tp == &temp) { - tp->val.s = npath; - } else { - tp->val.s = str_save(npath, APERM); - afree(npath, ATEMP); - } - tp->flag |= ISSET|ALLOC; - } else if ((flags & FC_FUNC) - && (fpath = str_val(global("FPATH"))) != null - && (npath = search(name, fpath, R_OK, - &tp->u2.errno_)) != (char *) 0) - { - /* An undocumented feature of at&t ksh is that it - * searches FPATH if a command is not found, even - * if the command hasn't been set up as an autoloaded - * function (ie, no typeset -uf). - */ - tp = &temp; - tp->type = CFUNC; - tp->flag = DEFINED; /* make ~ISSET */ - tp->u.fpath = npath; - } - } - return tp; -} - -/* - * flush executable commands with relative paths - */ -void -flushcom(all) - int all; /* just relative or all */ -{ - struct tbl *tp; - struct tstate ts; - - for (twalk(&ts, &taliases); (tp = tnext(&ts)) != NULL; ) - if ((tp->flag&ISSET) && (all || !ISDIRSEP(tp->val.s[0]))) { - if (tp->flag&ALLOC) { - tp->flag &= ~(ALLOC|ISSET); - afree(tp->val.s, APERM); - } - tp->flag &= ~ISSET; - } -} - -/* Check if path is something we want to find. Returns -1 for failure. */ -int -search_access(pathx, mode, errnop) - const char *pathx; - int mode; - int *errnop; /* set if candidate found, but not suitable */ -{ -#ifndef OS2 - int ret, err = 0; - struct stat statb; - - if (stat(pathx, &statb) < 0) - return -1; - ret = eaccess(pathx, mode); - if (ret < 0) - err = errno; /* File exists, but we can't access it */ - else if (mode == X_OK - && (!S_ISREG(statb.st_mode) - /* This 'cause access() says root can execute everything */ - || !(statb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)))) - { - ret = -1; - err = S_ISDIR(statb.st_mode) ? EISDIR : EACCES; - } - if (err && errnop && !*errnop) - *errnop = err; - return ret; -#else /* !OS2 */ - /* - * NOTE: ASSUMES path can be modified and has enough room at the - * end of the string for a suffix (ie, 4 extra characters). - * Certain code knows this (eg, eval.c(globit()), - * exec.c(search())). - */ - static char *xsuffixes[] = { ".ksh", ".exe", ".", ".sh", ".cmd", - ".com", ".bat", (char *) 0 - }; - static char *rsuffixes[] = { ".ksh", ".", ".sh", ".cmd", ".bat", - (char *) 0 - }; - int i; - char *mpath = (char *) pathx; - char *tp = mpath + strlen(mpath); - char *p; - char **sfx; - - /* If a suffix has been specified, check if it is one of the - * suffixes that indicate the file is executable - if so, change - * the access test to R_OK... - * This code assumes OS/2 files can have only one suffix... - */ - if ((p = strrchr((p = ksh_strrchr_dirsep(mpath)) ? p : mpath, '.'))) { - if (mode == X_OK) - mode = R_OK; - return search_access1(mpath, mode, errnop); - } - /* Try appending the various suffixes. Different suffixes for - * read and execute 'cause we don't want to read an executable... - */ - sfx = mode == R_OK ? rsuffixes : xsuffixes; - for (i = 0; sfx[i]; i++) { - strcpy(tp, p = sfx[i]); - if (search_access1(mpath, R_OK, errnop) == 0) - return 0; - *tp = '\0'; - } - return -1; -#endif /* !OS2 */ -} - -#ifdef OS2 -static int -search_access1(pathx, mode, errnop) - const char *pathx; - int mode; - int *errnop; /* set if candidate found, but not suitable */ -{ - int ret, err = 0; - struct stat statb; - - if (stat(pathx, &statb) < 0) - return -1; - ret = eaccess(pathx, mode); - if (ret < 0) - err = errno; /* File exists, but we can't access it */ - else if (!S_ISREG(statb.st_mode)) { - ret = -1; - err = S_ISDIR(statb.st_mode) ? EISDIR : EACCES; - } - if (err && errnop && !*errnop) - *errnop = err; - return ret; -} -#endif /* OS2 */ - -/* - * search for command with PATH - */ -char * -search(name, pathx, mode, errnop) - const char *name; - const char *pathx; - int mode; /* R_OK or X_OK */ - int *errnop; /* set if candidate found, but not suitable */ -{ - const char *sp, *p; - char *xp; - XString xs; - int namelen; - - if (errnop) - *errnop = 0; -#ifdef OS2 - /* Xinit() allocates 8 additional bytes, so appended suffixes won't - * overflow the memory. - */ - namelen = strlen(name) + 1; - Xinit(xs, xp, namelen, ATEMP); - memcpy(Xstring(xs, xp), name, namelen); - - if (ksh_strchr_dirsep(name)) { - if (search_access(Xstring(xs, xp), mode, errnop) >= 0) - return Xstring(xs, xp); /* not Xclose() - see above */ - Xfree(xs, xp); - return NULL; - } - - /* Look in current context always. (os2 style) */ - if (search_access(Xstring(xs, xp), mode, errnop) == 0) - return Xstring(xs, xp); /* not Xclose() - xp may be wrong */ -#else /* OS2 */ - if (ksh_strchr_dirsep(name)) { - if (search_access(name, mode, errnop) == 0) - return (char *)__UNCONST(name); - return NULL; - } - - namelen = strlen(name) + 1; - Xinit(xs, xp, 128, ATEMP); -#endif /* OS2 */ - - sp = pathx; - while (sp != NULL) { - xp = Xstring(xs, xp); - if (!(p = strchr(sp, PATHSEP))) - p = sp + strlen(sp); - if (p != sp) { - XcheckN(xs, xp, p - sp); - memcpy(xp, sp, p - sp); - xp += p - sp; - *xp++ = DIRSEP; - } - sp = p; - XcheckN(xs, xp, namelen); - memcpy(xp, name, namelen); - if (search_access(Xstring(xs, xp), mode, errnop) == 0) -#ifdef OS2 - return Xstring(xs, xp); /* Not Xclose() - see above */ -#else /* OS2 */ - return Xclose(xs, xp + namelen); -#endif /* OS2 */ - if (*sp++ == '\0') - sp = NULL; - } - Xfree(xs, xp); - return NULL; -} - -static int -call_builtin(tp, wp) - struct tbl *tp; - char **wp; -{ - int rv; - - builtin_argv0 = wp[0]; - builtin_flag = tp->flag; - shf_reopen(1, SHF_WR, shl_stdout); - shl_stdout_ok = 1; - ksh_getopt_reset(&builtin_opt, GF_ERROR); - rv = (*tp->val.f)(wp); - shf_flush(shl_stdout); - shl_stdout_ok = 0; - builtin_flag = 0; - builtin_argv0 = (char *) 0; - return rv; -} - -/* - * set up redirection, saving old fd's in e->savefd - */ -static int -iosetup(iop, tp) - register struct ioword *iop; - struct tbl *tp; -{ - register int u = -1; - char *cp = iop->name; - int iotype = iop->flag & IOTYPE; - int do_open = 1, do_close = 0, UNINITIALIZED(flags); - struct ioword iotmp; - struct stat statb; - - if (iotype != IOHERE) - cp = evalonestr(cp, DOTILDE|(Flag(FTALKING_I) ? DOGLOB : 0)); - - /* Used for tracing and error messages to print expanded cp */ - iotmp = *iop; - iotmp.name = (iotype == IOHERE) ? (char *) 0 : cp; - iotmp.flag |= IONAMEXP; - - if (Flag(FXTRACE)) - shellf("%s%s\n", - PS4_SUBSTITUTE(str_val(global("PS4"))), - snptreef((char *) 0, 32, "%R", &iotmp)); - - switch (iotype) { - case IOREAD: - flags = O_RDONLY; - break; - - case IOCAT: - flags = O_WRONLY | O_APPEND | O_CREAT; - break; - - case IOWRITE: - flags = O_WRONLY | O_CREAT | O_TRUNC; - /* The stat() is here to allow redirections to - * things like /dev/null without error. - */ - if (Flag(FNOCLOBBER) && !(iop->flag & IOCLOB) - && (stat(cp, &statb) < 0 || S_ISREG(statb.st_mode))) - flags |= O_EXCL; - break; - - case IORDWR: - flags = O_RDWR | O_CREAT; - break; - - case IOHERE: - do_open = 0; - /* herein() returns -2 if error has been printed */ - u = herein(iop->heredoc, iop->flag & IOEVAL); - /* cp may have wrong name */ - break; - - case IODUP: - { - const char *emsg; - - do_open = 0; - if (*cp == '-' && !cp[1]) { - u = 1009; /* prevent error return below */ - do_close = 1; - } else if ((u = check_fd(cp, - X_OK | ((iop->flag & IORDUP) ? R_OK : W_OK), - &emsg)) < 0) - { - warningf(TRUE, "%s: %s", - snptreef((char *) 0, 32, "%R", &iotmp), emsg); - return -1; - } - if (u == iop->unit) - return 0; /* "dup from" == "dup to" */ - break; - } - } - if (do_open) { - if (Flag(FRESTRICTED) && (flags & O_CREAT)) { - warningf(TRUE, "%s: restricted", cp); - return -1; - } - u = open(cp, flags, 0666); -#ifdef OS2 - if (u < 0 && strcmp(cp, "/dev/null") == 0) - u = open("nul", flags, 0666); -#endif /* OS2 */ - } - if (u < 0) { - /* herein() may already have printed message */ - if (u == -1) - warningf(TRUE, "cannot %s %s: %s", - iotype == IODUP ? "dup" - : (iotype == IOREAD || iotype == IOHERE) ? - "open" : "create", cp, strerror(errno)); - return -1; - } - /* Do not save if it has already been redirected (i.e. "cat >x >y"). */ - if (e->savefd[iop->unit] == 0) { - /* If these are the same, it means unit was previously closed */ - if (u == iop->unit) - e->savefd[iop->unit] = -1; - else - /* c_exec() assumes e->savefd[fd] set for any - * redirections. Ask savefd() not to close iop->unit; - * this allows error messages to be seen if iop->unit - * is 2; also means we can't lose the fd (eg, both - * dup2 below and dup2 in restfd() failing). - */ - e->savefd[iop->unit] = savefd(iop->unit, 1); - } - - if (do_close) - close(iop->unit); - else if (u != iop->unit) { - if (ksh_dup2(u, iop->unit, TRUE) < 0) { - warningf(TRUE, - "could not finish (dup) redirection %s: %s", - snptreef((char *) 0, 32, "%R", &iotmp), - strerror(errno)); - if (iotype != IODUP) - close(u); - return -1; - } - if (iotype != IODUP) - close(u); -#ifdef KSH - /* Touching any co-process fd in an empty exec - * causes the shell to close its copies - */ - else if (tp && tp->type == CSHELL && tp->val.f == c_exec) { - if (iop->flag & IORDUP) /* possible exec <&p */ - coproc_read_close(u); - else /* possible exec >&p */ - coproc_write_close(u); - } -#endif /* KSH */ - } - if (u == 2) /* Clear any write errors */ - shf_reopen(2, SHF_WR, shl_out); - return 0; -} - -/* - * open here document temp file. - * if unquoted here, expand here temp file into second temp file. - */ -static int -herein(content, sub) - const char *content; - int sub; -{ - volatile int fd = -1; - struct source *s, *volatile osource; - struct shf *volatile shf; - struct temp *h; - int i; - - /* ksh -c 'cat << EOF' can cause this... */ - if (content == (char *) 0) { - warningf(TRUE, "here document missing"); - return -2; /* special to iosetup(): don't print error */ - } - - /* Create temp file to hold content (done before newenv so temp - * doesn't get removed too soon). - */ - h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps); - if (!(shf = h->shf) || (fd = open(h->name, O_RDONLY, 0)) < 0) { - warningf(TRUE, "can't %s temporary file %s: %s", - !shf ? "create" : "open", - h->name, strerror(errno)); - if (shf) - shf_close(shf); - return -2 /* special to iosetup(): don't print error */; - } - - osource = source; - newenv(E_ERRH); - i = ksh_sigsetjmp(e->jbuf, 0); - if (i) { - source = osource; - quitenv(); - shf_close(shf); /* after quitenv */ - close(fd); - return -2; /* special to iosetup(): don't print error */ - } - if (sub) { - /* Do substitutions on the content of heredoc */ - s = pushs(SSTRING, ATEMP); - s->start = s->str = content; - source = s; - if (yylex(ONEWORD|HEREDOC) != LWORD) - internal_errorf(1, "herein: yylex"); - source = osource; - shf_puts(evalstr(yylval.cp, 0), shf); - } else - shf_puts(content, shf); - - quitenv(); - - if (shf_close(shf) == EOF) { - close(fd); - warningf(TRUE, "error writing %s: %s", h->name, - strerror(errno)); - return -2; /* special to iosetup(): don't print error */ - } - - return fd; -} - -#ifdef KSH -/* - * ksh special - the select command processing section - * print the args in column form - assuming that we can - */ -static char * -do_selectargs(ap, print_menu) - register char **ap; - bool_t print_menu; -{ - static const char *const read_args[] = { - "read", "-r", "REPLY", (char *) 0 - }; - char *s; - int i, argct; - - for (argct = 0; ap[argct]; argct++) - ; - while (1) { - /* Menu is printed if - * - this is the first time around the select loop - * - the user enters a blank line - * - the REPLY parameter is empty - */ - if (print_menu || !*str_val(global("REPLY"))) - pr_menu(ap); - shellf("%s", str_val(global("PS3"))); - if (call_builtin(findcom("read", FC_BI), - (char **) __UNCONST(read_args))) - return (char *) 0; - s = str_val(global("REPLY")); - if (*s) { - i = atoi(s); - return (i >= 1 && i <= argct) ? ap[i - 1] : null; - } - print_menu = 1; - } -} - -struct select_menu_info { - char *const *args; - int arg_width; - int num_width; -} info; - -static char *select_fmt_entry ARGS((void *arg, int i, char *buf, int buflen)); - -/* format a single select menu item */ -static char * -select_fmt_entry(arg, i, buf, buflen) - void *arg; - int i; - char *buf; - int buflen; -{ - struct select_menu_info *smi = (struct select_menu_info *) arg; - - shf_snprintf(buf, buflen, "%*d) %s", - smi->num_width, i + 1, smi->args[i]); - return buf; -} - -/* - * print a select style menu - */ -int -pr_menu(ap) - char *const *ap; -{ - struct select_menu_info smi; - char *const *pp; - int nwidth, dwidth; - int i, n; - - /* Width/column calculations were done once and saved, but this - * means select can't be used recursively so we re-calculate each - * time (could save in a structure that is returned, but its probably - * not worth the bother). - */ - - /* - * get dimensions of the list - */ - for (n = 0, nwidth = 0, pp = ap; *pp; n++, pp++) { - i = strlen(*pp); - nwidth = (i > nwidth) ? i : nwidth; - } - /* - * we will print an index of the form - * %d) - * in front of each entry - * get the max width of this - */ - for (i = n, dwidth = 1; i >= 10; i /= 10) - dwidth++; - - smi.args = ap; - smi.arg_width = nwidth; - smi.num_width = dwidth; - print_columns(shl_out, n, select_fmt_entry, (void *) &smi, - dwidth + nwidth + 2, 1); - - return n; -} - -/* XXX: horrible kludge to fit within the framework */ - -static char *plain_fmt_entry ARGS((void *arg, int i, char *buf, int buflen)); - -static char * -plain_fmt_entry(arg, i, buf, buflen) - void *arg; - int i; - char *buf; - int buflen; -{ - shf_snprintf(buf, buflen, "%s", ((char *const *)arg)[i]); - return buf; -} - -int -pr_list(ap) - char *const *ap; -{ - char *const *pp; - int nwidth; - int i, n; - - for (n = 0, nwidth = 0, pp = ap; *pp; n++, pp++) { - i = strlen(*pp); - nwidth = (i > nwidth) ? i : nwidth; - } - print_columns(shl_out, n, plain_fmt_entry, (void *)__UNCONST(ap), - nwidth + 1, 0); - - return n; -} -#endif /* KSH */ -#ifdef KSH - -/* - * [[ ... ]] evaluation routines - */ - -extern const char *const dbtest_tokens[]; -extern const char db_close[]; - -/* Test if the current token is a whatever. Accepts the current token if - * it is. Returns 0 if it is not, non-zero if it is (in the case of - * TM_UNOP and TM_BINOP, the returned value is a Test_op). - */ -static int -dbteste_isa(te, meta) - Test_env *te; - Test_meta meta; -{ - int ret = 0; - int uqword; - char *p; - - if (!*te->pos.wp) - return meta == TM_END; - - /* unquoted word? */ - for (p = *te->pos.wp; *p == CHAR; p += 2) - ; - uqword = *p == EOS; - - if (meta == TM_UNOP || meta == TM_BINOP) { - if (uqword) { - char buf[8]; /* longer than the longest operator */ - char *q = buf; - for (p = *te->pos.wp; *p == CHAR - && q < &buf[sizeof(buf) - 1]; - p += 2) - *q++ = p[1]; - *q = '\0'; - ret = (int) test_isop(te, meta, buf); - } - } else if (meta == TM_END) - ret = 0; - else - ret = uqword - && strcmp(*te->pos.wp, dbtest_tokens[(int) meta]) == 0; - - /* Accept the token? */ - if (ret) - te->pos.wp++; - - return ret; -} - -static const char * -dbteste_getopnd(te, op, do_eval) - Test_env *te; - Test_op op; - int do_eval; -{ - char *s = *te->pos.wp; - - if (!s) - return (char *) 0; - - te->pos.wp++; - - if (!do_eval) - return null; - - if (op == TO_STEQL || op == TO_STNEQ) - s = evalstr(s, DOTILDE | DOPAT); - else - s = evalstr(s, DOTILDE); - - return s; -} - -static int -dbteste_eval(te, op, opnd1, opnd2, do_eval) - Test_env *te; - Test_op op; - const char *opnd1; - const char *opnd2; - int do_eval; -{ - return test_eval(te, op, opnd1, opnd2, do_eval); -} - -static void -dbteste_error(te, offset, msg) - Test_env *te; - int offset; - const char *msg; -{ - te->flags |= TEF_ERROR; - internal_errorf(0, "dbteste_error: %s (offset %d)", msg, offset); -} -#endif /* KSH */ diff --git a/bin/ksh/expand.h b/bin/ksh/expand.h deleted file mode 100644 index 5618af222..000000000 --- a/bin/ksh/expand.h +++ /dev/null @@ -1,109 +0,0 @@ -/* $NetBSD: expand.h,v 1.5 2013/10/18 19:53:34 christos Exp $ */ - -/* - * Expanding strings - */ -/* $Id: expand.h,v 1.5 2013/10/18 19:53:34 christos Exp $ */ - -#define X_EXTRA 8 /* this many extra bytes in X string */ - -#if 0 /* Usage */ - XString xs; - char *xp; - - Xinit(xs, xp, 128, ATEMP); /* allocate initial string */ - while ((c = generate()) { - Xcheck(xs, xp); /* expand string if necessary */ - Xput(xs, xp, c); /* add character */ - } - return Xclose(xs, xp); /* resize string */ -/* - * NOTE: - * The Xcheck and Xinit macros have a magic + X_EXTRA in the lengths. - * This is so that you can put up to X_EXTRA characters in a XString - * before calling Xcheck. (See yylex in lex.c) - */ -#endif /* 0 */ - -typedef struct XString { - char *end, *beg; /* end, begin of string */ - size_t len; /* length */ - Area *areap; /* area to allocate/free from */ -} XString; - -typedef char * XStringP; - -/* initialize expandable string */ -#define Xinit(xs, xp, length, area) do { \ - (xs).len = length; \ - (xs).areap = (area); \ - (xs).beg = alloc((xs).len + X_EXTRA, (xs).areap); \ - (xs).end = (xs).beg + (xs).len; \ - xp = (xs).beg; \ - __USE(xp); \ - } while (0) - -/* stuff char into string */ -#define Xput(xs, xp, c) (*xp++ = (c)) - -/* check if there are at least n bytes left */ -#define XcheckN(xs, xp, n) do { \ - int more = ((xp) + (n)) - (xs).end; \ - if (more > 0) \ - xp = Xcheck_grow_(&xs, xp, more); \ - } while (0) - -/* check for overflow, expand string */ -#define Xcheck(xs, xp) XcheckN(xs, xp, 1) - -/* free string */ -#define Xfree(xs, xp) afree((void*) (xs).beg, (xs).areap) - -/* close, return string */ -#define Xclose(xs, xp) (char*) aresize((void*)(xs).beg, \ - (size_t)((xp) - (xs).beg), (xs).areap) -/* begin of string */ -#define Xstring(xs, xp) ((xs).beg) - -#define Xnleft(xs, xp) ((xs).end - (xp)) /* may be less than 0 */ -#define Xlength(xs, xp) ((xp) - (xs).beg) -#define Xsize(xs, xp) ((xs).end - (xs).beg) -#define Xsavepos(xs, xp) ((xp) - (xs).beg) -#define Xrestpos(xs, xp, n) ((xs).beg + (n)) - -char * Xcheck_grow_ ARGS((XString *xsp, char *xp, int more)); - -/* - * expandable vector of generic pointers - */ - -typedef struct XPtrV { - void **cur; /* next avail pointer */ - void **beg, **end; /* begin, end of vector */ -} XPtrV; - -#define XPinit(x, n) do { \ - register void **vp__; \ - vp__ = (void**) alloc(sizeofN(void*, n), ATEMP); \ - (x).cur = (x).beg = vp__; \ - (x).end = vp__ + n; \ - } while (0) - -#define XPput(x, p) do { \ - if ((x).cur >= (x).end) { \ - int n = XPsize(x); \ - (x).beg = (void**) aresize((void*) (x).beg, \ - sizeofN(void*, n*2), ATEMP); \ - (x).cur = (x).beg + n; \ - (x).end = (x).cur + n; \ - } \ - *(x).cur++ = (p); \ - } while (0) - -#define XPptrv(x) ((x).beg) -#define XPsize(x) ((x).cur - (x).beg) - -#define XPclose(x) (void**) aresize((void*)(x).beg, \ - sizeofN(void*, XPsize(x)), ATEMP) - -#define XPfree(x) afree((void*) (x).beg, ATEMP) diff --git a/bin/ksh/expr.c b/bin/ksh/expr.c deleted file mode 100644 index 6ba91dd3b..000000000 --- a/bin/ksh/expr.c +++ /dev/null @@ -1,613 +0,0 @@ -/* $NetBSD: expr.c,v 1.9 2011/10/16 17:12:11 joerg Exp $ */ - -/* - * Korn expression evaluation - */ -/* - * todo: better error handling: if in builtin, should be builtin error, etc. - */ -#include - -#ifndef lint -__RCSID("$NetBSD: expr.c,v 1.9 2011/10/16 17:12:11 joerg Exp $"); -#endif - - -#include "sh.h" -#include - - -/* The order of these enums is constrained by the order of opinfo[] */ -enum token { - /* some (long) unary operators */ - O_PLUSPLUS = 0, O_MINUSMINUS, - /* binary operators */ - O_EQ, O_NE, - /* assignments are assumed to be in range O_ASN .. O_BORASN */ - O_ASN, O_TIMESASN, O_DIVASN, O_MODASN, O_PLUSASN, O_MINUSASN, - O_LSHIFTASN, O_RSHIFTASN, O_BANDASN, O_BXORASN, O_BORASN, - O_LSHIFT, O_RSHIFT, - O_LE, O_GE, O_LT, O_GT, - O_LAND, - O_LOR, - O_TIMES, O_DIV, O_MOD, - O_PLUS, O_MINUS, - O_BAND, - O_BXOR, - O_BOR, - O_TERN, - O_COMMA, - /* things after this aren't used as binary operators */ - /* unary that are not also binaries */ - O_BNOT, O_LNOT, - /* misc */ - OPEN_PAREN, CLOSE_PAREN, CTERN, - /* things that don't appear in the opinfo[] table */ - VAR, LIT, END, BAD - }; -#define IS_BINOP(op) (((int)op) >= (int)O_EQ && ((int)op) <= (int)O_COMMA) -#define IS_ASSIGNOP(op) ((int)(op) >= (int)O_ASN && (int)(op) <= (int)O_BORASN) - -enum prec { - P_PRIMARY = 0, /* VAR, LIT, (), ~ ! - + */ - P_MULT, /* * / % */ - P_ADD, /* + - */ - P_SHIFT, /* << >> */ - P_RELATION, /* < <= > >= */ - P_EQUALITY, /* == != */ - P_BAND, /* & */ - P_BXOR, /* ^ */ - P_BOR, /* | */ - P_LAND, /* && */ - P_LOR, /* || */ - P_TERN, /* ?: */ - P_ASSIGN, /* = *= /= %= += -= <<= >>= &= ^= |= */ - P_COMMA /* , */ - }; -#define MAX_PREC P_COMMA - -struct opinfo { - char name[4]; - int len; /* name length */ - enum prec prec; /* precedence: lower is higher */ -}; - -/* Tokens in this table must be ordered so the longest are first - * (eg, += before +). If you change something, change the order - * of enum token too. - */ -static const struct opinfo opinfo[] = { - { "++", 2, P_PRIMARY }, /* before + */ - { "--", 2, P_PRIMARY }, /* before - */ - { "==", 2, P_EQUALITY }, /* before = */ - { "!=", 2, P_EQUALITY }, /* before ! */ - { "=", 1, P_ASSIGN }, /* keep assigns in a block */ - { "*=", 2, P_ASSIGN }, - { "/=", 2, P_ASSIGN }, - { "%=", 2, P_ASSIGN }, - { "+=", 2, P_ASSIGN }, - { "-=", 2, P_ASSIGN }, - { "<<=", 3, P_ASSIGN }, - { ">>=", 3, P_ASSIGN }, - { "&=", 2, P_ASSIGN }, - { "^=", 2, P_ASSIGN }, - { "|=", 2, P_ASSIGN }, - { "<<", 2, P_SHIFT }, - { ">>", 2, P_SHIFT }, - { "<=", 2, P_RELATION }, - { ">=", 2, P_RELATION }, - { "<", 1, P_RELATION }, - { ">", 1, P_RELATION }, - { "&&", 2, P_LAND }, - { "||", 2, P_LOR }, - { "*", 1, P_MULT }, - { "/", 1, P_MULT }, - { "%", 1, P_MULT }, - { "+", 1, P_ADD }, - { "-", 1, P_ADD }, - { "&", 1, P_BAND }, - { "^", 1, P_BXOR }, - { "|", 1, P_BOR }, - { "?", 1, P_TERN }, - { ",", 1, P_COMMA }, - { "~", 1, P_PRIMARY }, - { "!", 1, P_PRIMARY }, - { "(", 1, P_PRIMARY }, - { ")", 1, P_PRIMARY }, - { ":", 1, P_PRIMARY }, - { "", 0, P_PRIMARY } /* end of table */ - }; - - -typedef struct expr_state Expr_state; -struct expr_state { - const char *expression; /* expression being evaluated */ - const char *tokp; /* lexical position */ - enum token tok; /* token from token() */ - int noassign; /* don't do assigns (for ?:,&&,||) */ - struct tbl *val; /* value from token() */ - struct tbl *evaling; /* variable that is being recursively - * expanded (EXPRINEVAL flag set) - */ -}; - -enum error_type { ET_UNEXPECTED, ET_BADLIT, ET_RECURSIVE, - ET_LVALUE, ET_RDONLY, ET_STR }; - -static void evalerr ARGS((Expr_state *es, enum error_type type, - const char *str)) GCC_FUNC_ATTR(noreturn); -static struct tbl *evalexpr ARGS((Expr_state *es, enum prec prec)); -static void token ARGS((Expr_state *es)); -static struct tbl *do_ppmm ARGS((Expr_state *es, enum token op, - struct tbl *vasn, bool_t is_prefix)); -static void assign_check ARGS((Expr_state *es, enum token op, - struct tbl *vasn)); -static struct tbl *tempvar ARGS((void)); -static struct tbl *intvar ARGS((Expr_state *es, struct tbl *vp)); - -/* - * parse and evaluate expression - */ -int -evaluate(expr, rval, error_ok) - const char *expr; - long *rval; - int error_ok; -{ - struct tbl v; - int ret; - - v.flag = DEFINED|INTEGER; - v.type = 0; - ret = v_evaluate(&v, expr, error_ok); - *rval = v.val.i; - return ret; -} - -/* - * parse and evaluate expression, storing result in vp. - */ -int -v_evaluate(vp, expr, error_ok) - struct tbl *vp; - const char *expr; - volatile int error_ok; -{ - struct tbl *v; - Expr_state curstate; - Expr_state * const es = &curstate; - int i; - - /* save state to allow recursive calls */ - curstate.expression = curstate.tokp = expr; - curstate.noassign = 0; - curstate.evaling = (struct tbl *) 0; - - newenv(E_ERRH); - i = ksh_sigsetjmp(e->jbuf, 0); - if (i) { - /* Clear EXPRINEVAL in of any variables we were playing with */ - if (curstate.evaling) - curstate.evaling->flag &= ~EXPRINEVAL; - quitenv(); - if (i == LAEXPR) { - if (error_ok == KSH_RETURN_ERROR) - return 0; - errorf("%s", null); - } - unwind(i); - /*NOTREACHED*/ - } - - token(es); -#if 1 /* ifdef-out to disallow empty expressions to be treated as 0 */ - if (es->tok == END) { - es->tok = LIT; - es->val = tempvar(); - } -#endif /* 0 */ - v = intvar(es, evalexpr(es, MAX_PREC)); - - if (es->tok != END) - evalerr(es, ET_UNEXPECTED, (char *) 0); - - if (vp->flag & INTEGER) - setint_v(vp, v); - else - /* can fail if readonly */ - setstr(vp, str_val(v), error_ok); - - quitenv(); - - return 1; -} - -static void -evalerr(es, type, str) - Expr_state *es; - enum error_type type; - const char *str; -{ - char tbuf[2]; - const char *s; - - switch (type) { - case ET_UNEXPECTED: - switch (es->tok) { - case VAR: - s = es->val->name; - break; - case LIT: - s = str_val(es->val); - break; - case END: - s = "end of expression"; - break; - case BAD: - tbuf[0] = *es->tokp; - tbuf[1] = '\0'; - s = tbuf; - break; - default: - s = opinfo[(int)es->tok].name; - } - warningf(TRUE, "%s: unexpected `%s'", es->expression, s); - break; - - case ET_BADLIT: - warningf(TRUE, "%s: bad number `%s'", es->expression, str); - break; - - case ET_RECURSIVE: - warningf(TRUE, "%s: expression recurses on parameter `%s'", - es->expression, str); - break; - - case ET_LVALUE: - warningf(TRUE, "%s: %s requires lvalue", - es->expression, str); - break; - - case ET_RDONLY: - warningf(TRUE, "%s: %s applied to read only variable", - es->expression, str); - break; - - default: /* keep gcc happy */ - case ET_STR: - warningf(TRUE, "%s: %s", es->expression, str); - break; - } - unwind(LAEXPR); -} - -static struct tbl * -evalexpr(es, prec) - Expr_state *es; - enum prec prec; -{ - struct tbl *vl, UNINITIALIZED(*vr), *vasn; - enum token op; - long UNINITIALIZED(res); - - if (prec == P_PRIMARY) { - op = es->tok; - if (op == O_BNOT || op == O_LNOT || op == O_MINUS - || op == O_PLUS) - { - token(es); - vl = intvar(es, evalexpr(es, P_PRIMARY)); - if (op == O_BNOT) - vl->val.i = ~vl->val.i; - else if (op == O_LNOT) - vl->val.i = !vl->val.i; - else if (op == O_MINUS) - vl->val.i = -vl->val.i; - /* op == O_PLUS is a no-op */ - } else if (op == OPEN_PAREN) { - token(es); - vl = evalexpr(es, MAX_PREC); - if (es->tok != CLOSE_PAREN) - evalerr(es, ET_STR, "missing )"); - token(es); - } else if (op == O_PLUSPLUS || op == O_MINUSMINUS) { - token(es); - vl = do_ppmm(es, op, es->val, TRUE); - token(es); - } else if (op == VAR || op == LIT) { - vl = es->val; - token(es); - } else { - evalerr(es, ET_UNEXPECTED, (char *) 0); - /*NOTREACHED*/ - } - if (es->tok == O_PLUSPLUS || es->tok == O_MINUSMINUS) { - vl = do_ppmm(es, es->tok, vl, FALSE); - token(es); - } - return vl; - } - vl = evalexpr(es, ((int) prec) - 1); - for (op = es->tok; IS_BINOP(op) && opinfo[(int) op].prec == prec; - op = es->tok) - { - token(es); - vasn = vl; - if (op != O_ASN) /* vl may not have a value yet */ - vl = intvar(es, vl); - if (IS_ASSIGNOP(op)) { - assign_check(es, op, vasn); - vr = intvar(es, evalexpr(es, P_ASSIGN)); - } else if (op != O_TERN && op != O_LAND && op != O_LOR) - vr = intvar(es, evalexpr(es, ((int) prec) - 1)); - if ((op == O_DIV || op == O_MOD || op == O_DIVASN - || op == O_MODASN) && vr->val.i == 0) - { - if (es->noassign) - vr->val.i = 1; - else - evalerr(es, ET_STR, "zero divisor"); - } - switch ((int) op) { - case O_TIMES: - case O_TIMESASN: - res = vl->val.i * vr->val.i; - break; - case O_DIV: - case O_DIVASN: - res = vl->val.i / vr->val.i; - break; - case O_MOD: - case O_MODASN: - res = vl->val.i % vr->val.i; - break; - case O_PLUS: - case O_PLUSASN: - res = vl->val.i + vr->val.i; - break; - case O_MINUS: - case O_MINUSASN: - res = vl->val.i - vr->val.i; - break; - case O_LSHIFT: - case O_LSHIFTASN: - res = vl->val.i << vr->val.i; - break; - case O_RSHIFT: - case O_RSHIFTASN: - res = vl->val.i >> vr->val.i; - break; - case O_LT: - res = vl->val.i < vr->val.i; - break; - case O_LE: - res = vl->val.i <= vr->val.i; - break; - case O_GT: - res = vl->val.i > vr->val.i; - break; - case O_GE: - res = vl->val.i >= vr->val.i; - break; - case O_EQ: - res = vl->val.i == vr->val.i; - break; - case O_NE: - res = vl->val.i != vr->val.i; - break; - case O_BAND: - case O_BANDASN: - res = vl->val.i & vr->val.i; - break; - case O_BXOR: - case O_BXORASN: - res = vl->val.i ^ vr->val.i; - break; - case O_BOR: - case O_BORASN: - res = vl->val.i | vr->val.i; - break; - case O_LAND: - if (!vl->val.i) - es->noassign++; - vr = intvar(es, evalexpr(es, ((int) prec) - 1)); - res = vl->val.i && vr->val.i; - if (!vl->val.i) - es->noassign--; - break; - case O_LOR: - if (vl->val.i) - es->noassign++; - vr = intvar(es, evalexpr(es, ((int) prec) - 1)); - res = vl->val.i || vr->val.i; - if (vl->val.i) - es->noassign--; - break; - case O_TERN: - { - int ex = vl->val.i != 0; - if (!ex) - es->noassign++; - vl = evalexpr(es, MAX_PREC); - if (!ex) - es->noassign--; - if (es->tok != CTERN) - evalerr(es, ET_STR, "missing :"); - token(es); - if (ex) - es->noassign++; - vr = evalexpr(es, P_TERN); - if (ex) - es->noassign--; - vl = ex ? vl : vr; - } - break; - case O_ASN: - res = vr->val.i; - break; - case O_COMMA: - res = vr->val.i; - break; - } - if (IS_ASSIGNOP(op)) { - vr->val.i = res; - if (vasn->flag & INTEGER) - setint_v(vasn, vr); - else - setint(vasn, res); - vl = vr; - } else if (op != O_TERN) - vl->val.i = res; - } - return vl; -} - -static void -token(es) - Expr_state *es; -{ - const char *cp; - int c; - char *tvar; - - /* skip white space */ - for (cp = es->tokp; (c = *cp), isspace((unsigned char)c); cp++) - ; - es->tokp = cp; - - if (c == '\0') - es->tok = END; - else if (letter(c)) { - for (; letnum(c); c = *cp) - cp++; - if (c == '[') { - int len; - - len = array_ref_len(cp); - if (len == 0) - evalerr(es, ET_STR, "missing ]"); - cp += len; - } -#ifdef KSH - else if (c == '(' /*)*/ ) { - /* todo: add math functions (all take single argument): - * abs acos asin atan cos cosh exp int log sin sinh sqrt - * tan tanh - */ - ; - } -#endif /* KSH */ - if (es->noassign) { - es->val = tempvar(); - es->val->flag |= EXPRLVALUE; - } else { - tvar = str_nsave(es->tokp, cp - es->tokp, ATEMP); - es->val = global(tvar); - afree(tvar, ATEMP); - } - es->tok = VAR; - } else if (digit(c)) { - for (; c != '_' && (letnum(c) || c == '#'); c = *cp++) - ; - tvar = str_nsave(es->tokp, --cp - es->tokp, ATEMP); - es->val = tempvar(); - es->val->flag &= ~INTEGER; - es->val->type = 0; - es->val->val.s = tvar; - if (setint_v(es->val, es->val) == NULL) - evalerr(es, ET_BADLIT, tvar); - afree(tvar, ATEMP); - es->tok = LIT; - } else { - int i, n0; - - for (i = 0; (n0 = opinfo[i].name[0]); i++) - if (c == n0 - && strncmp(cp, opinfo[i].name, opinfo[i].len) == 0) - { - es->tok = (enum token) i; - cp += opinfo[i].len; - break; - } - if (!n0) - es->tok = BAD; - } - es->tokp = cp; -} - -/* Do a ++ or -- operation */ -static struct tbl * -do_ppmm(es, op, vasn, is_prefix) - Expr_state *es; - enum token op; - struct tbl *vasn; - bool_t is_prefix; -{ - struct tbl *vl; - int oval; - - assign_check(es, op, vasn); - - vl = intvar(es, vasn); - oval = op == O_PLUSPLUS ? vl->val.i++ : vl->val.i--; - if (vasn->flag & INTEGER) - setint_v(vasn, vl); - else - setint(vasn, vl->val.i); - if (!is_prefix) /* undo the inc/dec */ - vl->val.i = oval; - - return vl; -} - -static void -assign_check(es, op, vasn) - Expr_state *es; - enum token op; - struct tbl *vasn; -{ - if (vasn->name[0] == '\0' && !(vasn->flag & EXPRLVALUE)) - evalerr(es, ET_LVALUE, opinfo[(int) op].name); - else if (vasn->flag & RDONLY) - evalerr(es, ET_RDONLY, opinfo[(int) op].name); -} - -static struct tbl * -tempvar() -{ - register struct tbl *vp; - - vp = (struct tbl*) alloc(sizeof(struct tbl), ATEMP); - vp->flag = ISSET|INTEGER; - vp->type = 0; - vp->areap = ATEMP; - vp->val.i = 0; - vp->name[0] = '\0'; - return vp; -} - -/* cast (string) variable to temporary integer variable */ -static struct tbl * -intvar(es, vp) - Expr_state *es; - struct tbl *vp; -{ - struct tbl *vq; - - /* try to avoid replacing a temp var with another temp var */ - if (vp->name[0] == '\0' - && (vp->flag & (ISSET|INTEGER|EXPRLVALUE)) == (ISSET|INTEGER)) - return vp; - - vq = tempvar(); - if (setint_v(vq, vp) == NULL) { - if (vp->flag & EXPRINEVAL) - evalerr(es, ET_RECURSIVE, vp->name); - es->evaling = vp; - vp->flag |= EXPRINEVAL; - v_evaluate(vq, str_val(vp), KSH_UNWIND_ERROR); - vp->flag &= ~EXPRINEVAL; - es->evaling = (struct tbl *) 0; - } - return vq; -} diff --git a/bin/ksh/history.c b/bin/ksh/history.c deleted file mode 100644 index 1758464c7..000000000 --- a/bin/ksh/history.c +++ /dev/null @@ -1,1225 +0,0 @@ -/* $NetBSD: history.c,v 1.11 2011/08/31 16:24:54 plunky Exp $ */ - -/* - * command history - * - * only implements in-memory history. - */ - -/* - * This file contains - * a) the original in-memory history mechanism - * b) a simple file saving history mechanism done by sjg@zen - * define EASY_HISTORY to get this - * c) a more complicated mechanism done by pc@hillside.co.uk - * that more closely follows the real ksh way of doing - * things. You need to have the mmap system call for this - * to work on your system - */ -#include - -#ifndef lint -__RCSID("$NetBSD: history.c,v 1.11 2011/08/31 16:24:54 plunky Exp $"); -#endif - - -#include "sh.h" -#include "ksh_stat.h" - -#ifdef HISTORY -# ifdef EASY_HISTORY - -# ifndef HISTFILE -# ifdef OS2 -# define HISTFILE "history.ksh" -# else /* OS2 */ -# define HISTFILE ".pdksh_history" -# endif /* OS2 */ -# endif - -# else -/* Defines and includes for the complicated case */ - -# include -# include - -/* - * variables for handling the data file - */ -static int histfd; -static int hsize; - -static int hist_count_lines ARGS((unsigned char *, int)); -static int hist_shrink ARGS((unsigned char *, int)); -static unsigned char *hist_skip_back ARGS((unsigned char *,int *,int)); -static void histload ARGS((Source *, unsigned char *, int)); -static void histinsert ARGS((Source *, int, unsigned char *)); -static void writehistfile ARGS((int, char *)); -static int sprinkle ARGS((int)); - -# ifdef MAP_FILE -# define MAP_FLAGS (MAP_FILE|MAP_PRIVATE) -# else -# define MAP_FLAGS MAP_PRIVATE -# endif - -# endif /* of EASY_HISTORY */ - -static int hist_execute ARGS((char *)); -static int hist_replace ARGS((char **, const char *, const char *, int)); -static char **hist_get ARGS((const char *, int, int)); -static char **hist_get_newest ARGS((int)); -static char **hist_get_oldest ARGS((void)); -static void histbackup ARGS((void)); - -static char **current; /* current position in history[] */ -static int curpos; /* current index in history[] */ -static char *hname; /* current name of history file */ -static int hstarted; /* set after hist_init() called */ -static Source *hist_source; - - -int -c_fc(wp) - char **wp; -{ - struct shf *shf; - struct temp UNINITIALIZED(*tf); - char *p, *editor = (char *) 0; - int gflag = 0, lflag = 0, nflag = 0, sflag = 0, rflag = 0; - int optc; - char *first = (char *) 0, *last = (char *) 0; - char **hfirst, **hlast, **hp; - - if (hist_source == NULL) { - bi_errorf("not interactive"); - return 1; - } - - while ((optc = ksh_getopt(wp, &builtin_opt, "e:glnrs0,1,2,3,4,5,6,7,8,9,")) != EOF) - switch (optc) { - case 'e': - p = builtin_opt.optarg; - if (strcmp(p, "-") == 0) - sflag++; - else { - size_t len = strlen(p) + 4; - editor = str_nsave(p, len, ATEMP); - strlcat(editor, " $_", len); - } - break; - case 'g': /* non-at&t ksh */ - gflag++; - break; - case 'l': - lflag++; - break; - case 'n': - nflag++; - break; - case 'r': - rflag++; - break; - case 's': /* posix version of -e - */ - sflag++; - break; - /* kludge city - accept -num as -- -num (kind of) */ - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - p = shf_smprintf("-%c%s", - optc, builtin_opt.optarg); - if (!first) - first = p; - else if (!last) - last = p; - else { - bi_errorf("too many arguments"); - return 1; - } - break; - case '?': - return 1; - } - wp += builtin_opt.optind; - - /* Substitute and execute command */ - if (sflag) { - char *pat = (char *) 0, *rep = (char *) 0; - - if (editor || lflag || nflag || rflag) { - bi_errorf("can't use -e, -l, -n, -r with -s (-e -)"); - return 1; - } - - /* Check for pattern replacement argument */ - if (*wp && **wp && (p = strchr(*wp + 1, '='))) { - pat = str_save(*wp, ATEMP); - p = pat + (p - *wp); - *p++ = '\0'; - rep = p; - wp++; - } - /* Check for search prefix */ - if (!first && (first = *wp)) - wp++; - if (last || *wp) { - bi_errorf("too many arguments"); - return 1; - } - - hp = first ? hist_get(first, FALSE, FALSE) - : hist_get_newest(FALSE); - if (!hp) - return 1; - return hist_replace(hp, pat, rep, gflag); - } - - if (editor && (lflag || nflag)) { - bi_errorf("can't use -l, -n with -e"); - return 1; - } - - if (!first && (first = *wp)) - wp++; - if (!last && (last = *wp)) - wp++; - if (*wp) { - bi_errorf("too many arguments"); - return 1; - } - if (!first) { - hfirst = lflag ? hist_get("-16", TRUE, TRUE) - : hist_get_newest(FALSE); - if (!hfirst) - return 1; - /* can't fail if hfirst didn't fail */ - hlast = hist_get_newest(FALSE); - } else { - /* POSIX says not an error if first/last out of bounds - * when range is specified; at&t ksh and pdksh allow out of - * bounds for -l as well. - */ - hfirst = hist_get(first, (lflag || last) ? TRUE : FALSE, - lflag ? TRUE : FALSE); - if (!hfirst) - return 1; - hlast = last ? hist_get(last, TRUE, lflag ? TRUE : FALSE) - : (lflag ? hist_get_newest(FALSE) : hfirst); - if (!hlast) - return 1; - } - if (hfirst > hlast) { - char **temp; - - temp = hfirst; hfirst = hlast; hlast = temp; - rflag = !rflag; /* POSIX */ - } - - /* List history */ - if (lflag) { - char *s, *t; - const char *nfmt = nflag ? "\t" : "%d\t"; - - for (hp = rflag ? hlast : hfirst; - hp >= hfirst && hp <= hlast; hp += rflag ? -1 : 1) - { - shf_fprintf(shl_stdout, nfmt, - hist_source->line - (int) (histptr - hp)); - /* print multi-line commands correctly */ - for (s = *hp; (t = strchr(s, '\n')); s = t) - shf_fprintf(shl_stdout, "%.*s\t", ++t - s, s); - shf_fprintf(shl_stdout, "%s\n", s); - } - shf_flush(shl_stdout); - return 0; - } - - /* Run editor on selected lines, then run resulting commands */ - - tf = maketemp(ATEMP, TT_HIST_EDIT, &e->temps); - if (!(shf = tf->shf)) { - bi_errorf("cannot create temp file %s - %s", - tf->name, strerror(errno)); - return 1; - } - for (hp = rflag ? hlast : hfirst; - hp >= hfirst && hp <= hlast; hp += rflag ? -1 : 1) - shf_fprintf(shf, "%s\n", *hp); - if (shf_close(shf) == EOF) { - bi_errorf("error writing temporary file - %s", strerror(errno)); - return 1; - } - - /* Ignore setstr errors here (arbitrary) */ - setstr(local("_", FALSE), tf->name, KSH_RETURN_ERROR); - - /* XXX: source should not get trashed by this.. */ - { - Source *sold = source; - int ret; - - ret = command(editor ? editor : "${FCEDIT:-/bin/ed} $_"); - source = sold; - if (ret) - return ret; - } - - { - struct stat statb; - XString xs; - char *xp; - int n; - - if (!(shf = shf_open(tf->name, O_RDONLY, 0, 0))) { - bi_errorf("cannot open temp file %s", tf->name); - return 1; - } - - n = fstat(shf_fileno(shf), &statb) < 0 ? 128 - : statb.st_size + 1; - Xinit(xs, xp, n, hist_source->areap); - while ((n = shf_read(xp, Xnleft(xs, xp), shf)) > 0) { - xp += n; - if (Xnleft(xs, xp) <= 0) - XcheckN(xs, xp, Xlength(xs, xp)); - } - if (n < 0) { - bi_errorf("error reading temp file %s - %s", - tf->name, strerror(shf_errno(shf))); - shf_close(shf); - return 1; - } - shf_close(shf); - *xp = '\0'; - strip_nuls(Xstring(xs, xp), Xlength(xs, xp)); - return hist_execute(Xstring(xs, xp)); - } -} - -/* Save cmd in history, execute cmd (cmd gets trashed) */ -static int -hist_execute(cmd) - char *cmd; -{ - Source *sold; - int ret; - char *p, *q; - - histbackup(); - - for (p = cmd; p; p = q) { - if ((q = strchr(p, '\n'))) { - *q++ = '\0'; /* kill the newline */ - if (!*q) /* ignore trailing newline */ - q = (char *) 0; - } -#ifdef EASY_HISTORY - if (p != cmd) - histappend(p, TRUE); - else -#endif /* EASY_HISTORY */ - histsave(++(hist_source->line), p, 1); - - shellf("%s\n", p); /* POSIX doesn't say this is done... */ - if ((p = q)) /* restore \n (trailing \n not restored) */ - q[-1] = '\n'; - } - - /* Commands are executed here instead of pushing them onto the - * input 'cause posix says the redirection and variable assignments - * in - * X=y fc -e - 42 2> /dev/null - * are to effect the repeated commands environment. - */ - /* XXX: source should not get trashed by this.. */ - sold = source; - ret = command(cmd); - source = sold; - return ret; -} - -static int -hist_replace(hp, pat, rep, globalv) - char **hp; - const char *pat; - const char *rep; - int globalv; -{ - char *line; - - if (!pat) - line = str_save(*hp, ATEMP); - else { - char *s, *s1; - int pat_len = strlen(pat); - int rep_len = strlen(rep); - int len; - XString xs; - char *xp; - int any_subst = 0; - - Xinit(xs, xp, 128, ATEMP); - for (s = *hp; (s1 = strstr(s, pat)) - && (!any_subst || globalv) ; s = s1 + pat_len) - { - any_subst = 1; - len = s1 - s; - XcheckN(xs, xp, len + rep_len); - memcpy(xp, s, len); /* first part */ - xp += len; - memcpy(xp, rep, rep_len); /* replacement */ - xp += rep_len; - } - if (!any_subst) { - bi_errorf("substitution failed"); - return 1; - } - len = strlen(s) + 1; - XcheckN(xs, xp, len); - memcpy(xp, s, len); - xp += len; - line = Xclose(xs, xp); - } - return hist_execute(line); -} - -/* - * get pointer to history given pattern - * pattern is a number or string - */ -static char ** -hist_get(str, approx, allow_cur) - const char *str; - int approx; - int allow_cur; -{ - char **hp = (char **) 0; - int n; - - if (getn(str, &n)) { - hp = histptr + (n < 0 ? n : (n - hist_source->line)); - if (hp < histlist) { - if (approx) - hp = hist_get_oldest(); - else { - bi_errorf("%s: not in history", str); - hp = (char **) 0; - } - } else if (hp > histptr) { - if (approx) - hp = hist_get_newest(allow_cur); - else { - bi_errorf("%s: not in history", str); - hp = (char **) 0; - } - } else if (!allow_cur && hp == histptr) { - bi_errorf("%s: invalid range", str); - hp = (char **) 0; - } - } else { - int anchored = *str == '?' ? (++str, 0) : 1; - - /* the -1 is to avoid the current fc command */ - n = findhist(histptr - histlist - 1, 0, str, anchored); - if (n < 0) { - bi_errorf("%s: not in history", str); - hp = (char **) 0; - } else - hp = &histlist[n]; - } - return hp; -} - -/* Return a pointer to the newest command in the history */ -static char ** -hist_get_newest(allow_cur) - int allow_cur; -{ - if (histptr < histlist || (!allow_cur && histptr == histlist)) { - bi_errorf("no history (yet)"); - return (char **) 0; - } - if (allow_cur) - return histptr; - return histptr - 1; -} - -/* Return a pointer to the newest command in the history */ -static char ** -hist_get_oldest() -{ - if (histptr <= histlist) { - bi_errorf("no history (yet)"); - return (char **) 0; - } - return histlist; -} - -/******************************/ -/* Back up over last histsave */ -/******************************/ -static void -histbackup() -{ - static int last_line = -1; - - if (histptr >= histlist && last_line != hist_source->line) { - hist_source->line--; - afree((void*)*histptr, APERM); - histptr--; - last_line = hist_source->line; - } -} - -/* - * Return the current position. - */ -char ** -histpos() -{ - return current; -} - -int -histN() -{ - return curpos; -} - -int -histnum(n) - int n; -{ - int last = histptr - histlist; - - if (n < 0 || n >= last) { - current = histptr; - curpos = last; - return last; - } else { - current = &histlist[n]; - curpos = n; - return n; - } -} - -/* - * This will become unnecessary if hist_get is modified to allow - * searching from positions other than the end, and in either - * direction. - */ -int -findhist(start, fwd, str, anchored) - int start; - int fwd; - const char *str; - int anchored; -{ - char **hp; - int maxhist = histptr - histlist; - int incr = fwd ? 1 : -1; - int len = strlen(str); - - if (start < 0 || start >= maxhist) - start = maxhist; - - hp = &histlist[start]; - for (; hp >= histlist && hp <= histptr; hp += incr) - if ((anchored && strncmp(*hp, str, len) == 0) - || (!anchored && strstr(*hp, str))) - return hp - histlist; - - return -1; -} - -/* - * set history - * this means reallocating the dataspace - */ -void -sethistsize(n) - int n; -{ - if (n > 0 && n != histsize) { - int cursize = histptr - histlist; - - /* save most recent history */ - if (n < cursize) { - memmove(histlist, histptr - n, n * sizeof(char *)); - cursize = n; - } - - histlist = (char **)aresize(histlist, n*sizeof(char *), APERM); - - histsize = n; - histptr = histlist + cursize; - } -} - -/* - * set history file - * This can mean reloading/resetting/starting history file - * maintenance - */ -void -sethistfile(name) - const char *name; -{ - /* if not started then nothing to do */ - if (hstarted == 0) - return; - - /* if the name is the same as the name we have */ - if (hname && strcmp(hname, name) == 0) - return; - - /* - * its a new name - possibly - */ -# ifdef EASY_HISTORY - if (hname) { - afree(hname, APERM); - hname = NULL; - } -# else - if (histfd) { - /* yes the file is open */ - (void) close(histfd); - histfd = 0; - hsize = 0; - afree(hname, APERM); - hname = NULL; - /* let's reset the history */ - histptr = histlist - 1; - hist_source->line = 0; - } -# endif - - hist_init(hist_source); -} - -/* - * initialise the history vector - */ -void -init_histvec() -{ - if (histlist == NULL) { - histsize = HISTORYSIZE; - histlist = (char **)alloc(histsize*sizeof (char *), APERM); - histptr = histlist - 1; - } -} - -# ifdef EASY_HISTORY -/* - * save command in history - */ -void -histsave(lno, cmd, dowrite) - int lno; /* ignored (compatibility with COMPLEX_HISTORY) */ - const char *cmd; - int dowrite; /* ignored (compatibility with COMPLEX_HISTORY) */ -{ - register char **hp = histptr; - char *cp; - - if (++hp >= histlist + histsize) { /* remove oldest command */ - afree((void*)histlist[0], APERM); - memmove(histlist, histlist + 1, - sizeof(histlist[0]) * (histsize - 1)); - hp = &histlist[histsize - 1]; - } - *hp = str_save(cmd, APERM); - /* trash trailing newline but allow imbedded newlines */ - cp = *hp + strlen(*hp); - if (cp > *hp && cp[-1] == '\n') - cp[-1] = '\0'; - histptr = hp; -} - -/* - * Append an entry to the last saved command. Used for multiline - * commands - */ -void -histappend(cmd, nl_separate) - const char *cmd; - int nl_separate; -{ - int hlen, clen; - char *p; - - hlen = strlen(*histptr); - clen = strlen(cmd); - if (clen > 0 && cmd[clen-1] == '\n') - clen--; - p = *histptr = (char *) aresize(*histptr, hlen + clen + 2, APERM); - p += hlen; - if (nl_separate) - *p++ = '\n'; - memcpy(p, cmd, clen); - p[clen] = '\0'; -} - -/* - * 92-04-25 - * A simple history file implementation. - * At present we only save the history when we exit. - * This can cause problems when there are multiple shells are - * running under the same user-id. The last shell to exit gets - * to save its history. - */ -void -hist_init(s) - Source *s; -{ - char *f; - FILE *fh; - - if (Flag(FTALKING) == 0) - return; - - hstarted = 1; - - hist_source = s; - - if ((f = str_val(global("HISTFILE"))) == NULL || *f == '\0') { -# if 1 /* Don't use history file unless the user asks for it */ - hname = NULL; - return; -# else - char *home = str_val(global("HOME")); - int len; - - if (home == NULL) - home = null; - f = HISTFILE; - hname = alloc(len = strlen(home) + strlen(f) + 2, APERM); - shf_snprintf(hname, len, "%s/%s", home, f); -# endif - } else - hname = str_save(f, APERM); - - if ((fh = fopen(hname, "r"))) { - int pos = 0, nread = 0; - int contin = 0; /* continuation of previous command */ - char *end; - char hline[LINE + 1]; - - while (1) { - if (pos >= nread) { - pos = 0; - nread = fread(hline, 1, LINE, fh); - if (nread <= 0) - break; - hline[nread] = '\0'; - } - end = strchr(hline + pos, 0); /* will always succeed */ - if (contin) - histappend(hline + pos, 0); - else { - hist_source->line++; - histsave(0, hline + pos, 0); - } - pos = end - hline + 1; - contin = end == &hline[nread]; - } - fclose(fh); - } -} - -/* - * save our history. - * We check that we do not have more than we are allowed. - * If the history file is read-only we do nothing. - * Handy for having all shells start with a useful history set. - */ - -void -hist_finish() -{ - static int once; - int fd; -#if defined(__minix) - /* LSC: FIXME: Minix doesn't implement O_EXLOCK yet. */ - int rc; -#endif - FILE *fh; - register int i; - register char **hp; - - if (once++) - return; - if (hname == NULL || hname[0] == 0) - return; - - /* check how many we have */ - i = histptr - histlist; - if (i >= histsize) - hp = &histptr[-histsize]; - else - hp = histlist; - - fd = open(hname, O_WRONLY | O_CREAT | O_TRUNC | O_EXLOCK, 0777); -#if defined(__minix) - do { - rc = flock(fd, LOCK_EX); - if (rc == -1 && errno != EINTR) - return; - } while (rc == -1 && errno == EINTR); /* if interrupted, try again. */ -#endif - - /* Remove anything written before we got the lock */ - ftruncate(fd, 0); - if (fd >= 0 && (fh = fdopen(fd, "w"))) { - for (i = 0; hp + i <= histptr && hp[i]; i++) - fprintf(fh, "%s%c", hp[i], '\0'); -#if defined(__minix) - flock(fd, LOCK_UN); -#endif - fclose(fh); - } -} - -# else /* EASY_HISTORY */ - -/* - * Routines added by Peter Collinson BSDI(Europe)/Hillside Systems to - * a) permit HISTSIZE to control number of lines of history stored - * b) maintain a physical history file - * - * It turns out that there is a lot of ghastly hackery here - */ - - -/* - * save command in history - */ -void -histsave(lno, cmd, dowrite) - int lno; - const char *cmd; - int dowrite; -{ - register char **hp; - char *c, *cp; - - c = str_save(cmd, APERM); - if ((cp = strchr(c, '\n')) != NULL) - *cp = '\0'; - - if (histfd && dowrite) - writehistfile(lno, c); - - hp = histptr; - - if (++hp >= histlist + histsize) { /* remove oldest command */ - afree((void*)*histlist, APERM); - for (hp = histlist; hp < histlist + histsize - 1; hp++) - hp[0] = hp[1]; - } - *hp = c; - histptr = hp; -} - -/* - * Write history data to a file nominated by HISTFILE - * if HISTFILE is unset then history still happens, but - * the data is not written to a file - * All copies of ksh looking at the file will maintain the - * same history. This is ksh behaviour. - * - * This stuff uses mmap() - * if your system ain't got it - then you'll have to undef HISTORYFILE - */ - -/* - * Open a history file - * Format is: - * Bytes 1, 2: HMAGIC - just to check that we are dealing with - * the correct object - * Then follows a number of stored commands - * Each command is - * - */ -# define HMAGIC1 0xab -# define HMAGIC2 0xcd -# define COMMAND 0xff - -void -hist_init(s) - Source *s; -{ - unsigned char *base; - int lines; - int fd; - - if (Flag(FTALKING) == 0) - return; - - hstarted = 1; - - hist_source = s; - - hname = str_val(global("HISTFILE")); - if (hname == NULL) - return; - hname = str_save(hname, APERM); - - retry: - /* we have a file and are interactive */ - if ((fd = open(hname, O_RDWR|O_CREAT|O_APPEND, 0600)) < 0) - return; - - histfd = savefd(fd, 0); - - (void) flock(histfd, LOCK_EX); - - hsize = lseek(histfd, 0L, SEEK_END); - - if (hsize == 0) { - /* add magic */ - if (sprinkle(histfd)) { - hist_finish(); - return; - } - } - else if (hsize > 0) { - /* - * we have some data - */ - base = (unsigned char *)mmap(0, hsize, PROT_READ, MAP_FLAGS, histfd, 0); - /* - * check on its validity - */ - if (base == MAP_FAILED || *base != HMAGIC1 || base[1] != HMAGIC2) { - if (base != MAP_FAILED) - munmap((caddr_t)base, hsize); - hist_finish(); - unlink(hname); - goto retry; - } - if (hsize > 2) { - lines = hist_count_lines(base+2, hsize-2); - if (lines > histsize) { - /* we need to make the file smaller */ - if (hist_shrink(base, hsize)) - unlink(hname); - munmap((caddr_t)base, hsize); - hist_finish(); - goto retry; - } - } - histload(hist_source, base+2, hsize-2); - munmap((caddr_t)base, hsize); - } - (void) flock(histfd, LOCK_UN); - hsize = lseek(histfd, 0L, SEEK_END); -} - -typedef enum state { - shdr, /* expecting a header */ - sline, /* looking for a null byte to end the line */ - sn1, /* bytes 1 to 4 of a line no */ - sn2, sn3, sn4 -} State; - -static int -hist_count_lines(base, bytes) - register unsigned char *base; - register int bytes; -{ - State state = shdr; - int lines = 0; - - while (bytes--) { - switch (state) - { - case shdr: - if (*base == COMMAND) - state = sn1; - break; - case sn1: - state = sn2; break; - case sn2: - state = sn3; break; - case sn3: - state = sn4; break; - case sn4: - state = sline; break; - case sline: - if (*base == '\0') - lines++, state = shdr; - } - base++; - } - return lines; -} - -/* - * Shrink the history file to histsize lines - */ -static int -hist_shrink(oldbase, oldbytes) - unsigned char *oldbase; - int oldbytes; -{ - int fd; - char nfile[1024]; - struct stat statb; - unsigned char *nbase = oldbase; - int nbytes = oldbytes; - - nbase = hist_skip_back(nbase, &nbytes, histsize); - if (nbase == NULL) - return 1; - if (nbase == oldbase) - return 0; - - /* - * create temp file - */ - (void) shf_snprintf(nfile, sizeof(nfile), "%s.%d", hname, procpid); - if ((fd = creat(nfile, 0600)) < 0) - return 1; - - if (sprinkle(fd)) { - close(fd); - unlink(nfile); - return 1; - } - if (write(fd, nbase, nbytes) != nbytes) { - close(fd); - unlink(nfile); - return 1; - } - /* - * worry about who owns this file - */ - if (fstat(histfd, &statb) >= 0) - fchown(fd, statb.st_uid, statb.st_gid); - close(fd); - - /* - * rename - */ - if (rename(nfile, hname) < 0) - return 1; - return 0; -} - - -/* - * find a pointer to the data `no' back from the end of the file - * return the pointer and the number of bytes left - */ -static unsigned char * -hist_skip_back(base, bytes, no) - unsigned char *base; - int *bytes; - int no; -{ - register int lines = 0; - register unsigned char *ep; - - for (ep = base + *bytes; --ep > base; ) { - /* this doesn't really work: the 4 byte line number that is - * encoded after the COMMAND byte can itself contain the - * COMMAND byte.... - */ - for (; ep > base && *ep != COMMAND; ep--) - ; - if (ep == base) - break; - if (++lines == no) { - *bytes = *bytes - ((char *)ep - (char *)base); - return ep; - } - } - return NULL; -} - -/* - * load the history structure from the stored data - */ -static void -histload(s, base, bytes) - Source *s; - register unsigned char *base; - register int bytes; -{ - State state; - int lno = 0; - unsigned char *line = NULL; - - for (state = shdr; bytes-- > 0; base++) { - switch (state) { - case shdr: - if (*base == COMMAND) - state = sn1; - break; - case sn1: - lno = (((*base)&0xff)<<24); - state = sn2; - break; - case sn2: - lno |= (((*base)&0xff)<<16); - state = sn3; - break; - case sn3: - lno |= (((*base)&0xff)<<8); - state = sn4; - break; - case sn4: - lno |= (*base)&0xff; - line = base+1; - state = sline; - break; - case sline: - if (*base == '\0') { - /* worry about line numbers */ - if (histptr >= histlist && lno-1 != s->line) { - /* a replacement ? */ - histinsert(s, lno, line); - } - else { - s->line = lno; - histsave(lno, (char *)line, 0); - } - state = shdr; - } - } - } -} - -/* - * Insert a line into the history at a specified number - */ -static void -histinsert(s, lno, line) - Source *s; - int lno; - unsigned char *line; -{ - register char **hp; - - if (lno >= s->line-(histptr-histlist) && lno <= s->line) { - hp = &histptr[lno-s->line]; - if (*hp) - afree((void*)*hp, APERM); - *hp = str_save((char *)line, APERM); - } -} - -/* - * write a command to the end of the history file - * This *MAY* seem easy but it's also necessary to check - * that the history file has not changed in size. - * If it has - then some other shell has written to it - * and we should read those commands to update our history - */ -static void -writehistfile(lno, cmd) - int lno; - char *cmd; -{ - int sizenow; - unsigned char *base; - unsigned char *new; - int bytes; - unsigned char hdr[5]; - - (void) flock(histfd, LOCK_EX); - sizenow = lseek(histfd, 0L, SEEK_END); - if (sizenow != hsize) { - /* - * Things have changed - */ - if (sizenow > hsize) { - /* someone has added some lines */ - bytes = sizenow - hsize; - base = (unsigned char *)mmap(0, sizenow, PROT_READ, MAP_FLAGS, histfd, 0); - if (base == MAP_FAILED) - goto bad; - new = base + hsize; - if (*new != COMMAND) { - munmap((caddr_t)base, sizenow); - goto bad; - } - hist_source->line--; - histload(hist_source, new, bytes); - hist_source->line++; - lno = hist_source->line; - munmap((caddr_t)base, sizenow); - hsize = sizenow; - } else { - /* it has shrunk */ - /* but to what? */ - /* we'll give up for now */ - goto bad; - } - } - /* - * we can write our bit now - */ - hdr[0] = COMMAND; - hdr[1] = (lno>>24)&0xff; - hdr[2] = (lno>>16)&0xff; - hdr[3] = (lno>>8)&0xff; - hdr[4] = lno&0xff; - (void) write(histfd, hdr, 5); - (void) write(histfd, cmd, strlen(cmd)+1); - hsize = lseek(histfd, 0L, SEEK_END); - (void) flock(histfd, LOCK_UN); - return; -bad: - hist_finish(); -} - -void -hist_finish() -{ - (void) flock(histfd, LOCK_UN); - (void) close(histfd); - histfd = 0; -} - -/* - * add magic to the history file - */ -static int -sprinkle(fd) - int fd; -{ - static unsigned char mag[] = { HMAGIC1, HMAGIC2 }; - - return(write(fd, mag, 2) != 2); -} - -# endif -#else /* HISTORY */ - -/* No history to be compiled in: dummy routines to avoid lots more ifdefs */ -void -init_histvec() -{ -} -void -hist_init(s) - Source *s; -{ -} -void -hist_finish() -{ -} -void -histsave(lno, cmd, dowrite) - int lno; - const char *cmd; - int dowrite; -{ - errorf("history not enabled"); -} -#endif /* HISTORY */ diff --git a/bin/ksh/io.c b/bin/ksh/io.c deleted file mode 100644 index b8b3c603b..000000000 --- a/bin/ksh/io.c +++ /dev/null @@ -1,568 +0,0 @@ -/* $NetBSD: io.c,v 1.9 2005/06/26 19:09:00 christos Exp $ */ - -/* - * shell buffered IO and formatted output - */ -#include - -#ifndef lint -__RCSID("$NetBSD: io.c,v 1.9 2005/06/26 19:09:00 christos Exp $"); -#endif - - -#include -#include "sh.h" -#include "ksh_stat.h" - -static int initio_done; - -/* - * formatted output functions - */ - - -/* A shell error occurred (eg, syntax error, etc.) */ -void -#ifdef HAVE_PROTOTYPES -errorf(const char *fmt, ...) -#else -errorf(fmt, va_alist) - const char *fmt; - va_dcl -#endif -{ - va_list va; - - shl_stdout_ok = 0; /* debugging: note that stdout not valid */ - exstat = 1; - if (*fmt) { - error_prefix(TRUE); - SH_VA_START(va, fmt); - shf_vfprintf(shl_out, fmt, va); - va_end(va); - shf_putchar('\n', shl_out); - } - shf_flush(shl_out); - unwind(LERROR); -} - -/* like errorf(), but no unwind is done */ -void -#ifdef HAVE_PROTOTYPES -warningf(int fileline, const char *fmt, ...) -#else -warningf(fileline, fmt, va_alist) - int fileline; - const char *fmt; - va_dcl -#endif -{ - va_list va; - - error_prefix(fileline); - SH_VA_START(va, fmt); - shf_vfprintf(shl_out, fmt, va); - va_end(va); - shf_putchar('\n', shl_out); - shf_flush(shl_out); -} - -/* Used by built-in utilities to prefix shell and utility name to message - * (also unwinds environments for special builtins). - */ -void -#ifdef HAVE_PROTOTYPES -bi_errorf(const char *fmt, ...) -#else -bi_errorf(fmt, va_alist) - const char *fmt; - va_dcl -#endif -{ - va_list va; - - shl_stdout_ok = 0; /* debugging: note that stdout not valid */ - exstat = 1; - if (*fmt) { - error_prefix(TRUE); - /* not set when main() calls parse_args() */ - if (builtin_argv0) - shf_fprintf(shl_out, "%s: ", builtin_argv0); - SH_VA_START(va, fmt); - shf_vfprintf(shl_out, fmt, va); - va_end(va); - shf_putchar('\n', shl_out); - } - shf_flush(shl_out); - /* POSIX special builtins and ksh special builtins cause - * non-interactive shells to exit. - * XXX odd use of KEEPASN; also may not want LERROR here - */ - if ((builtin_flag & SPEC_BI) - || (Flag(FPOSIX) && (builtin_flag & KEEPASN))) - { - builtin_argv0 = (char *) 0; - unwind(LERROR); - } -} - -/* Called when something that shouldn't happen does */ -void -#ifdef HAVE_PROTOTYPES -internal_errorf(int jump, const char *fmt, ...) -#else -internal_errorf(jump, fmt, va_alist) - int jump; - const char *fmt; - va_dcl -#endif -{ - va_list va; - - error_prefix(TRUE); - shf_fprintf(shl_out, "internal error: "); - SH_VA_START(va, fmt); - shf_vfprintf(shl_out, fmt, va); - va_end(va); - shf_putchar('\n', shl_out); - shf_flush(shl_out); - if (jump) - unwind(LERROR); -} - -/* used by error reporting functions to print "ksh: .kshrc[25]: " */ -void -error_prefix(fileline) - int fileline; -{ - /* Avoid foo: foo[2]: ... */ - if (!fileline || !source || !source->file - || strcmp(source->file, kshname) != 0) - shf_fprintf(shl_out, "%s: ", kshname + (*kshname == '-')); - if (fileline && source && source->file != NULL) { - shf_fprintf(shl_out, "%s[%d]: ", source->file, - source->errline > 0 ? source->errline : source->line); - source->errline = 0; - } -} - -/* printf to shl_out (stderr) with flush */ -void -#ifdef HAVE_PROTOTYPES -shellf(const char *fmt, ...) -#else -shellf(fmt, va_alist) - const char *fmt; - va_dcl -#endif -{ - va_list va; - - if (!initio_done) /* shl_out may not be set up yet... */ - return; - SH_VA_START(va, fmt); - shf_vfprintf(shl_out, fmt, va); - va_end(va); - shf_flush(shl_out); -} - -/* printf to shl_stdout (stdout) */ -void -#ifdef HAVE_PROTOTYPES -shprintf(const char *fmt, ...) -#else -shprintf(fmt, va_alist) - const char *fmt; - va_dcl -#endif -{ - va_list va; - - if (!shl_stdout_ok) - internal_errorf(1, "shl_stdout not valid"); - SH_VA_START(va, fmt); - shf_vfprintf(shl_stdout, fmt, va); - va_end(va); -} - -#ifdef KSH_DEBUG -static struct shf *kshdebug_shf; - -void -kshdebug_init_() -{ - if (kshdebug_shf) - shf_close(kshdebug_shf); - kshdebug_shf = shf_open("/tmp/ksh-debug.log", - O_WRONLY|O_APPEND|O_CREAT, 0600, - SHF_WR|SHF_MAPHI); - if (kshdebug_shf) { - shf_fprintf(kshdebug_shf, "\nNew shell[pid %d]\n", getpid()); - shf_flush(kshdebug_shf); - } -} - -/* print to debugging log */ -void -# ifdef HAVE_PROTOTYPES -kshdebug_printf_(const char *fmt, ...) -# else -kshdebug_printf_(fmt, va_alist) - const char *fmt; - va_dcl -# endif -{ - va_list va; - - if (!kshdebug_shf) - return; - SH_VA_START(va, fmt); - shf_fprintf(kshdebug_shf, "[%d] ", getpid()); - shf_vfprintf(kshdebug_shf, fmt, va); - va_end(va); - shf_flush(kshdebug_shf); -} - -void -kshdebug_dump_(str, mem, nbytes) - const char *str; - const void *mem; - int nbytes; -{ - int i, j; - int nprow = 16; - - if (!kshdebug_shf) - return; - shf_fprintf(kshdebug_shf, "[%d] %s:\n", getpid(), str); - for (i = 0; i < nbytes; i += nprow) { - char c = '\t'; - for (j = 0; j < nprow && i + j < nbytes; j++) { - shf_fprintf(kshdebug_shf, "%c%02x", - c, ((const unsigned char *) mem)[i + j]); - c = ' '; - } - shf_fprintf(kshdebug_shf, "\n"); - } - shf_flush(kshdebug_shf); -} -#endif /* KSH_DEBUG */ - -/* test if we can seek backwards fd (returns 0 or SHF_UNBUF) */ -int -can_seek(fd) - int fd; -{ - struct stat statb; - - return fstat(fd, &statb) == 0 && !S_ISREG(statb.st_mode) ? - SHF_UNBUF : 0; -} - -struct shf shf_iob[3]; - -void -initio() -{ - shf_fdopen(1, SHF_WR, shl_stdout); /* force buffer allocation */ - shf_fdopen(2, SHF_WR, shl_out); - shf_fdopen(2, SHF_WR, shl_spare); /* force buffer allocation */ - initio_done = 1; - kshdebug_init(); -} - -/* A dup2() with error checking */ -int -ksh_dup2(ofd, nfd, errok) - int ofd; - int nfd; - int errok; -{ - int ret = dup2(ofd, nfd); - - if (ret < 0 && errno != EBADF && !errok) - errorf("too many files open in shell"); - -#ifdef DUP2_BROKEN - /* Ultrix systems like to preserve the close-on-exec flag */ - if (ret >= 0) - (void) fcntl(nfd, F_SETFD, 0); -#endif /* DUP2_BROKEN */ - - return ret; -} - -/* - * move fd from user space (0<=fd<10) to shell space (fd>=10), - * set close-on-exec flag. - */ -int -savefd(fd, noclose) - int fd; - int noclose; -{ - int nfd; - - if (fd < FDBASE) { - nfd = ksh_dupbase(fd, FDBASE); - if (nfd < 0) { - if (errno == EBADF) - return -1; - else - errorf("too many files open in shell"); - } - if (!noclose) - close(fd); - } else - nfd = fd; - fd_clexec(nfd); - return nfd; -} - -void -restfd(fd, ofd) - int fd, ofd; -{ - if (fd == 2) - shf_flush(&shf_iob[fd]); - if (ofd < 0) /* original fd closed */ - close(fd); - else if (fd != ofd) { - ksh_dup2(ofd, fd, TRUE); /* XXX: what to do if this fails? */ - close(ofd); - } -} - -void -openpipe(pv) - register int *pv; -{ - if (pipe(pv) < 0) - errorf("can't create pipe - try again"); - pv[0] = savefd(pv[0], 0); - pv[1] = savefd(pv[1], 0); -} - -void -closepipe(pv) - register int *pv; -{ - close(pv[0]); - close(pv[1]); -} - -/* Called by iosetup() (deals with 2>&4, etc.), c_read, c_print to turn - * a string (the X in 2>&X, read -uX, print -uX) into a file descriptor. - */ -int -check_fd(name, mode, emsgp) - char *name; - int mode; - const char **emsgp; -{ - int fd, fl; - - if (isdigit((unsigned char)name[0]) && !name[1]) { - fd = name[0] - '0'; - if ((fl = fcntl(fd = name[0] - '0', F_GETFL, 0)) < 0) { - if (emsgp) - *emsgp = "bad file descriptor"; - return -1; - } - fl &= O_ACCMODE; -#ifdef OS2 - if (mode == W_OK ) { - if (setmode(fd, O_TEXT) == -1) { - if (emsgp) - *emsgp = "couldn't set write mode"; - return -1; - } - } else if (mode == R_OK) - if (setmode(fd, O_BINARY) == -1) { - if (emsgp) - *emsgp = "couldn't set read mode"; - return -1; - } -#else /* OS2 */ - /* X_OK is a kludge to disable this check for dups (x<&1): - * historical shells never did this check (XXX don't know what - * posix has to say). - */ - if (!(mode & X_OK) && fl != O_RDWR - && (((mode & R_OK) && fl != O_RDONLY) - || ((mode & W_OK) && fl != O_WRONLY))) - { - if (emsgp) - *emsgp = (fl == O_WRONLY) ? - "fd not open for reading" - : "fd not open for writing"; - return -1; - } -#endif /* OS2 */ - return fd; - } -#ifdef KSH - else if (name[0] == 'p' && !name[1]) - return coproc_getfd(mode, emsgp); -#endif /* KSH */ - if (emsgp) - *emsgp = "illegal file descriptor name"; - return -1; -} - -#ifdef KSH -/* Called once from main */ -void -coproc_init() -{ - coproc.read = coproc.readw = coproc.write = -1; - coproc.njobs = 0; - coproc.id = 0; -} - -/* Called by c_read() when eof is read - close fd if it is the co-process fd */ -void -coproc_read_close(fd) - int fd; -{ - if (coproc.read >= 0 && fd == coproc.read) { - coproc_readw_close(fd); - close(coproc.read); - coproc.read = -1; - } -} - -/* Called by c_read() and by iosetup() to close the other side of the - * read pipe, so reads will actually terminate. - */ -void -coproc_readw_close(fd) - int fd; -{ - if (coproc.readw >= 0 && coproc.read >= 0 && fd == coproc.read) { - close(coproc.readw); - coproc.readw = -1; - } -} - -/* Called by c_print when a write to a fd fails with EPIPE and by iosetup - * when co-process input is dup'd - */ -void -coproc_write_close(fd) - int fd; -{ - if (coproc.write >= 0 && fd == coproc.write) { - close(coproc.write); - coproc.write = -1; - } -} - -/* Called to check for existence of/value of the co-process file descriptor. - * (Used by check_fd() and by c_read/c_print to deal with -p option). - */ -int -coproc_getfd(mode, emsgp) - int mode; - const char **emsgp; -{ - int fd = (mode & R_OK) ? coproc.read : coproc.write; - - if (fd >= 0) - return fd; - if (emsgp) - *emsgp = "no coprocess"; - return -1; -} - -/* called to close file descriptors related to the coprocess (if any) - * Should be called with SIGCHLD blocked. - */ -void -coproc_cleanup(reuse) - int reuse; -{ - /* This to allow co-processes to share output pipe */ - if (!reuse || coproc.readw < 0 || coproc.read < 0) { - if (coproc.read >= 0) { - close(coproc.read); - coproc.read = -1; - } - if (coproc.readw >= 0) { - close(coproc.readw); - coproc.readw = -1; - } - } - if (coproc.write >= 0) { - close(coproc.write); - coproc.write = -1; - } -} -#endif /* KSH */ - - -/* - * temporary files - */ - -struct temp * -maketemp(ap, type, tlist) - Area *ap; - Temp_type type; - struct temp **tlist; -{ -#ifndef __NetBSD__ - static unsigned int inc; -#endif - struct temp *tp; - int len; - int fd; - char *pathx; - const char *dir; - - dir = tmpdir ? tmpdir : "/tmp"; - /* The 20 + 20 is a paranoid worst case for pid/inc */ - len = strlen(dir) + 3 + 20 + 20 + 1; - tp = (struct temp *) alloc(sizeof(struct temp) + len, ap); - tp->name = pathx = (char *) &tp[1]; - tp->shf = (struct shf *) 0; - tp->type = type; -#ifdef __NetBSD__ - shf_snprintf(pathx, len, "%s/shXXXXXXXX", dir); - fd = mkstemp(pathx); - if (fd >= 0) - tp->shf = shf_fdopen(fd, SHF_WR, (struct shf *) 0); -#else - while (1) { - /* Note that temp files need to fit 8.3 DOS limits */ - shf_snprintf(pathx, len, "%s/sh%05u.%03x", - dir, (unsigned) procpid, inc++); - /* Mode 0600 to be paranoid, O_TRUNC in case O_EXCL isn't - * really there. - */ - fd = open(pathx, O_RDWR|O_CREAT|O_EXCL|O_TRUNC, 0600); - if (fd >= 0) { - tp->shf = shf_fdopen(fd, SHF_WR, (struct shf *) 0); - break; - } - if (errno != EINTR -#ifdef EEXIST - && errno != EEXIST -#endif /* EEXIST */ -#ifdef EISDIR - && errno != EISDIR -#endif /* EISDIR */ - ) - /* Error must be printed by caller: don't know here if - * errorf() or bi_errorf() should be used. - */ - break; - } -#endif /* __NetBSD__ */ - tp->pid = procpid; - - tp->next = *tlist; - *tlist = tp; - - return tp; -} diff --git a/bin/ksh/jobs.c b/bin/ksh/jobs.c deleted file mode 100644 index 1ef0e8dd7..000000000 --- a/bin/ksh/jobs.c +++ /dev/null @@ -1,1858 +0,0 @@ -/* $NetBSD: jobs.c,v 1.10 2011/10/16 17:12:11 joerg Exp $ */ - -/* - * Process and job control - */ - -/* - * Reworked/Rewritten version of Eric Gisin's/Ron Natalie's code by - * Larry Bouzane (larry@cs.mun.ca) and hacked again by - * Michael Rendell (michael@cs.mun.ca) - * - * The interface to the rest of the shell should probably be changed - * to allow use of vfork() when available but that would be way too much - * work :) - * - * Notes regarding the copious ifdefs: - * - JOB_SIGS is independent of JOBS - it is defined if there are modern - * signal and wait routines available. This is preferred, even when - * JOBS is not defined, since the shell will not otherwise notice when - * background jobs die until the shell waits for a foreground process - * to die. - * - TTY_PGRP defined iff JOBS is defined - defined if there are tty - * process groups - * - NEED_PGRP_SYNC defined iff JOBS is defined - see comment below - */ -#include - -#ifndef lint -__RCSID("$NetBSD: jobs.c,v 1.10 2011/10/16 17:12:11 joerg Exp $"); -#endif - - -#include "sh.h" -#include "ksh_stat.h" -#include "ksh_wait.h" -#include "ksh_times.h" -#include "tty.h" - -/* Start of system configuration stuff */ - -/* We keep CHILD_MAX zombie processes around (exact value isn't critical) */ -#ifndef CHILD_MAX -# if defined(HAVE_SYSCONF) && defined(_SC_CHILD_MAX) -# define CHILD_MAX sysconf(_SC_CHILD_MAX) -# else /* _SC_CHILD_MAX */ -# ifdef _POSIX_CHILD_MAX -# define CHILD_MAX ((_POSIX_CHILD_MAX) * 2) -# else /* _POSIX_CHILD_MAX */ -# define CHILD_MAX 20 -# endif /* _POSIX_CHILD_MAX */ -# endif /* _SC_CHILD_MAX */ -#endif /* !CHILD_MAX */ - -#ifdef JOBS -# if defined(HAVE_TCSETPGRP) || defined(TIOCSPGRP) -# define TTY_PGRP -# endif -# ifdef BSD_PGRP -# define setpgid setpgrp -# define getpgID() getpgrp(0) -# else -# define getpgID() getpgrp() -# endif -# if defined(TTY_PGRP) && !defined(HAVE_TCSETPGRP) -int tcsetpgrp ARGS((int fd, pid_t grp)); -int tcgetpgrp ARGS((int fd)); - -int -tcsetpgrp(fd, grp) - int fd; - pid_t grp; -{ - return ioctl(fd, TIOCSPGRP, &grp); -} - -int -tcgetpgrp(fd) - int fd; -{ - int r, grp; - - if ((r = ioctl(fd, TIOCGPGRP, &grp)) < 0) - return r; - return grp; -} -# endif /* !HAVE_TCSETPGRP && TIOCSPGRP */ -#else /* JOBS */ -/* These so we can use ifdef xxx instead of if defined(JOBS) && defined(xxx) */ -# undef TTY_PGRP -# undef NEED_PGRP_SYNC -#endif /* JOBS */ - -/* End of system configuration stuff */ - - -/* Order important! */ -#define PRUNNING 0 -#define PEXITED 1 -#define PSIGNALLED 2 -#define PSTOPPED 3 - -typedef struct proc Proc; -struct proc { - Proc *next; /* next process in pipeline (if any) */ - int state; - WAIT_T status; /* wait status */ - pid_t pid; /* process id */ - char command[48]; /* process command string */ -}; - -/* Notify/print flag - j_print() argument */ -#define JP_NONE 0 /* don't print anything */ -#define JP_SHORT 1 /* print signals processes were killed by */ -#define JP_MEDIUM 2 /* print [job-num] -/+ command */ -#define JP_LONG 3 /* print [job-num] -/+ pid command */ -#define JP_PGRP 4 /* print pgrp */ - -/* put_job() flags */ -#define PJ_ON_FRONT 0 /* at very front */ -#define PJ_PAST_STOPPED 1 /* just past any stopped jobs */ - -/* Job.flags values */ -#define JF_STARTED 0x001 /* set when all processes in job are started */ -#define JF_WAITING 0x002 /* set if j_waitj() is waiting on job */ -#define JF_W_ASYNCNOTIFY 0x004 /* set if waiting and async notification ok */ -#define JF_XXCOM 0x008 /* set for `command` jobs */ -#define JF_FG 0x010 /* running in foreground (also has tty pgrp) */ -#define JF_SAVEDTTY 0x020 /* j->ttystate is valid */ -#define JF_CHANGED 0x040 /* process has changed state */ -#define JF_KNOWN 0x080 /* $! referenced */ -#define JF_ZOMBIE 0x100 /* known, unwaited process */ -#define JF_REMOVE 0x200 /* flagged for removal (j_jobs()/j_noityf()) */ -#define JF_USETTYMODE 0x400 /* tty mode saved if process exits normally */ -#define JF_SAVEDTTYPGRP 0x800 /* j->saved_ttypgrp is valid */ - -typedef struct job Job; -struct job { - Job *next; /* next job in list */ - int job; /* job number: %n */ - int flags; /* see JF_* */ - int state; /* job state */ - int status; /* exit status of last process */ - pid_t pgrp; /* process group of job */ - pid_t ppid; /* pid of process that forked job */ - INT32 age; /* number of jobs started */ - clock_t systime; /* system time used by job */ - clock_t usrtime; /* user time used by job */ - Proc *proc_list; /* process list */ - Proc *last_proc; /* last process in list */ -#ifdef KSH - Coproc_id coproc_id; /* 0 or id of coprocess output pipe */ -#endif /* KSH */ -#ifdef TTY_PGRP - TTY_state ttystate; /* saved tty state for stopped jobs */ - pid_t saved_ttypgrp; /* saved tty process group for stopped jobs */ -#endif /* TTY_PGRP */ -}; - -/* Flags for j_waitj() */ -#define JW_NONE 0x00 -#define JW_INTERRUPT 0x01 /* ^C will stop the wait */ -#define JW_ASYNCNOTIFY 0x02 /* asynchronous notification during wait ok */ -#define JW_STOPPEDWAIT 0x04 /* wait even if job stopped */ - -/* Error codes for j_lookup() */ -#define JL_OK 0 -#define JL_NOSUCH 1 /* no such job */ -#define JL_AMBIG 2 /* %foo or %?foo is ambiguous */ -#define JL_INVALID 3 /* non-pid, non-% job id */ - -static const char *const lookup_msgs[] = { - null, - "no such job", - "ambiguous", - "argument must be %job or process id", - (char *) 0 - }; -clock_t j_systime, j_usrtime; /* user and system time of last j_waitjed job */ - -static Job *job_list; /* job list */ -static Job *last_job; -static Job *async_job; -static pid_t async_pid; - -static int nzombie; /* # of zombies owned by this process */ -static INT32 njobs; /* # of jobs started */ -static int child_max; /* CHILD_MAX */ - - -#ifdef JOB_SIGS -/* held_sigchld is set if sigchld occurs before a job is completely started */ -static int held_sigchld; -#endif /* JOB_SIGS */ - -#ifdef JOBS -static struct shf *shl_j; -#endif /* JOBS */ - -#ifdef NEED_PGRP_SYNC -/* On some systems, the kernel doesn't count zombie processes when checking - * if a process group is valid, which can cause problems in creating the - * pipeline "cmd1 | cmd2": if cmd1 can die (and go into the zombie state) - * before cmd2 is started, the kernel doesn't allow the setpgid() for cmd2 - * to succeed. Solution is to create a pipe between the parent and the first - * process; the first process doesn't do anything until the pipe is closed - * and the parent doesn't close the pipe until all the processes are started. - */ -static int j_sync_pipe[2]; -static int j_sync_open; -#endif /* NEED_PGRP_SYNC */ - -#ifdef TTY_PGRP -static int ttypgrp_ok; /* set if can use tty pgrps */ -static pid_t restore_ttypgrp = -1; -static pid_t our_pgrp; -static int const tt_sigs[] = { SIGTSTP, SIGTTIN, SIGTTOU }; -#endif /* TTY_PGRP */ - -static void j_set_async ARGS((Job *j)); -static void j_startjob ARGS((Job *j)); -static int j_waitj ARGS((Job *j, int flags, const char *where)); -static RETSIGTYPE j_sigchld ARGS((int sig)); -static void j_print ARGS((Job *j, int how, struct shf *shf)); -static Job *j_lookup ARGS((const char *cp, int *ecodep)); -static Job *new_job ARGS((void)); -static Proc *new_proc ARGS((void)); -static void check_job ARGS((Job *j)); -static void put_job ARGS((Job *j, int where)); -static void remove_job ARGS((Job *j, const char *where)); -static int kill_job ARGS((Job *j, int sig)); - -/* initialize job control */ -void -j_init(mflagset) - int mflagset; -{ - child_max = CHILD_MAX; /* so syscon() isn't always being called */ - -#ifdef JOB_SIGS - sigemptyset(&sm_default); - sigprocmask(SIG_SETMASK, &sm_default, (sigset_t *) 0); - - sigemptyset(&sm_sigchld); - sigaddset(&sm_sigchld, SIGCHLD); - - setsig(&sigtraps[SIGCHLD], j_sigchld, - SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP); -#else /* JOB_SIGS */ - /* Make sure SIGCHLD isn't ignored - can do odd things under SYSV */ - setsig(&sigtraps[SIGCHLD], SIG_DFL, SS_RESTORE_ORIG|SS_FORCE); -#endif /* JOB_SIGS */ - -#ifdef JOBS - if (!mflagset && Flag(FTALKING)) - Flag(FMONITOR) = 1; - - /* shl_j is used to do asynchronous notification (used in - * an interrupt handler, so need a distinct shf) - */ - shl_j = shf_fdopen(2, SHF_WR, (struct shf *) 0); - -# ifdef TTY_PGRP - if (Flag(FMONITOR) || Flag(FTALKING)) { - int i; - - /* the TF_SHELL_USES test is a kludge that lets us know if - * if the signals have been changed by the shell. - */ - for (i = NELEM(tt_sigs); --i >= 0; ) { - sigtraps[tt_sigs[i]].flags |= TF_SHELL_USES; - /* j_change() sets this to SS_RESTORE_DFL if FMONITOR */ - setsig(&sigtraps[tt_sigs[i]], SIG_IGN, - SS_RESTORE_IGN|SS_FORCE); - } - } -# endif /* TTY_PGRP */ - - /* j_change() calls tty_init() */ - if (Flag(FMONITOR)) - j_change(); - else -#endif /* JOBS */ - if (Flag(FTALKING)) - tty_init(TRUE); -} - -/* job cleanup before shell exit */ -void -j_exit() -{ - /* kill stopped, and possibly running, jobs */ - Job *j; - int killed = 0; - - for (j = job_list; j != (Job *) 0; j = j->next) { - if (j->ppid == procpid - && (j->state == PSTOPPED - || (j->state == PRUNNING - && ((j->flags & JF_FG) - || (Flag(FLOGIN) && !Flag(FNOHUP) - && procpid == kshpid))))) - { - killed = 1; - if (j->pgrp == 0) - kill_job(j, SIGHUP); - else - killpg(j->pgrp, SIGHUP); -#ifdef JOBS - if (j->state == PSTOPPED) { - if (j->pgrp == 0) - kill_job(j, SIGCONT); - else - killpg(j->pgrp, SIGCONT); - } -#endif /* JOBS */ - } - } - if (killed) - sleep(1); - j_notify(); - -#ifdef JOBS -# ifdef TTY_PGRP - if (kshpid == procpid && restore_ttypgrp >= 0) { - /* Need to restore the tty pgrp to what it was when the - * shell started up, so that the process that started us - * will be able to access the tty when we are done. - * Also need to restore our process group in case we are - * about to do an exec so that both our parent and the - * process we are to become will be able to access the tty. - */ - tcsetpgrp(tty_fd, restore_ttypgrp); - setpgid(0, restore_ttypgrp); - } -# endif /* TTY_PGRP */ - if (Flag(FMONITOR)) { - Flag(FMONITOR) = 0; - j_change(); - } -#endif /* JOBS */ -} - -#ifdef JOBS -/* turn job control on or off according to Flag(FMONITOR) */ -void -j_change() -{ - int i; - - if (Flag(FMONITOR)) { - /* Don't call get_tty() 'til we own the tty process group */ - tty_init(FALSE); - -# ifdef TTY_PGRP - /* no controlling tty, no SIGT* */ - ttypgrp_ok = tty_fd >= 0 && tty_devtty; - - if (ttypgrp_ok && (our_pgrp = getpgID()) < 0) { - warningf(FALSE, "j_init: getpgrp() failed: %s", - strerror(errno)); - ttypgrp_ok = 0; - } - if (ttypgrp_ok) { - setsig(&sigtraps[SIGTTIN], SIG_DFL, - SS_RESTORE_ORIG|SS_FORCE); - /* wait to be given tty (POSIX.1, B.2, job control) */ - while (1) { - pid_t ttypgrp; - - if ((ttypgrp = tcgetpgrp(tty_fd)) < 0) { - warningf(FALSE, - "j_init: tcgetpgrp() failed: %s", - strerror(errno)); - ttypgrp_ok = 0; - break; - } - if (ttypgrp == our_pgrp) - break; - kill(0, SIGTTIN); - } - } - for (i = NELEM(tt_sigs); --i >= 0; ) - setsig(&sigtraps[tt_sigs[i]], SIG_IGN, - SS_RESTORE_DFL|SS_FORCE); - if (ttypgrp_ok && our_pgrp != kshpid) { - if (setpgid(0, kshpid) < 0) { - warningf(FALSE, - "j_init: setpgid() failed: %s", - strerror(errno)); - ttypgrp_ok = 0; - } else { - if (tcsetpgrp(tty_fd, kshpid) < 0) { - warningf(FALSE, - "j_init: tcsetpgrp() failed: %s", - strerror(errno)); - ttypgrp_ok = 0; - } else - restore_ttypgrp = our_pgrp; - our_pgrp = kshpid; - } - } -# if defined(NTTYDISC) && defined(TIOCSETD) && !defined(HAVE_TERMIOS_H) && !defined(HAVE_TERMIO_H) - if (ttypgrp_ok) { - int ldisc = NTTYDISC; - - if (ioctl(tty_fd, TIOCSETD, &ldisc) < 0) - warningf(FALSE, - "j_init: can't set new line discipline: %s", - strerror(errno)); - } -# endif /* NTTYDISC && TIOCSETD */ - if (!ttypgrp_ok) - warningf(FALSE, "warning: won't have full job control"); -# endif /* TTY_PGRP */ - if (tty_fd >= 0) - get_tty(tty_fd, &tty_state); - } else { -# ifdef TTY_PGRP - ttypgrp_ok = 0; - if (Flag(FTALKING)) - for (i = NELEM(tt_sigs); --i >= 0; ) - setsig(&sigtraps[tt_sigs[i]], SIG_IGN, - SS_RESTORE_IGN|SS_FORCE); - else - for (i = NELEM(tt_sigs); --i >= 0; ) { - if (sigtraps[tt_sigs[i]].flags & (TF_ORIG_IGN - |TF_ORIG_DFL)) - setsig(&sigtraps[tt_sigs[i]], - (sigtraps[tt_sigs[i]].flags & TF_ORIG_IGN) ? SIG_IGN : SIG_DFL, - SS_RESTORE_ORIG|SS_FORCE); - } -# endif /* TTY_PGRP */ - if (!Flag(FTALKING)) - tty_close(); - } -} -#endif /* JOBS */ - -/* execute tree in child subprocess */ -int -exchild(t, flags, close_fd) - struct op *t; - int flags; - int close_fd; /* used if XPCLOSE or XCCLOSE */ -{ - static Proc *last_proc; /* for pipelines */ - - int i; -#ifdef JOB_SIGS - sigset_t omask; -#endif /* JOB_SIGS */ - Proc *p; - Job *j; - int rv = 0; - int forksleep; - int ischild; - - if (flags & XEXEC) - /* Clear XFORK|XPCLOSE|XCCLOSE|XCOPROC|XPIPEO|XPIPEI|XXCOM|XBGND - * (also done in another execute() below) - */ - return execute(t, flags & (XEXEC | XERROK)); - -#ifdef JOB_SIGS - /* no SIGCHLD's while messing with job and process lists */ - sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); -#endif /* JOB_SIGS */ - - p = new_proc(); - p->next = (Proc *) 0; - p->state = PRUNNING; - WSTATUS(p->status) = 0; - p->pid = 0; - - /* link process into jobs list */ - if (flags&XPIPEI) { /* continuing with a pipe */ - if (!last_job) - internal_errorf(1, "exchild: XPIPEI and no last_job - pid %d", (int) procpid); - j = last_job; - last_proc->next = p; - last_proc = p; - } else { -#ifdef NEED_PGRP_SYNC - if (j_sync_open) { /* should never happen */ - j_sync_open = 0; - closepipe(j_sync_pipe); - } - /* don't do the sync pipe business if there is no pipeline */ - if (flags & XPIPEO) { - openpipe(j_sync_pipe); - j_sync_open = 1; - } -#endif /* NEED_PGRP_SYNC */ - j = new_job(); /* fills in j->job */ - /* we don't consider XXCOM's foreground since they don't get - * tty process group and we don't save or restore tty modes. - */ - j->flags = (flags & XXCOM) ? JF_XXCOM - : ((flags & XBGND) ? 0 : (JF_FG|JF_USETTYMODE)); - j->usrtime = j->systime = 0; - j->state = PRUNNING; - j->pgrp = 0; - j->ppid = procpid; - j->age = ++njobs; - j->proc_list = p; -#ifdef KSH - j->coproc_id = 0; -#endif /* KSH */ - last_job = j; - last_proc = p; - put_job(j, PJ_PAST_STOPPED); - } - - snptreef(p->command, sizeof(p->command), "%T", t); - - /* create child process */ - forksleep = 1; - while ((i = fork()) < 0 && errno == EAGAIN && forksleep < 32) { - if (intrsig) /* allow user to ^C out... */ - break; - sleep(forksleep); - forksleep <<= 1; - } - if (i < 0) { - kill_job(j, SIGKILL); - remove_job(j, "fork failed"); -#ifdef NEED_PGRP_SYNC - if (j_sync_open) { - closepipe(j_sync_pipe); - j_sync_open = 0; - } -#endif /* NEED_PGRP_SYNC */ -#ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); -#endif /* JOB_SIGS */ - errorf("cannot fork - try again"); - } - ischild = i == 0; - if (ischild) - p->pid = procpid = getpid(); - else - p->pid = i; - -#ifdef JOBS - /* job control set up */ - if (Flag(FMONITOR) && !(flags&XXCOM)) { - int dotty = 0; -# ifdef NEED_PGRP_SYNC - int first_child_sync = 0; -# endif /* NEED_PGRP_SYNC */ - -# ifdef NEED_PGRP_SYNC - if (j_sync_open) { - /* - * The Parent closes 0, keeps 1 open 'til the whole - * pipeline is started. The First child closes 1, - * keeps 0 open (reads from it). The remaining - * children just have to close 1 (parent has already - * closeed 0). - */ - if (j->pgrp == 0) { /* First process */ - close(j_sync_pipe[ischild]); - j_sync_pipe[ischild] = -1; - first_child_sync = ischild; - } else if (ischild) { - j_sync_open = 0; - closepipe(j_sync_pipe); - } - } -# endif /* NEED_PGRP_SYNC */ - if (j->pgrp == 0) { /* First process */ - j->pgrp = p->pid; - dotty = 1; - } - - /* set pgrp in both parent and child to deal with race - * condition - */ - setpgid(p->pid, j->pgrp); -# ifdef TTY_PGRP - /* YYY: should this be - if (ttypgrp_ok && ischild && !(flags&XBGND)) - tcsetpgrp(tty_fd, j->pgrp); - instead? (see also YYY below) - */ - if (ttypgrp_ok && dotty && !(flags & XBGND)) - tcsetpgrp(tty_fd, j->pgrp); -# endif /* TTY_PGRP */ -# ifdef NEED_PGRP_SYNC - if (first_child_sync) { - char c; - while (read(j_sync_pipe[0], &c, 1) == -1 - && errno == EINTR) - ; - close(j_sync_pipe[0]); - j_sync_open = 0; - } -# endif /* NEED_PGRP_SYNC */ - } -#endif /* JOBS */ - - /* used to close pipe input fd */ - if (close_fd >= 0 && (((flags & XPCLOSE) && !ischild) - || ((flags & XCCLOSE) && ischild))) - close(close_fd); - if (ischild) { /* child */ -#ifdef KSH - /* Do this before restoring signal */ - if (flags & XCOPROC) - coproc_cleanup(FALSE); -#endif /* KSH */ -#ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); -#endif /* JOB_SIGS */ - cleanup_parents_env(); -#ifdef TTY_PGRP - /* If FMONITOR or FTALKING is set, these signals are ignored, - * if neither FMONITOR nor FTALKING are set, the signals have - * their inherited values. - */ - if (Flag(FMONITOR) && !(flags & XXCOM)) { - for (i = NELEM(tt_sigs); --i >= 0; ) - setsig(&sigtraps[tt_sigs[i]], SIG_DFL, - SS_RESTORE_DFL|SS_FORCE); - } -#endif /* TTY_PGRP */ -#ifdef HAVE_NICE - if (Flag(FBGNICE) && (flags & XBGND)) - nice(4); -#endif /* HAVE_NICE */ - if ((flags & XBGND) && !Flag(FMONITOR)) { - setsig(&sigtraps[SIGINT], SIG_IGN, - SS_RESTORE_IGN|SS_FORCE); - setsig(&sigtraps[SIGQUIT], SIG_IGN, - SS_RESTORE_IGN|SS_FORCE); - if (!(flags & (XPIPEI | XCOPROC))) { - int fd = open("/dev/null", 0); - if (fd != 0) { - (void) ksh_dup2(fd, 0, TRUE); - close(fd); - } - } - } - remove_job(j, "child"); /* in case of `jobs` command */ - nzombie = 0; -#ifdef JOBS - ttypgrp_ok = 0; - Flag(FMONITOR) = 0; -#endif /* JOBS */ - Flag(FTALKING) = 0; -#ifdef OS2 - if (tty_fd >= 0) - flags |= XINTACT; -#endif /* OS2 */ - tty_close(); - cleartraps(); - execute(t, (flags & XERROK) | XEXEC); /* no return */ - internal_errorf(0, "exchild: execute() returned"); - unwind(LLEAVE); - /* NOTREACHED */ - } - - /* shell (parent) stuff */ - /* Ensure next child gets a (slightly) different $RANDOM sequence */ - change_random(); - if (!(flags & XPIPEO)) { /* last process in a job */ -#ifdef TTY_PGRP - /* YYY: Is this needed? (see also YYY above) - if (Flag(FMONITOR) && !(flags&(XXCOM|XBGND))) - tcsetpgrp(tty_fd, j->pgrp); - */ -#endif /* TTY_PGRP */ - j_startjob(j); -#ifdef KSH - if (flags & XCOPROC) { - j->coproc_id = coproc.id; - coproc.njobs++; /* n jobs using co-process output */ - coproc.job = (void *) j; /* j using co-process input */ - } -#endif /* KSH */ - if (flags & XBGND) { - j_set_async(j); - if (Flag(FTALKING)) { - shf_fprintf(shl_out, "[%d]", j->job); - for (p = j->proc_list; p; p = p->next) - shf_fprintf(shl_out, " %d", p->pid); - shf_putchar('\n', shl_out); - shf_flush(shl_out); - } - } else - rv = j_waitj(j, JW_NONE, "jw:last proc"); - } - -#ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); -#endif /* JOB_SIGS */ - - return rv; -} - -/* start the last job: only used for `command` jobs */ -void -startlast() -{ -#ifdef JOB_SIGS - sigset_t omask; - - sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); -#endif /* JOB_SIGS */ - - if (last_job) { /* no need to report error - waitlast() will do it */ - /* ensure it isn't removed by check_job() */ - last_job->flags |= JF_WAITING; - j_startjob(last_job); - } -#ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); -#endif /* JOB_SIGS */ -} - -/* wait for last job: only used for `command` jobs */ -int -waitlast() -{ - int rv; - Job *j; -#ifdef JOB_SIGS - sigset_t omask; - - sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); -#endif /* JOB_SIGS */ - - j = last_job; - if (!j || !(j->flags & JF_STARTED)) { - if (!j) - warningf(TRUE, "waitlast: no last job"); - else - internal_errorf(0, "waitlast: not started"); -#ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); -#endif /* JOB_SIGS */ - return 125; /* not so arbitrary, non-zero value */ - } - - rv = j_waitj(j, JW_NONE, "jw:waitlast"); - -#ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); -#endif /* JOB_SIGS */ - - return rv; -} - -/* wait for child, interruptable. */ -int -waitfor(cp, sigp) - const char *cp; - int *sigp; -{ - int rv; - Job *j; - int ecode; - int flags = JW_INTERRUPT|JW_ASYNCNOTIFY; -#ifdef JOB_SIGS - sigset_t omask; - - sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); -#endif /* JOB_SIGS */ - - *sigp = 0; - - if (cp == (char *) 0) { - /* wait for an unspecified job - always returns 0, so - * don't have to worry about exited/signaled jobs - */ - for (j = job_list; j; j = j->next) - /* at&t ksh will wait for stopped jobs - we don't */ - if (j->ppid == procpid && j->state == PRUNNING) - break; - if (!j) { -#ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); -#endif /* JOB_SIGS */ - return -1; - } - } else if ((j = j_lookup(cp, &ecode))) { - /* don't report normal job completion */ - flags &= ~JW_ASYNCNOTIFY; - if (j->ppid != procpid) { -#ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); -#endif /* JOB_SIGS */ - return -1; - } - } else { -#ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); -#endif /* JOB_SIGS */ - if (ecode != JL_NOSUCH) - bi_errorf("%s: %s", cp, lookup_msgs[ecode]); - return -1; - } - - /* at&t ksh will wait for stopped jobs - we don't */ - rv = j_waitj(j, flags, "jw:waitfor"); - -#ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); -#endif /* JOB_SIGS */ - - if (rv < 0) /* we were interrupted */ - *sigp = 128 + -rv; - - return rv; -} - -/* kill (built-in) a job */ -int -j_kill(cp, sig) - const char *cp; - int sig; -{ - Job *j; - int rv = 0; - int ecode; -#ifdef JOB_SIGS - sigset_t omask; - - sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); -#endif /* JOB_SIGS */ - - if ((j = j_lookup(cp, &ecode)) == (Job *) 0) { -#ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); -#endif /* JOB_SIGS */ - bi_errorf("%s: %s", cp, lookup_msgs[ecode]); - return 1; - } - - if (j->pgrp == 0) { /* started when !Flag(FMONITOR) */ - if (kill_job(j, sig) < 0) { - bi_errorf("%s: %s", cp, strerror(errno)); - rv = 1; - } - } else { -#ifdef JOBS - if (j->state == PSTOPPED && (sig == SIGTERM || sig == SIGHUP)) - (void) killpg(j->pgrp, SIGCONT); -#endif /* JOBS */ - if (killpg(j->pgrp, sig) < 0) { - bi_errorf("%s: %s", cp, strerror(errno)); - rv = 1; - } - } - -#ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); -#endif /* JOB_SIGS */ - - return rv; -} - -#ifdef JOBS -/* fg and bg built-ins: called only if Flag(FMONITOR) set */ -int -j_resume(cp, bg) - const char *cp; - int bg; -{ - Job *j; - Proc *p; - int ecode; - int running; - int rv = 0; - sigset_t omask; - - sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); - - if ((j = j_lookup(cp, &ecode)) == (Job *) 0) { - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); - bi_errorf("%s: %s", cp, lookup_msgs[ecode]); - return 1; - } - - if (j->pgrp == 0) { - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); - bi_errorf("job not job-controlled"); - return 1; - } - - if (bg) - shprintf("[%d] ", j->job); - - running = 0; - for (p = j->proc_list; p != (Proc *) 0; p = p->next) { - if (p->state == PSTOPPED) { - p->state = PRUNNING; - WSTATUS(p->status) = 0; - running = 1; - } - shprintf("%s%s", p->command, p->next ? "| " : null); - } - shprintf("%s", newline); - shf_flush(shl_stdout); - if (running) - j->state = PRUNNING; - - put_job(j, PJ_PAST_STOPPED); - if (bg) - j_set_async(j); - else { -# ifdef TTY_PGRP - /* attach tty to job */ - if (j->state == PRUNNING) { - if (ttypgrp_ok && (j->flags & JF_SAVEDTTY)) { - set_tty(tty_fd, &j->ttystate, TF_NONE); - } - /* See comment in j_waitj regarding saved_ttypgrp. */ - if (ttypgrp_ok && tcsetpgrp(tty_fd, (j->flags & JF_SAVEDTTYPGRP) ? j->saved_ttypgrp : j->pgrp) < 0) { - if (j->flags & JF_SAVEDTTY) { - set_tty(tty_fd, &tty_state, TF_NONE); - } - sigprocmask(SIG_SETMASK, &omask, - (sigset_t *) 0); - bi_errorf("1st tcsetpgrp(%d, %d) failed: %s", - tty_fd, (int) ((j->flags & JF_SAVEDTTYPGRP) ? j->saved_ttypgrp : j->pgrp), strerror(errno)); - return 1; - } - } -# endif /* TTY_PGRP */ - j->flags |= JF_FG; - j->flags &= ~JF_KNOWN; - if (j == async_job) - async_job = (Job *) 0; - } - - if (j->state == PRUNNING && killpg(j->pgrp, SIGCONT) < 0) { - int err = errno; - - if (!bg) { - j->flags &= ~JF_FG; -# ifdef TTY_PGRP - if (ttypgrp_ok && (j->flags & JF_SAVEDTTY)) { - set_tty(tty_fd, &tty_state, TF_NONE); - } - if (ttypgrp_ok && tcsetpgrp(tty_fd, our_pgrp) < 0) { - warningf(TRUE, - "fg: 2nd tcsetpgrp(%d, %d) failed: %s", - tty_fd, (int) our_pgrp, - strerror(errno)); - } -# endif /* TTY_PGRP */ - } - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); - bi_errorf("cannot continue job %s: %s", - cp, strerror(err)); - return 1; - } - if (!bg) { -# ifdef TTY_PGRP - if (ttypgrp_ok) { - j->flags &= ~(JF_SAVEDTTY | JF_SAVEDTTYPGRP); - } -# endif /* TTY_PGRP */ - rv = j_waitj(j, JW_NONE, "jw:resume"); - } - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); - return rv; -} -#endif /* JOBS */ - -/* are there any running or stopped jobs ? */ -int -j_stopped_running() -{ - Job *j; - int which = 0; - - for (j = job_list; j != (Job *) 0; j = j->next) { -#ifdef JOBS - if (j->ppid == procpid && j->state == PSTOPPED) - which |= 1; -#endif /* JOBS */ - if (Flag(FLOGIN) && !Flag(FNOHUP) && procpid == kshpid - && j->ppid == procpid && j->state == PRUNNING) - which |= 2; - } - if (which) { - shellf("You have %s%s%s jobs\n", - which & 1 ? "stopped" : "", - which == 3 ? " and " : "", - which & 2 ? "running" : ""); - return 1; - } - - return 0; -} - -/* list jobs for jobs built-in */ -int -j_jobs(cp, slp, nflag) - const char *cp; - int slp; /* 0: short, 1: long, 2: pgrp */ - int nflag; -{ - Job *j, *tmp; - int how; - int zflag = 0; -#ifdef JOB_SIGS - sigset_t omask; - - sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); -#endif /* JOB_SIGS */ - - if (nflag < 0) { /* kludge: print zombies */ - nflag = 0; - zflag = 1; - } - if (cp) { - int ecode; - - if ((j = j_lookup(cp, &ecode)) == (Job *) 0) { -#ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); -#endif /* JOB_SIGS */ - bi_errorf("%s: %s", cp, lookup_msgs[ecode]); - return 1; - } - } else - j = job_list; - how = slp == 0 ? JP_MEDIUM : (slp == 1 ? JP_LONG : JP_PGRP); - for (; j; j = j->next) { - if ((!(j->flags & JF_ZOMBIE) || zflag) - && (!nflag || (j->flags & JF_CHANGED))) - { - j_print(j, how, shl_stdout); - if (j->state == PEXITED || j->state == PSIGNALLED) - j->flags |= JF_REMOVE; - } - if (cp) - break; - } - /* Remove jobs after printing so there won't be multiple + or - jobs */ - for (j = job_list; j; j = tmp) { - tmp = j->next; - if (j->flags & JF_REMOVE) - remove_job(j, "jobs"); - } -#ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); -#endif /* JOB_SIGS */ - return 0; -} - -/* list jobs for top-level notification */ -void -j_notify() -{ - Job *j, *tmp; -#ifdef JOB_SIGS - sigset_t omask; - - sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); -#endif /* JOB_SIGS */ - for (j = job_list; j; j = j->next) { -#ifdef JOBS - if (Flag(FMONITOR) && (j->flags & JF_CHANGED)) - j_print(j, JP_MEDIUM, shl_out); -#endif /* JOBS */ - /* Remove job after doing reports so there aren't - * multiple +/- jobs. - */ - if (j->state == PEXITED || j->state == PSIGNALLED) - j->flags |= JF_REMOVE; - } - for (j = job_list; j; j = tmp) { - tmp = j->next; - if (j->flags & JF_REMOVE) - remove_job(j, "notify"); - } - shf_flush(shl_out); -#ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); -#endif /* JOB_SIGS */ -} - -/* Return pid of last process in last asynchronous job */ -pid_t -j_async() -{ -#ifdef JOB_SIGS - sigset_t omask; - - sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); -#endif /* JOB_SIGS */ - - if (async_job) - async_job->flags |= JF_KNOWN; - -#ifdef JOB_SIGS - sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); -#endif /* JOB_SIGS */ - - return async_pid; -} - -/* Make j the last async process - * - * If jobs are compiled in then this routine expects sigchld to be blocked. - */ -static void -j_set_async(j) - Job *j; -{ - Job *jl, *oldest; - - if (async_job && (async_job->flags & (JF_KNOWN|JF_ZOMBIE)) == JF_ZOMBIE) - remove_job(async_job, "async"); - if (!(j->flags & JF_STARTED)) { - internal_errorf(0, "j_async: job not started"); - return; - } - async_job = j; - async_pid = j->last_proc->pid; - while (nzombie > child_max) { - oldest = (Job *) 0; - for (jl = job_list; jl; jl = jl->next) - if (jl != async_job && (jl->flags & JF_ZOMBIE) - && (!oldest || jl->age < oldest->age)) - oldest = jl; - if (!oldest) { - /* XXX debugging */ - if (!(async_job->flags & JF_ZOMBIE) || nzombie != 1) { - internal_errorf(0, "j_async: bad nzombie (%d)", nzombie); - nzombie = 0; - } - break; - } - remove_job(oldest, "zombie"); - } -} - -/* Start a job: set STARTED, check for held signals and set j->last_proc - * - * If jobs are compiled in then this routine expects sigchld to be blocked. - */ -static void -j_startjob(j) - Job *j; -{ - Proc *p; - - j->flags |= JF_STARTED; - for (p = j->proc_list; p->next; p = p->next) - ; - j->last_proc = p; - -#ifdef NEED_PGRP_SYNC - if (j_sync_open) { - j_sync_open = 0; - closepipe(j_sync_pipe); - } -#endif /* NEED_PGRP_SYNC */ -#ifdef JOB_SIGS - if (held_sigchld) { - held_sigchld = 0; - /* Don't call j_sigchld() as it may remove job... */ - kill(procpid, SIGCHLD); - } -#endif /* JOB_SIGS */ -} - -/* - * wait for job to complete or change state - * - * If jobs are compiled in then this routine expects sigchld to be blocked. - */ -static int -j_waitj(j, flags, where) - Job *j; - int flags; /* see JW_* */ - const char *where; -{ - int rv; - - /* - * No auto-notify on the job we are waiting on. - */ - j->flags |= JF_WAITING; - if (flags & JW_ASYNCNOTIFY) - j->flags |= JF_W_ASYNCNOTIFY; - - if (!Flag(FMONITOR)) - flags |= JW_STOPPEDWAIT; - - while ((volatile int) j->state == PRUNNING - || ((flags & JW_STOPPEDWAIT) - && (volatile int) j->state == PSTOPPED)) - { -#ifdef JOB_SIGS - sigsuspend(&sm_default); -#else /* JOB_SIGS */ - j_sigchld(SIGCHLD); -#endif /* JOB_SIGS */ - if (fatal_trap) { - int oldf = j->flags & (JF_WAITING|JF_W_ASYNCNOTIFY); - j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY); - runtraps(TF_FATAL); - j->flags |= oldf; /* not reached... */ - } - if ((flags & JW_INTERRUPT) && (rv = trap_pending())) { - j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY); - return -rv; - } - } - j->flags &= ~(JF_WAITING|JF_W_ASYNCNOTIFY); - - if (j->flags & JF_FG) { - WAIT_T status; - - j->flags &= ~JF_FG; -#ifdef TTY_PGRP - if (Flag(FMONITOR) && ttypgrp_ok && j->pgrp) { - /* - * Save the tty's current pgrp so it can be restored - * when the job is foregrounded. This is to - * deal with things like the GNU su which does - * a fork/exec instead of an exec (the fork means - * the execed shell gets a different pid from its - * pgrp, so naturally it sets its pgrp and gets hosed - * when it gets foregrounded by the parent shell, which - * has restored the tty's pgrp to that of the su - * process). - */ - if (j->state == PSTOPPED - && (j->saved_ttypgrp = tcgetpgrp(tty_fd)) >= 0) - j->flags |= JF_SAVEDTTYPGRP; - if (tcsetpgrp(tty_fd, our_pgrp) < 0) { - warningf(TRUE, - "j_waitj: tcsetpgrp(%d, %d) failed: %s", - tty_fd, (int) our_pgrp, - strerror(errno)); - } - if (j->state == PSTOPPED) { - j->flags |= JF_SAVEDTTY; - get_tty(tty_fd, &j->ttystate); - } - } -#endif /* TTY_PGRP */ - if (tty_fd >= 0) { - /* Only restore tty settings if job was originally - * started in the foreground. Problems can be - * caused by things like `more foobar &' which will - * typically get and save the shell's vi/emacs tty - * settings before setting up the tty for itself; - * when more exits, it restores the `original' - * settings, and things go down hill from there... - */ - if (j->state == PEXITED && j->status == 0 - && (j->flags & JF_USETTYMODE)) - { - get_tty(tty_fd, &tty_state); - } else { - set_tty(tty_fd, &tty_state, - (j->state == PEXITED) ? 0 : TF_MIPSKLUDGE); - /* Don't use tty mode if job is stopped and - * later restarted and exits. Consider - * the sequence: - * vi foo (stopped) - * ... - * stty something - * ... - * fg (vi; ZZ) - * mode should be that of the stty, not what - * was before the vi started. - */ - if (j->state == PSTOPPED) - j->flags &= ~JF_USETTYMODE; - } - } -#ifdef JOBS - /* If it looks like user hit ^C to kill a job, pretend we got - * one too to break out of for loops, etc. (at&t ksh does this - * even when not monitoring, but this doesn't make sense since - * a tty generated ^C goes to the whole process group) - */ - status = j->last_proc->status; - if (Flag(FMONITOR) && j->state == PSIGNALLED - && WIFSIGNALED(status) - && (sigtraps[WTERMSIG(status)].flags & TF_TTY_INTR)) - trapsig(WTERMSIG(status)); -#endif /* JOBS */ - } - - j_usrtime = j->usrtime; - j_systime = j->systime; - rv = j->status; - - if (!(flags & JW_ASYNCNOTIFY) - && (!Flag(FMONITOR) || j->state != PSTOPPED)) - { - j_print(j, JP_SHORT, shl_out); - shf_flush(shl_out); - } - if (j->state != PSTOPPED - && (!Flag(FMONITOR) || !(flags & JW_ASYNCNOTIFY))) - remove_job(j, where); - - return rv; -} - -/* SIGCHLD handler to reap children and update job states - * - * If jobs are compiled in then this routine expects sigchld to be blocked. - */ -static RETSIGTYPE -j_sigchld(sig) - int sig; -{ - int errno_ = errno; - Job *j; - Proc UNINITIALIZED(*p); - int pid; - WAIT_T status; - struct tms t0, t1; - -#ifdef JOB_SIGS - /* Don't wait for any processes if a job is partially started. - * This is so we don't do away with the process group leader - * before all the processes in a pipe line are started (so the - * setpgid() won't fail) - */ - for (j = job_list; j; j = j->next) - if (j->ppid == procpid && !(j->flags & JF_STARTED)) { - held_sigchld = 1; - return RETSIGVAL; - } -#endif /* JOB_SIGS */ - - ksh_times(&t0); - do { -#ifdef JOB_SIGS - pid = ksh_waitpid(-1, &status, (WNOHANG|WUNTRACED)); -#else /* JOB_SIGS */ - pid = wait(&status); -#endif /* JOB_SIGS */ - - if (pid <= 0) /* return if would block (0) ... */ - break; /* ... or no children or interrupted (-1) */ - - ksh_times(&t1); - - /* find job and process structures for this pid */ - for (j = job_list; j != (Job *) 0; j = j->next) - for (p = j->proc_list; p != (Proc *) 0; p = p->next) - if (p->pid == pid) - goto found; -found: - if (j == (Job *) 0) { - /* Can occur if process has kids, then execs shell - warningf(TRUE, "bad process waited for (pid = %d)", - pid); - */ - t0 = t1; - continue; - } - - j->usrtime += t1.tms_cutime - t0.tms_cutime; - j->systime += t1.tms_cstime - t0.tms_cstime; - t0 = t1; - p->status = status; -#ifdef JOBS - if (WIFSTOPPED(status)) - p->state = PSTOPPED; - else -#endif /* JOBS */ - if (WIFSIGNALED(status)) - p->state = PSIGNALLED; - else - p->state = PEXITED; - - check_job(j); /* check to see if entire job is done */ - } -#ifdef JOB_SIGS - while (1); -#else /* JOB_SIGS */ - while (0); -#endif /* JOB_SIGS */ - - errno = errno_; - - return RETSIGVAL; -} - -/* - * Called only when a process in j has exited/stopped (ie, called only - * from j_sigchld()). If no processes are running, the job status - * and state are updated, asynchronous job notification is done and, - * if unneeded, the job is removed. - * - * If jobs are compiled in then this routine expects sigchld to be blocked. - */ -static void -check_job(j) - Job *j; -{ - int jstate; - Proc *p; - - /* XXX debugging (nasty - interrupt routine using shl_out) */ - if (!(j->flags & JF_STARTED)) { - internal_errorf(0, "check_job: job started (flags 0x%x)", - j->flags); - return; - } - - jstate = PRUNNING; - for (p=j->proc_list; p != (Proc *) 0; p = p->next) { - if (p->state == PRUNNING) - return; /* some processes still running */ - if (p->state > jstate) - jstate = p->state; - } - j->state = jstate; - - switch (j->last_proc->state) { - case PEXITED: - j->status = WEXITSTATUS(j->last_proc->status); - break; - case PSIGNALLED: - j->status = 128 + WTERMSIG(j->last_proc->status); - break; - default: - j->status = 0; - break; - } - -#ifdef KSH - /* Note when co-process dies: can't be done in j_wait() nor - * remove_job() since neither may be called for non-interactive - * shells. - */ - if (j->state == PEXITED || j->state == PSIGNALLED) { - /* No need to keep co-process input any more - * (at least, this is what ksh93d thinks) - */ - if (coproc.job == j) { - coproc.job = (void *) 0; - /* XXX would be nice to get the closes out of here - * so they aren't done in the signal handler. - * Would mean a check in coproc_getfd() to - * do "if job == 0 && write >= 0, close write". - */ - coproc_write_close(coproc.write); - } - /* Do we need to keep the output? */ - if (j->coproc_id && j->coproc_id == coproc.id - && --coproc.njobs == 0) - coproc_readw_close(coproc.read); - } -#endif /* KSH */ - - j->flags |= JF_CHANGED; -#ifdef JOBS - if (Flag(FMONITOR) && !(j->flags & JF_XXCOM)) { - /* Only put stopped jobs at the front to avoid confusing - * the user (don't want finished jobs effecting %+ or %-) - */ - if (j->state == PSTOPPED) - put_job(j, PJ_ON_FRONT); - if (Flag(FNOTIFY) - && (j->flags & (JF_WAITING|JF_W_ASYNCNOTIFY)) != JF_WAITING) - { - /* Look for the real file descriptor 2 */ - { - struct env *ep; - int fd = 2; - - for (ep = e; ep; ep = ep->oenv) - if (ep->savefd && ep->savefd[2]) - fd = ep->savefd[2]; - shf_reopen(fd, SHF_WR, shl_j); - } - /* Can't call j_notify() as it removes jobs. The job - * must stay in the job list as j_waitj() may be - * running with this job. - */ - j_print(j, JP_MEDIUM, shl_j); - shf_flush(shl_j); - if (!(j->flags & JF_WAITING) && j->state != PSTOPPED) - remove_job(j, "notify"); - } - } -#endif /* JOBS */ - if (!Flag(FMONITOR) && !(j->flags & (JF_WAITING|JF_FG)) - && j->state != PSTOPPED) - { - if (j == async_job || (j->flags & JF_KNOWN)) { - j->flags |= JF_ZOMBIE; - j->job = -1; - nzombie++; - } else - remove_job(j, "checkjob"); - } -} - -/* - * Print job status in either short, medium or long format. - * - * If jobs are compiled in then this routine expects sigchld to be blocked. - */ -static void -j_print(j, how, shf) - Job *j; - int how; - struct shf *shf; -{ - Proc *p; - int state; - WAIT_T status; - int coredumped; - char jobchar = ' '; - char buf[64]; - const char *filler; - int output = 0; - - if (how == JP_PGRP) { - /* POSIX doesn't say what to do it there is no process - * group leader (ie, !FMONITOR). We arbitrarily return - * last pid (which is what $! returns). - */ - shf_fprintf(shf, "%d\n", j->pgrp ? j->pgrp - : (j->last_proc ? j->last_proc->pid : 0)); - return; - } - j->flags &= ~JF_CHANGED; - filler = j->job > 10 ? "\n " : "\n "; - if (j == job_list) - jobchar = '+'; - else if (j == job_list->next) - jobchar = '-'; - - for (p = j->proc_list; p != (Proc *) 0;) { - coredumped = 0; - switch (p->state) { - case PRUNNING: - strlcpy(buf, "Running", sizeof buf); - break; - case PSTOPPED: - strlcpy(buf, sigtraps[WSTOPSIG(p->status)].mess, - sizeof buf); - break; - case PEXITED: - if (how == JP_SHORT) - buf[0] = '\0'; - else if (WEXITSTATUS(p->status) == 0) - strlcpy(buf, "Done", sizeof buf); - else - shf_snprintf(buf, sizeof(buf), "Done (%d)", - WEXITSTATUS(p->status)); - break; - case PSIGNALLED: - if (WIFCORED(p->status)) - coredumped = 1; - /* kludge for not reporting `normal termination signals' - * (ie, SIGINT, SIGPIPE) - */ - if (how == JP_SHORT && !coredumped - && (WTERMSIG(p->status) == SIGINT - || WTERMSIG(p->status) == SIGPIPE)) { - buf[0] = '\0'; - } else - strlcpy(buf, sigtraps[WTERMSIG(p->status)].mess, - sizeof buf); - break; - } - - if (how != JP_SHORT) { - if (p == j->proc_list) - shf_fprintf(shf, "[%d] %c ", j->job, jobchar); - else - shf_fprintf(shf, "%s", filler); - } - - if (how == JP_LONG) - shf_fprintf(shf, "%5d ", p->pid); - - if (how == JP_SHORT) { - if (buf[0]) { - output = 1; - shf_fprintf(shf, "%s%s ", - buf, coredumped ? " (core dumped)" : null); - } - } else { - output = 1; - shf_fprintf(shf, "%-20s %s%s%s", buf, p->command, - p->next ? "|" : null, - coredumped ? " (core dumped)" : null); - } - - state = p->state; - status = p->status; - p = p->next; - while (p && p->state == state - && WSTATUS(p->status) == WSTATUS(status)) - { - if (how == JP_LONG) - shf_fprintf(shf, "%s%5d %-20s %s%s", filler, p->pid, - space, p->command, p->next ? "|" : null); - else if (how == JP_MEDIUM) - shf_fprintf(shf, " %s%s", p->command, - p->next ? "|" : null); - p = p->next; - } - } - if (output) - shf_fprintf(shf, newline); -} - -/* Convert % sequence to job - * - * If jobs are compiled in then this routine expects sigchld to be blocked. - */ -static Job * -j_lookup(cp, ecodep) - const char *cp; - int *ecodep; -{ - Job *j, *last_match; - Proc *p; - int len, job = 0; - - if (digit(*cp)) { - job = atoi(cp); - /* Look for last_proc->pid (what $! returns) first... */ - for (j = job_list; j != (Job *) 0; j = j->next) - if (j->last_proc && j->last_proc->pid == job) - return j; - /* ...then look for process group (this is non-POSIX), - * but should not break anything (so FPOSIX isn't used). - */ - for (j = job_list; j != (Job *) 0; j = j->next) - if (j->pgrp && j->pgrp == job) - return j; - if (ecodep) - *ecodep = JL_NOSUCH; - return (Job *) 0; - } - if (*cp != '%') { - if (ecodep) - *ecodep = JL_INVALID; - return (Job *) 0; - } - switch (*++cp) { - case '\0': /* non-standard */ - case '+': - case '%': - if (job_list != (Job *) 0) - return job_list; - break; - - case '-': - if (job_list != (Job *) 0 && job_list->next) - return job_list->next; - break; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - job = atoi(cp); - for (j = job_list; j != (Job *) 0; j = j->next) - if (j->job == job) - return j; - break; - - case '?': /* %?string */ - last_match = (Job *) 0; - for (j = job_list; j != (Job *) 0; j = j->next) - for (p = j->proc_list; p != (Proc *) 0; p = p->next) - if (strstr(p->command, cp+1) != (char *) 0) { - if (last_match) { - if (ecodep) - *ecodep = JL_AMBIG; - return (Job *) 0; - } - last_match = j; - } - if (last_match) - return last_match; - break; - - default: /* %string */ - len = strlen(cp); - last_match = (Job *) 0; - for (j = job_list; j != (Job *) 0; j = j->next) - if (strncmp(cp, j->proc_list->command, len) == 0) { - if (last_match) { - if (ecodep) - *ecodep = JL_AMBIG; - return (Job *) 0; - } - last_match = j; - } - if (last_match) - return last_match; - break; - } - if (ecodep) - *ecodep = JL_NOSUCH; - return (Job *) 0; -} - -static Job *free_jobs; -static Proc *free_procs; - -/* allocate a new job and fill in the job number. - * - * If jobs are compiled in then this routine expects sigchld to be blocked. - */ -static Job * -new_job() -{ - int i; - Job *newj, *j; - - if (free_jobs != (Job *) 0) { - newj = free_jobs; - free_jobs = free_jobs->next; - } else - newj = (Job *) alloc(sizeof(Job), APERM); - - /* brute force method */ - for (i = 1; ; i++) { - for (j = job_list; j && j->job != i; j = j->next) - ; - if (j == (Job *) 0) - break; - } - newj->job = i; - - return newj; -} - -/* Allocate new process struct - * - * If jobs are compiled in then this routine expects sigchld to be blocked. - */ -static Proc * -new_proc() -{ - Proc *p; - - if (free_procs != (Proc *) 0) { - p = free_procs; - free_procs = free_procs->next; - } else - p = (Proc *) alloc(sizeof(Proc), APERM); - - return p; -} - -/* Take job out of job_list and put old structures into free list. - * Keeps nzombies, last_job and async_job up to date. - * - * If jobs are compiled in then this routine expects sigchld to be blocked. - */ -static void -remove_job(j, where) - Job *j; - const char *where; -{ - Proc *p, *tmp; - Job **prev, *curr; - - prev = &job_list; - curr = *prev; - for (; curr != (Job *) 0 && curr != j; prev = &curr->next, curr = *prev) - ; - if (curr != j) { - internal_errorf(0, "remove_job: job not found (%s)", where); - return; - } - *prev = curr->next; - - /* free up proc structures */ - for (p = j->proc_list; p != (Proc *) 0; ) { - tmp = p; - p = p->next; - tmp->next = free_procs; - free_procs = tmp; - } - - if ((j->flags & JF_ZOMBIE) && j->ppid == procpid) - --nzombie; - j->next = free_jobs; - free_jobs = j; - - if (j == last_job) - last_job = (Job *) 0; - if (j == async_job) - async_job = (Job *) 0; -} - -/* put j in a particular location (taking it out job_list if it is there - * already) - * - * If jobs are compiled in then this routine expects sigchld to be blocked. - */ -static void -put_job(j, where) - Job *j; - int where; -{ - Job **prev, *curr; - - /* Remove job from list (if there) */ - prev = &job_list; - curr = job_list; - for (; curr && curr != j; prev = &curr->next, curr = *prev) - ; - if (curr == j) - *prev = curr->next; - - switch (where) { - case PJ_ON_FRONT: - j->next = job_list; - job_list = j; - break; - - case PJ_PAST_STOPPED: - prev = &job_list; - curr = job_list; - for (; curr && curr->state == PSTOPPED; prev = &curr->next, - curr = *prev) - ; - j->next = curr; - *prev = j; - break; - } -} - -/* nuke a job (called when unable to start full job). - * - * If jobs are compiled in then this routine expects sigchld to be blocked. - */ -static int -kill_job(j, sig) - Job *j; - int sig; -{ - Proc *p; - int rval = 0; - - for (p = j->proc_list; p != (Proc *) 0; p = p->next) - if (p->pid != 0) - if (kill(p->pid, sig) < 0) - rval = -1; - return rval; -} diff --git a/bin/ksh/ksh.Man b/bin/ksh/ksh.Man deleted file mode 100644 index 92f2c466c..000000000 --- a/bin/ksh/ksh.Man +++ /dev/null @@ -1,3620 +0,0 @@ -'\" t -.\" $NetBSD: ksh.Man,v 1.24 2015/04/12 17:05:03 jmcneill Exp $ -.\"{{{}}} -.\"{{{ Notes about man page -.\" - use the pseudo-macros .sh( and .sh) to begin and end sh-specific -.\" text and .ksh( and .ksh) for ksh specific text. -.\" - put i.e., e.g. and etc. in italics -.\"}}} -.\"{{{ To do -.\" todo: Things not covered that should be: -.\" - distinguish (POSIX) special built-in's, (POSIX) regular built-in's, -.\" and sh/ksh weirdo built-in's (put S,R,X superscripts after command -.\" name in built-in commands section?) -.\" - need to be consistent about notation for `See section-name', ` -.\" See description of foobar command', `See section section-name', etc. -.\" - need to use the term `external command' meaning `a command that is -.\" executed using execve(2)' (as opposed to a built-in command or -.\" function) for more clear description. -.\"}}} -.\"{{{ Title -.ksh( -.TH KSH 1 "April 12, 2015" "" "User commands" -.ksh) -.sh( -.TH SH 1 "April 12, 2015" "" "User commands" -.sh) -.\"}}} -.\"{{{ Name -.SH NAME -.ksh( -ksh \- Public domain Korn shell -.ksh) -.sh( -sh \- Public domain Bourne shell -.sh) -.\"}}} -.\"{{{ Synopsis -.SH SYNOPSIS -.ad l -.ksh( -\fBksh\fP -.ksh) -.sh( -\fBsh\fP -.sh) -[\fB\(+-abCefhikmnprsuvxX\fP] [\fB\(+-o\fP \fIoption\fP] [ [ \fB\-c\fP \fIcommand-string\fP [\fIcommand-name\fP] | \fB\-s\fP | \fIfile\fP ] [\fIargument\fP ...] ] -.ad b -.\"}}} -.\"{{{ Description -.SH DESCRIPTION -.ksh( -\fBksh\fP is a command interpreter that is intended for both -interactive and shell script use. -Its command language is a superset of the \fIsh\fP(1) shell language. -.ksh) -.sh( -\fBsh\fP is a re-implementation of the Bourne shell, a command -interpreter for both interactive and script use. -.sh) -.\"{{{ Shell Startup -.SS "Shell Startup" -The following options can be specified only on the command line: -.IP "\fB\-c\fP \fIcommand-string\fP" -the shell executes the command(s) contained in \fIcommand-string\fP -.IP \fB\-i\fP -interactive mode \(em see below -.IP \fB\-l\fP -login shell \(em see below -interactive mode \(em see below -.IP \fB\-s\fP -the shell reads commands from standard input; all non-option arguments -are positional parameters -.IP \fB\-r\fP -restricted mode \(em see below -.PP -In addition to the above, the options described in the \fBset\fP built-in -command can also be used on the command line. -.PP -If neither the \fB\-c\fP nor the \fB\-s\fP options are specified, the -first non-option argument specifies the name of a file the shell reads -commands from; if there are no non-option arguments, the shell reads -commands from standard input. -The name of the shell (\fIi.e.\fP, the contents of the \fB$0\fP) parameter -is determined as follows: if the \fB\-c\fP option is used and there is -a non-option argument, it is used as the name; if commands are being -read from a file, the file is used as the name; otherwise the name -the shell was called with (\fIi.e.\fP, argv[0]) is used. -.PP -A shell is \fBinteractive\fP if the \fB\-i\fP option is used or -if both standard input and standard error are attached to a tty. -An interactive shell has job control enabled (if available), -ignores the INT, QUIT and TERM signals, and prints prompts before -reading input (see \fBPS1\fP and \fBPS2\fP parameters). -For non-interactive shells, the \fBtrackall\fP option is on by default -(see \fBset\fP command below). -.PP -A shell is \fBrestricted\fP if the \fB\-r\fP option is used or if either -the basename of the name the shell is invoked with or the \fBSHELL\fP -parameter match the pattern *r*sh (\fIe.g.\fP, rsh, rksh, rpdksh, \fIetc.\fP). -The following restrictions come into effect after the shell processes -any profile and \fB$ENV\fP files: -.nr P2 \n(PD -.nr PD 0 -.IP \ \ \(bu -the \fBcd\fP command is disabled -.IP \ \ \(bu -the \fBSHELL\fP, \fBENV\fP and \fBPATH\fP parameters can't be changed -.IP \ \ \(bu -command names can't be specified with absolute or relative paths -.IP \ \ \(bu -the \fB\-p\fP option of the \fBcommand\fP built-in can't be used -.IP \ \ \(bu -redirections that create files can't be used (\fIi.e.\fP, \fB>\fP, -\fB>|\fP, \fB>>\fP, \fB<>\fP) -.nr PD \n(P2 -.PP -A shell is \fBprivileged\fP if the \fB\-p\fP option is used or if -the real user-id or group-id does not match the effective user-id -or group-id (see \fIgetuid\fP(2), \fIgetgid\fP(2)). -A privileged shell does not process $HOME/.profile nor the \fBENV\fP -parameter (see below), instead the file /etc/suid_profile is processed. -Clearing the privileged option causes the shell to set its effective -user-id (group-id) to its real user-id (group-id). -.PP -If the basename of the name the shell is called with (\fIi.e.\fP, argv[0]) -starts with \fB\-\fP or if the \fB\-l\fP option is used, the shell is assumed -to be a login shell and the shell reads and executes the contents of -\fB/etc/profile\fP, \fB$HOME/.profile\fP and \fB$ENV\fP if they exist and are -readable. -.PP -If the \fBENV\fP parameter is set when the shell starts (or, in the -case of login shells, after any profiles are processed), its value -is subjected to parameter, command, arithmetic and tilde substitution and -the resulting file (if any) is read and executed. -If the \fBENV\fP parameter is not set (and not null) the file \fB$HOME/.kshrc\fP -is included (after the above mentioned substitutions have been performed). -.PP -The exit status of the shell is 127 if the command file specified -on the command line could not be opened, or non-zero if a fatal syntax -error occurred during the execution of a script. -In the absence of fatal errors, the exit status is that of the last -command executed, or zero, if no command is executed. -.\"}}} -.\"{{{ Command Syntax -.SS "Command Syntax" -.\"{{{ words and tokens -The shell begins parsing its input by breaking it into \fIword\fPs. -Words, which are sequences of characters, are delimited by unquoted -\fIwhite-space\fP characters (space, tab and newline) or \fImeta-characters\fP -(\fB<\fP, \fB>\fP, \fB|\fP, \fB;\fP, \fB&\fP, \fB(\fP and \fB)\fP). -Aside from delimiting words, spaces and tabs are ignored, while -newlines usually delimit commands. -The meta-characters are used in building the following tokens: -\fB<\fP, \fB<&\fP, \fB<<\fP, \fB>\fP, \fB>&\fP, \fB>>\fP, \fIetc.\fP are -used to specify redirections (see Input/Output Redirection below); -\fB|\fP is used to create pipelines; -.ksh( -\fB|&\fP is used to create co-processes (see Co-Processes below); -.ksh) -\fB;\fP is used to separate commands; -\fB&\fP is used to create asynchronous pipelines; -\fB&&\fP and \fB||\fP are used to specify conditional execution; -\fB;;\fP is used in \fBcase\fP statements; -.ksh( -\fB((\fP .. \fB))\fP are used in arithmetic expressions; -.ksh) -and lastly, -\fB(\fP .. \fB)\fP are used to create subshells. -.PP -White-space and meta-characters can be quoted individually using -backslash (\fB\e\fP), or in groups using double (\fB"\fP) or single (\fB'\fP) -quotes. -Note that the following characters are also treated specially by the shell and -must be quoted if they are to represent themselves: -\fB\e\fP, \fB"\fP, \fB'\fP, \fB#\fP, \fB$\fP, \fB`\fP, \fB~\fP, \fB{\fP, -\fB}\fP, \fB*\fP, \fB?\fP and \fB[\fP. -The first three of these are the above mentioned quoting characters -(see Quoting below); -\fB#\fP, if used at the beginning of a word, introduces a comment \(em everything -after the \fB#\fP up to the nearest newline is ignored; -\fB$\fP is used to introduce parameter, command and arithmetic substitutions -(see Substitution below); -\fB`\fP introduces an old-style command substitution -(see Substitution below); -\fB~\fP begins a directory expansion (see Tilde Expansion below); -\fB{\fP and \fB}\fP delimit \fIcsh\fP(1) style alternations -(see Brace Expansion below); -and, finally, \fB*\fP, \fB?\fP and \fB[\fP are used in file name generation -(see File Name Patterns below). -.\"}}} -.\"{{{ simple-command -.PP -As words and tokens are parsed, the shell builds commands, of which -there are two basic types: \fIsimple-commands\fP, typically programs -that are executed, and \fIcompound-commands\fP, such as \fBfor\fP and -\fBif\fP statements, grouping constructs and function definitions. -.PP -A simple-command consists of some combination of parameter assignments (see -Parameters below), input/output redirections (see Input/Output Redirections -below), and command words; the only restriction is that parameter assignments -come before any command words. -The command words, if any, define the command that is to be executed and its -arguments. -The command may be a shell built-in command, a function or an \fIexternal -command\fP, \fIi.e.\fP, a separate executable file that is located using the -\fBPATH\fP parameter (see Command Execution below). -Note that all command constructs have an \fIexit status\fP: for external -commands, this is related to the status returned by \fIwait\fP(2) (if the -command could not be found, the exit status is 127, if it could not be -executed, the exit status is 126); -the exit status of other command constructs (built-in commands, functions, -compound-commands, pipelines, lists, \fIetc.\fP) are all well defined and are -described where the construct is described. -The exit status of a command consisting only of parameter assignments is that -of the last command substitution performed during the parameter assignment -or zero if there were no command substitutions. -.\"}}} -.\"{{{ pipeline -.PP -Commands can be chained together using the \fB|\fP token to -form \fIpipelines\fP, in which the standard output of each command but -the last is piped (see \fIpipe\fP(2)) to the standard input of the following -command. -The exit status of a pipeline is that of its last command. -A pipeline may be prefixed by the \fB!\fP reserved word which -causes the exit status of the pipeline to be logically -complemented: if the original status was 0 the complemented status will -be 1, and if the original status was not 0, then the complemented -status will be 0. -.\"}}} -.\"{{{ lists -.PP -\fILists\fP of commands can be created by separating pipelines by -any of the following tokens: \fB&&\fP, \fB||\fP, \fB&\fP, \fB|&\fP and \fB;\fP. -The first two are for conditional execution: \fIcmd1\fP \fB&&\fP \fIcmd2\fP -executes \fIcmd2\fP only if the exit status of \fIcmd1\fP is zero; -\fB||\fP is the opposite \(em \fIcmd2\fP is executed only if the exit status -of \fIcmd1\fP is non-zero. -\fB&&\fP and \fB||\fP have equal precedence which is higher than that of -\fB&\fP, \fB|&\fP and \fB;\fP, which also have equal precedence. -The \fB&\fP token causes the preceding command to be executed asynchronously, -that is, the shell starts the command, but does not wait for it to complete -(the shell does keep track of the status of asynchronous commands \(em see -Job Control below). -When an asynchronous command is started when job control is disabled -(\fIi.e.\fP, in most scripts), the command is started with signals INT -and QUIT ignored and with input redirected from /dev/null -(however, redirections specified in the asynchronous command have precedence). -.ksh( -The \fB|&\fP operator starts a \fIco-process\fP which is special kind of -asynchronous process (see Co-Processes below). -.ksh) -Note that a command must follow the \fB&&\fP and \fB||\fP operators, while -a command need not follow \fB&\fP, \fB|&\fP and \fB;\fP. -The exit status of a list is that of the last command executed, with the -exception of asynchronous lists, for which the exit status is 0. -.\"}}} -.\"{{{ compound-commands -.PP -Compound commands are created using the following reserved words \(em these -words are only recognized if they are unquoted and if they are used as -the first word of a command (\fIi.e.\fP, they can't be preceded by parameter -assignments or redirections): -.TS -center; -lfB lfB lfB lfB lfB . -case else function then ! -do esac if time [[ -done fi in until { -elif for select while } -.TE -\fBNote:\fP Some shells (but not this one) execute control structure commands -in a subshell when one or more of their file descriptors are redirected, so -any environment changes inside them may fail. -To be portable, the \fBexec\fP statement should be used instead to redirect -file descriptors before the control structure. -.PP -In the following compound command descriptions, command lists (denoted as -\fIlist\fP) that are followed by reserved words must end with a -semi-colon, a newline or a (syntactically correct) reserved word. -For example, -.RS -\fB{ echo foo; echo bar; }\fP -.br -\fB{ echo foo; echo bar}\fP -.br -\fB{ { echo foo; echo bar; } }\fP -.RE -are all valid, but -.RS -\fB{ echo foo; echo bar }\fP -.RE -is not. -.\"{{{ ( list ) -.IP "\fB(\fP \fIlist\fP \fB)\fP" -Execute \fIlist\fP in a subshell. -There is no implicit way to pass -environment changes from a subshell back to its parent. -.\"}}} -.\"{{{ { list } -.IP "\fB{\fP \fIlist\fP \fB}\fP" -Compound construct; \fIlist\fP is executed, but not in a subshell. -Note that \fB{\fP and \fB}\fP are reserved words, not meta-characters. -.\"}}} -.\"{{{ case word in [ [ ( ] pattern [ | pattern ] ... ) list ;; ] ... esac -.IP "\fBcase\fP \fIword\fP \fBin\fP [ [\fB(\fP] \fIpattern\fP [\fB|\fP \fIpattern\fP] ... \fB)\fP \fIlist\fP \fB;;\fP ] ... \fBesac\fP" -The \fBcase\fP statement attempts to match \fIword\fP against the specified -\fIpattern\fPs; the \fIlist\fP associated with the first successfully matched -pattern is executed. -Patterns used in \fBcase\fP statements are the same as -those used for file name patterns except that the restrictions regarding -\fB\&.\fP and \fB/\fP are dropped. -Note that any unquoted space before and -after a pattern is stripped; any space with a pattern must be quoted. -Both the word and the patterns are subject to parameter, command, and -arithmetic substitution as well as tilde substitution. -For historical reasons, open and close braces may be used instead -of \fBin\fP and \fBesac\fP (\fIe.g.\fP, \fBcase $foo { *) echo bar; }\fP). -The exit status of a \fBcase\fP statement is that of the executed \fIlist\fP; -if no \fIlist\fP is executed, the exit status is zero. -.\"}}} -.\"{{{ for name [ in word ... term ] do list done -.IP "\fBfor\fP \fIname\fP [ \fBin\fP \fIword\fP ... \fIterm\fP ] \fBdo\fP \fIlist\fP \fBdone\fP" -where \fIterm\fP is either a newline or a \fB;\fP. -For each \fIword\fP in the specified word list, the parameter \fIname\fP is -set to the word and \fIlist\fP is executed. -If \fBin\fP is not used to -specify a word list, the positional parameters (\fB"$1"\fP, \fB"$2"\fP, -\fIetc.\fP) are used instead. -For historical reasons, open and close braces may be used instead -of \fBdo\fP and \fBdone\fP (\fIe.g.\fP, \fBfor i; { echo $i; }\fP). -The exit status of a \fBfor\fP statement is the last exit status -of \fIlist\fP; if \fIlist\fP is never executed, the exit status is zero. -.\"}}} -.\"{{{ if list then list [ elif list then list ] ... [ else list ] fi -.IP "\fBif\fP \fIlist\fP \fBthen\fP \fIlist\fP [\fBelif\fP \fIlist\fP \fBthen\fP \fIlist\fP] ... [\fBelse\fP \fIlist\fP] \fBfi\fP" -If the exit status of the first \fIlist\fP is zero, the second \fIlist\fP -is executed; otherwise the \fIlist\fP following the \fBelif\fP, if any, is -executed with similar consequences. -If all the lists following the \fBif\fP -and \fBelif\fPs fail (\fIi.e.\fP, exit with non-zero status), the \fIlist\fP -following the \fBelse\fP is executed. -The exit status of an \fBif\fP statement is that -of non-conditional \fIlist\fP that is executed; if no non-conditional -\fIlist\fP is executed, the exit status is zero. -.\"}}} -.\"{{{ select name [ in word ... ] do list done -.ksh( -.IP "\fBselect\fP \fIname\fP [ \fBin\fP \fIword\fP ... \fIterm\fP ] \fBdo\fP \fIlist\fP \fBdone\fP" -where \fIterm\fP is either a newline or a \fB;\fP. -The \fBselect\fP statement provides an automatic method of presenting -the user with a menu and selecting from it. -An enumerated list of the specified \fIwords\fP is printed on standard -error, followed by a prompt (\fBPS3\fP, normally `\fB#? \fP'). -A number corresponding to one of the enumerated words is then read -from standard input, \fIname\fP is set to the selected word (or is -unset if the selection is not valid), \fBREPLY\fP -is set to what was read (leading/trailing space is stripped), -and \fIlist\fP is executed. -If a blank line (\fIi.e.\fP, zero or more \fBIFS\fP characters) is entered, -the menu is re-printed without executing \fIlist\fP. -When \fIlist\fP completes, the enumerated list is printed if \fBREPLY\fP -is null, the prompt is printed and so on. -This process is continues until an end-of-file is read, an interrupt is -received or a break statement is executed inside the loop. -If \fBin\fP \fIword\fP \fB\&...\fP is omitted, the positional parameters -are used (\fIi.e.\fP, \fB"$1"\fP, \fB"$2"\fP, \fIetc.\fP). -For historical reasons, open and close braces may be used instead -of \fBdo\fP and \fBdone\fP (\fIe.g.\fP, \fBselect i; { echo $i; }\fP). -The exit status of a \fBselect\fP statement is zero if a break statement -is used to exit the loop, non-zero otherwise. -.ksh) -.\"}}} -.\"{{{ until list do list done -.IP "\fBuntil\fP \fIlist\fP \fBdo\fP \fIlist\fP \fBdone\fP" -This works like \fBwhile\fP, except that the body is executed only while the -exit status of the first \fIlist\fP is non-zero. -.\"}}} -.\"{{{ while list do list done -.IP "\fBwhile\fP \fIlist\fP \fBdo\fP \fIlist\fP \fBdone\fP" -A \fBwhile\fP is a prechecked loop. -Its body is executed as often -as the exit status of the first \fIlist\fP is zero. -The exit status of a \fBwhile\fP statement is the last exit status -of the \fIlist\fP in the body of the loop; if the body is not executed, -the exit status is zero. -.\"}}} -.\"{{{ function name { list } -.IP "\fBfunction\fP \fIname\fP \fB{\fP \fIlist\fP \fB}\fP" -Defines the function \fIname\fP. -See Functions below. -Note that redirections specified after a function definition are -performed whenever the function is executed, not when the function -definition is executed. -.\"}}} -.\"{{{ name () command -.IP "\fIname\fP \fB()\fP \fIcommand\fP" -Mostly the same as \fBfunction\fP. -See Functions below. -.\"}}} -.\"{{{ time [-p] [ pipeline ] -.IP "\fBtime\fP [ \fB-p\fP ] [ \fIpipeline\fP ]" -The \fBtime\fP reserved word is described in the Command Execution section. -.\"}}} -.\"{{{ (( expression )) -.ksh( -.IP "\fB((\fP \fIexpression\fP \fB))\fP" -The arithmetic expression \fIexpression\fP is evaluated; -equivalent to \fBlet "\fP\fIexpression\fP\fB"\fP. -See Arithmetic Expressions and the \fBlet\fP command below. -.ksh) -.\"}}} -.\"{{{ [[ expression ]] -.ksh( -.IP "\fB[[\fP \fIexpression\fP \fB]]\fP" -Similar to the \fBtest\fP and \fB[\fP \&... \fB]\fP commands (described later), -with the following exceptions: -.RS -.nr P2 \n(PD -.nr PD 0 -.IP \ \ \(bu -Field splitting and file name generation are not performed on -arguments. -.IP \ \ \(bu -The \fB\-a\fP (and) and \fB\-o\fP (or) operators are replaced with -\fB&&\fP and \fB||\fP, respectively. -.IP \ \ \(bu -Operators (\fIe.g.\fP, \fB\-f\fP, \fB=\fP, \fB!\fP, \fIetc.\fP) must be unquoted. -.IP \ \ \(bu -The second operand of \fB!=\fP and \fB=\fP -expressions are patterns (\fIe.g.\fP, the comparison in -.ce -\fB[[ foobar = f*r ]]\fP -succeeds). -.IP \ \ \(bu -There are two additional binary operators: \fB<\fP and \fB>\fP -which return true if their first string operand is less than, -or greater than, their second string operand, respectively. -.IP \ \ \(bu -The single argument form -of \fBtest\fP, which tests if the argument has non-zero length, is not valid -- explicit operators must always be used, \fIe.g.\fP, instead of -.ce -\fB[\fP \fIstr\fP \fB]\fP -use -.ce -\fB[[ \-n \fP\fIstr\fP\fB ]]\fP -.IP \ \ \(bu -Parameter, command and arithmetic substitutions are performed as -expressions are evaluated and lazy expression evaluation is used for -the \fB&&\fP and \fB||\fP operators. -This means that in the statement -.ce -\fB[[ -r foo && $(< foo) = b*r ]]\fP -the \fB$(< foo)\fP is evaluated if and only if the file \fBfoo\fP exists -and is readable. -.nr PD \n(P2 -.RE -.ksh) -.\"}}} -.\"}}} -.\"}}} -.\"{{{ Quoting -.SS Quoting -Quoting is used to prevent the shell from treating characters or words -specially. -There are three methods of quoting: First, \fB\e\fP quotes -the following character, unless it is at the end of a line, in which -case both the \fB\e\fP and the newline are stripped. -Second, a single quote (\fB'\fP) quotes everything up to the next single -quote (this may span lines). -Third, a double quote (\fB"\fP) quotes all characters, -except \fB$\fP, \fB`\fP and \fB\e\fP, up to the next unquoted double quote. -\fB$\fP and \fB`\fP inside double quotes have their usual meaning (\fIi.e.\fP, -parameter, command or arithmetic substitution) except no field splitting -is carried out on the results of double-quoted substitutions. -If a \fB\e\fP inside a double-quoted string is followed by \fB\e\fP, \fB$\fP, -\fB`\fP or \fB"\fP, it is replaced by the second character; if it is -followed by a newline, both the \fB\e\fP and the newline are stripped; -otherwise, both the \fB\e\fP and the character following are unchanged. -.PP -Note: An earlier version of ksh(1) changed the interpretation of sequences -of the form \fB"\fP...\fB`\fP...\fB\e"\fP...\fB`\fP..\fB"\fP -according to whether or not POSIX mode was in effect. -In the current implementation, the backslash in \fB\e"\fP -is seen and removed by the outer \fB"\fP...\fB"\fP, -so the backslash is not seen by the inner \fB`\fP...\fB`\fP. -.\"}}} -.\"{{{ Aliases -.SS "Aliases" -There are two types of aliases: normal command aliases and tracked aliases. -Command aliases are normally used as a short hand for a long -or often used command. -The shell expands command aliases (\fIi.e.\fP, -substitutes the alias name for its value) when it reads the first word -of a command. -An expanded alias is re-processed to check for more -aliases. -If a command alias ends in a space or tab, the following word -is also checked for alias expansion. -The alias expansion process stops -when a word that is not an alias is found, when a quoted word is found -or when an alias word that is currently being expanded is found. -.PP -The following command aliases are defined automatically by the shell: -.ft B -.RS -.ksh( -autoload='typeset \-fu' -.br -functions='typeset \-f' -.br -.ksh) -hash='alias \-t' -.ksh( -.br -history='fc \-l' -.br -integer='typeset \-i' -.br -local='typeset' -.br -login='exec login' -.\" ifndef __NetBSD__ -.\" .br -.\" newgrp='exec newgrp' -.\" endif -.br -nohup='nohup ' -.br -r='fc \-e \-' -.br -stop='kill \-STOP' -.br -suspend='kill \-STOP $$' -.ksh) -.br -type='whence \-v' -.RE -.ft P -.PP -Tracked aliases allow the shell to remember where it found a particular -command. -The first time the shell does a path search for a command that -is marked as a tracked alias, it saves the full path of the command. -The next time the command is executed, the shell checks the saved path -to see that it is still valid, and if so, avoids repeating the path search. -Tracked aliases can be listed and created using \fBalias \-t\fP. -Note that changing the \fBPATH\fP parameter clears the saved -paths for all tracked aliases. -If the \fBtrackall\fP option is set (\fIi.e.\fP, -\fBset \-o trackall\fP or \fBset \-h\fP), the shell tracks all commands. -This option is set automatically for non-interactive shells. -For interactive shells, only the following commands are automatically -tracked: \fBcat\fP, \fBcc\fP, \fBchmod\fP, \fBcp\fP, \fBdate\fP, \fBed\fP, -\fBemacs\fP, \fBgrep\fP, \fBls\fP, \fBmail\fP, \fBmake\fP, \fBmv\fP, -\fBpr\fP, \fBrm\fP, \fBsed\fP, \fBsh\fP, \fBvi\fP and \fBwho\fP. -.\"}}} -.\"{{{ Substitution -.SS "Substitution" -The first step the shell takes in executing a simple-command is to -perform substitutions on the words of the command. -There are three kinds of substitution: parameter, command and arithmetic. -Parameter substitutions, which are described in detail in the next section, -take the form \fB$name\fP or \fB${\fP...\fB}\fP; command substitutions take -the form \fB$(\fP\fIcommand\fP\fB)\fP or \fB`\fP\fIcommand\fP\fB`\fP; -and arithmetic substitutions take the form \fB$((\fP\fIexpression\fP\fB))\fP. -.PP -If a substitution appears outside of double quotes, the results of the -substitution are generally subject to word or field splitting according to -the current value of the \fBIFS\fP parameter. -The \fBIFS\fP parameter specifies a list of characters which -are used to break a string up into several words; -any characters from the set space, tab and newline that appear in the -IFS characters are called \fIIFS white space\fP. -Sequences of one or more IFS white space characters, in combination with -zero or one non-IFS white space characters delimit a field. -As a special case, leading and trailing IFS white space is stripped (\fIi.e.\fP, -no leading or trailing empty field is created by it); leading or trailing -non-IFS white space does create an empty field. -Example: if \fBIFS\fP is set to `:', the sequence of characters -`A:B::D' contains four fields: `A', `B', `' and `D'. -Note that if the \fBIFS\fP parameter is set to the null string, no -field splitting is done; if the parameter is unset, the default value -of space, tab and newline is used. -.PP -The results of substitution are, unless otherwise specified, also subject -to brace expansion and file name expansion (see the relevant sections -below). -.PP -A command substitution is replaced by the output generated by the specified -command, which is run in a subshell. -For \fB$(\fP\fIcommand\fP\fB)\fP substitutions, normal quoting rules -are used when \fIcommand\fP is parsed, however, for the -\fB`\fP\fIcommand\fP\fB`\fP form, a \fB\e\fP followed by any of -\fB$\fP, \fB`\fP or \fB\e\fP is stripped (a \fB\e\fP followed by any other -character is unchanged). -As a special case in command substitutions, a command of the form -\fB<\fP \fIfile\fP is interpreted to mean substitute the contents -of \fIfile\fP ($(< foo) has the same effect as $(cat foo), but it -is carried out more efficiently because no process is started). -.br -.\"todo: fix this( $(..) parenthesis counting). -NOTE: \fB$(\fP\fIcommand\fP\fB)\fP expressions are currently parsed by -finding the matching parenthesis, regardless of quoting. -This will hopefully be fixed soon. -.PP -Arithmetic substitutions are replaced by the value of the specified -expression. -For example, the command \fBecho $((2+3*4))\fP prints 14. -See Arithmetic Expressions for a description of an \fIexpression\fP. -.\"}}} -.\"{{{ Parameters -.SS "Parameters" -Parameters are shell variables; they can be assigned values and -their values can be accessed using a parameter substitution. -A parameter name is either one of the special single punctuation or digit -character parameters described below, or a letter followed by zero or more -letters or digits (`_' counts as a letter). -The later form can be treated as arrays by appending an array -index of the form: \fB[\fP\fIexpr\fP\fB]\fP where \fIexpr\fP is -an arithmetic expression. -Array indices are currently limited to the range 0 through 1023, inclusive. -Parameter substitutions take the form \fB$\fP\fIname\fP, -\fB${\fP\fIname\fP\fB}\fP or -\fB${\fP\fIname\fP\fB[\fP\fIexpr\fP\fB]}\fP, where \fIname\fP is a -parameter name. -If substitution is performed on a parameter (or an array parameter element) -that is not set, a null -string is substituted unless the \fBnounset\fP option (\fBset \-o nounset\fP -or \fBset \-u\fP) is set, in which case an error occurs. -.PP -.\"{{{ parameter assignment -Parameters can be assigned values in a number of ways. -First, the shell implicitly sets some parameters like \fB#\fP, \fBPWD\fP, -etc.; this is the only way the special single character parameters are -set. -Second, parameters are imported from the shell's environment at startup. -Third, parameters can be assigned values on the command line, for example, -`\fBFOO=bar\fP' sets the parameter FOO to bar; multiple parameter -assignments can be given on a single command line and they can -be followed by a simple-command, in which case the assignments are -in effect only for the duration of the command (such assignments are -also exported, see below for implications of this). -Note that both the parameter name and the \fB=\fP must be unquoted for -the shell to recognize a parameter assignment. -The fourth way of setting a parameter is with the \fBexport\fP, \fBreadonly\fP -and \fBtypeset\fP commands; see their descriptions in the Command Execution -section. -Fifth, \fBfor\fP and \fBselect\fP loops set parameters as well as -the \fBgetopts\fP, \fBread\fP and \fBset \-A\fP commands. -Lastly, parameters can be assigned values using assignment operators -inside arithmetic expressions (see Arithmetic Expressions below) or -using the \fB${\fP\fIname\fP\fB=\fP\fIvalue\fP\fB}\fP form -of parameter substitution (see below). -.\"}}} -.PP -.\"{{{ environment -Parameters with the export attribute (set using the \fBexport\fP or -\fBtypeset \-x\fP commands, or by parameter assignments followed by simple -commands) are put in the environment (see \fIenviron\fP(7)) of commands -run by the shell as \fIname\fP\fB=\fP\fIvalue\fP pairs. -The order in which parameters appear in the environment of a command -is unspecified. -When the shell starts up, it extracts parameters and their values from its -environment and automatically sets the export attribute for those parameters. -.\"}}} -.\"{{{ ${name[:][-+=?]word} -.PP -Modifiers can be applied to the \fB${\fP\fIname\fP\fB}\fP form of parameter -substitution: -.IP \fB${\fP\fIname\fP\fB:-\fP\fIword\fP\fB}\fP -if \fIname\fP is set and not null, it is substituted, otherwise \fIword\fP is -substituted. -.IP \fB${\fP\fIname\fP\fB:+\fP\fIword\fP\fB}\fP -if \fIname\fP is set and not null, \fIword\fP is substituted, otherwise nothing is substituted. -.IP \fB${\fP\fIname\fP\fB:=\fP\fIword\fP\fB}\fP -if \fIname\fP is set and not null, it is substituted, otherwise it is -assigned \fIword\fP and the resulting value of \fIname\fP is substituted. -.IP \fB${\fP\fIname\fP\fB:?\fP\fIword\fP\fB}\fP -if \fIname\fP is set and not null, it is substituted, otherwise \fIword\fP -is printed on standard error (preceded by \fIname\fP:) and an error occurs -(normally causing termination of a shell script, function or \&.-script). -If word is omitted the string `parameter null or not set' is used instead. -.PP -In the above modifiers, the \fB:\fP can be omitted, in which case the -conditions only depend on \fIname\fP being set (as opposed to set and -not null). -If \fIword\fP is needed, parameter, command, arithmetic and tilde substitution -are performed on it; if \fIword\fP is not needed, it is not evaluated. -.\"}}} -.PP -The following forms of parameter substitution can also be used: -.\"{{{ ${#name} -.IP \fB${#\fP\fIname\fP\fB}\fP -The number of positional parameters if \fIname\fP is \fB*\fP, \fB@\fP or -is not specified, -or the length of the string value of parameter \fIname\fP. -.\"}}} -.\"{{{ ${#name[*]}, ${#name[@]} -.IP "\fB${#\fP\fIname\fP\fB[*]}\fP, \fB${#\fP\fIname\fP\fB[@]}\fP" -The number of elements in the array \fIname\fP. -.\"}}} -.\"{{{ ${name#pattern}, ${name##pattern} -.IP "\fB${\fP\fIname\fP\fB#\fP\fIpattern\fP\fB}\fP, \fB${\fP\fIname\fP\fB##\fP\fIpattern\fP\fB}\fP" -If \fIpattern\fP matches the beginning of the value of parameter \fIname\fP, -the matched text is deleted from the result of substitution. -A single \fB#\fP results in the shortest match, two \fB#\fP's results in the -longest match. -.\"}}} -.\"{{{ ${name%pattern}, ${name%%pattern} -.IP "\fB${\fP\fIname\fP\fB%\fP\fIpattern\fP\fB}\fP, \fB${\fP\fIname\fP\fB%%\fP\fIpattern\fP\fB}\fP" -Like \fB${\fP..\fB#\fP..\fB}\fP substitution, but it deletes from the end of the -value. -.\"}}} -.\"{{{ special shell parameters -.PP -The following special parameters are implicitly set by the shell and cannot be -set directly using assignments: -.\"{{{ ! -.IP \fB!\fP -Process id of the last background process started. -If no background processes have been started, the parameter is not set. -.\"}}} -.\"{{{ # -.IP \fB#\fP -The number of positional parameters (\fIi.e.\fP, \fB$1\fP, \fB$2\fP, -\fIetc.\fP). -.\"}}} -.\"{{{ $ -.IP \fB$\fP -The process ID of the shell, or the PID of the original shell if -it is a subshell. -.\"}}} -.\"{{{ - -.IP \fB\-\fP -The concatenation of the current single letter options -(see \fBset\fP command below for list of options). -.\"}}} -.\"{{{ ? -.IP \fB?\fP -The exit status of the last non-asynchronous command executed. -If the last command was killed by a signal, \fB$?\fP is set to 128 plus -the signal number. -.\"}}} -.\"{{{ 0 -.IP "\fB0\fP" -The name the shell was invoked with (\fIi.e.\fP, \fBargv[0]\fP), or the -\fBcommand-name\fP if it was invoked with the \fB\-c\fP option and the -\fBcommand-name\fP was supplied, or the \fIfile\fP argument, if it was -supplied. -If the \fBposix\fP option is not set, \fB$0\fP is the name of the current -function or script. -.\"}}} -.\"{{{ 1-9 -.IP "\fB1\fP ... \fB9\fP" -The first nine positional parameters that were supplied to the shell, -function or \fB.\fP-script. -Further positional parameters may be accessed using -\fB${\fP\fInumber\fP\fB}\fP. -.\"}}} -.\"{{{ * -.IP \fB*\fP -All positional parameters (except parameter 0), -\fIi.e.\fP, \fB$1 $2 $3\fP.... -If used outside of double quotes, parameters are separate words -(which are subjected to word splitting); if used within double quotes, -parameters are separated by the first character of the \fBIFS\fP parameter -(or the empty string if \fBIFS\fP is null). -.\"}}} -.\"{{{ @ -.IP \fB@\fP -Same as \fB$*\fP, unless it is used inside double quotes, in which case -a separate word is generated for each positional parameter \- if there -are no positional parameters, no word is generated ("$@" can be used -to access arguments, verbatim, without losing null arguments or -splitting arguments with spaces). -.\"}}} -.\"}}} -.\"{{{ general shell parameters -.PP -The following parameters are set and/or used by the shell: -.\"{{{ _ -.ksh( -.IP "\fB_\fP \fI(underscore)\fP" -When an external command is executed by the shell, this parameter is -set in the environment of the new process to the path of the executed -command. -In interactive use, this parameter is also set in the parent shell to -the last word of the previous command. -When \fBMAILPATH\fP messages are evaluated, this parameter contains -the name of the file that changed (see \fBMAILPATH\fP parameter below). -.ksh) -.\"}}} -.\"{{{ CDPATH -.IP \fBCDPATH\fP -Search path for the \fBcd\fP built-in command. -Works the same way as -\fBPATH\fP for those directories not beginning with \fB/\fP in \fBcd\fP -commands. -Note that if CDPATH is set and does not contain \fB.\fP nor an empty path, -the current directory is not searched. -.\"}}} -.\"{{{ COLUMNS -.IP \fBCOLUMNS\fP -Set to the number of columns on the terminal or window. -Currently set to the \fBcols\fP value as reported by \fIstty\fP(1) if that -value is non-zero. -This parameter is used by the interactive line editing modes, and by -\fBselect\fP, \fBset \-o\fP and \fBkill \-l\fP commands -to format information in columns. -.\"}}} -.\"{{{ EDITOR -.ksh( -.IP \fBEDITOR\fP -If the \fBVISUAL\fP parameter is not set, this parameter controls the -command line editing mode for interactive shells. -See \fBVISUAL\fP parameter below for how this works. -.ksh) -.\"}}} -.\"{{{ ENV -.IP \fBENV\fP -If this parameter is found to be set after any profile files are -executed, the expanded value is used as a shell start-up file. -It typically contains function and alias definitions. -.\"}}} -.\"{{{ ERRNO -.IP \fBERRNO\fP -Integer value of the shell's errno variable \(em indicates the reason -the last system call failed. -.\" todo: ERRNO variable -.sp -Not implemented yet. -.\"}}} -.\"{{{ EXECSHELL -.IP \fBEXECSHELL\fP -If set, this parameter is assumed to contain the shell that is to be -used to execute commands that \fIexecve\fP(2) fails to execute and -which do not start with a `\fB#!\fP \fIshell\fP' sequence. -.\"}}} -.\"{{{ FCEDIT -.IP \fBFCEDIT\fP -The editor used by the \fBfc\fP command (see below). -.\"}}} -.\"{{{ FPATH -.IP \fBFPATH\fP -Like \fBPATH\fP, but used when an undefined function is executed to locate -the file defining the function. -It is also searched when a command can't be found using \fBPATH\fP. -See Functions below for more information. -.\"}}} -.\"{{{ HISTFILE -.ksh( -.IP \fBHISTFILE\fP -The name of the file used to store history. -When assigned to, history is loaded from the specified file. -Also, several invocations of the -shell running on the same machine will share history if their -\fBHISTFILE\fP parameters all point at the same file. -.br -NOTE: if HISTFILE isn't set, no history file is used. -This is -different from the original Korn shell, which uses \fB$HOME/.sh_history\fP; -in future, pdksh may also use a default history file. -.ksh) -.\"}}} -.\"{{{ HISTSIZE -.ksh( -.IP \fBHISTSIZE\fP -The number of commands normally stored for history, default 128. -.ksh) -.\"}}} -.\"{{{ HOME -.IP \fBHOME\fP -The default directory for the \fBcd\fP command and the value -substituted for an unqualified \fB~\fP (see Tilde Expansion below). -.\"}}} -.\"{{{ IFS -.IP \fBIFS\fP -Internal field separator, used during substitution and by the \fBread\fP -command, to split values into distinct arguments; normally set to -space, tab and newline. -See Substitution above for details. -.br -\fBNote:\fP this parameter is not imported from the environment -when the shell is started. -.\"}}} -.\"{{{ KSH_VERSION -.ksh( -.IP \fBKSH_VERSION\fP -The version of shell and the date the version was created (readonly). -See also the version commands in Emacs Editing Mode -and Vi Editing Mode sections, below. -.ksh) -.\"}}} -.\"{{{ SH_VERSION -.sh( -.IP \fBSH_VERSION\fP -The version of shell and the date the version was created (readonly). -.sh) -.\"}}} -.\"{{{ LINENO -.IP \fBLINENO\fP -The line number of the function or shell script that is currently being -executed. -.\"}}} -.\"{{{ LINES -.IP \fBLINES\fP -Set to the number of lines on the terminal or window. -.\"Currently set to the \fBrows\fP value as reported by \fIstty\fP(1) if that -.\"value is non-zero. -.\" todo: LINES variable -.sp -Not implemented yet. -.\"}}} -.\"{{{ MAIL -.ksh( -.IP \fBMAIL\fP -If set, the user will be informed of the arrival of mail in the named file. -This parameter is ignored if the \fBMAILPATH\fP parameter is set. -.ksh) -.\"}}} -.\"{{{ MAILCHECK -.ksh( -.IP \fBMAILCHECK\fP -How often, in seconds, the shell will check for mail in the file(s) -specified by \fBMAIL\fP or \fBMAILPATH\fP. -If 0, the shell checks before each prompt. -The default is 600 (10 minutes). -.ksh) -.\"}}} -.\"{{{ MAILPATH -.ksh( -.IP \fBMAILPATH\fP -A list of files to be checked for mail. -The list is colon separated, -and each file may be followed by a \fB?\fP and a message to be printed -if new mail has arrived. -Command, parameter and arithmetic substitution is -performed on the message, and, during substitution, the parameter \fB$_\fP -contains the name of the file. -The default message is \fByou have mail in $_\fP. -.ksh) -.\"}}} -.\"{{{ OLDPWD -.IP \fBOLDPWD\fP -The previous working directory. -Unset if \fBcd\fP has not successfully changed directories since the -shell started, or if the shell doesn't know where it is. -.\"}}} -.\"{{{ OPTARG -.IP \fBOPTARG\fP -When using \fBgetopts\fP, it contains the argument for a parsed option, -if it requires one. -.\"}}} -.\"{{{ OPTIND -.IP \fBOPTIND\fP -The index of the last argument processed when using \fBgetopts\fP. -Assigning 1 to this parameter causes \fBgetopts\fP to -process arguments from the beginning the next time it is invoked. -.\"}}} -.\"{{{ PATH -.IP \fBPATH\fP -A colon separated list of directories that are searched when looking -for commands and \fB.\fP'd files. -An empty string resulting from a leading or trailing colon, or two adjacent -colons is treated as a `.', the current directory. -.\"}}} -.\"{{{ POSIXLY_CORRECT -.IP \fBPOSIXLY_CORRECT\fP -If set, this parameter causes the \fBposix\fP option to be enabled. -See POSIX Mode below. -.\"}}} -.\"{{{ PPID -.IP \fBPPID\fP -The process ID of the shell's parent (readonly). -.\"}}} -.\"{{{ PS1 -.IP \fBPS1\fP -\fBPS1\fP is the primary prompt for interactive shells. -.ksh( -Parameter, command and arithmetic substitutions are performed, and -\fB!\fP is replaced with the current command number (see \fBfc\fP -command below). -A literal ! can be put in the prompt by placing !! in PS1. -Note that since the command line editors try to figure out how long the -prompt is (so they know how far it is to edge of the screen), -escape codes in the prompt tend to mess things up. -You can tell the shell not to count certain sequences (such as escape codes) -by prefixing your prompt with a non-printing character (such as control-A) -followed by a carriage return and then delimiting the escape codes with -this non-printing character. -If you don't have any non-printing characters, you're out of luck... -BTW, don't blame me for this hack; it's in the original ksh. -.ksh) -.sh( -The prompt is printed verbatim (\fIi.e.\fP, no substitutions are done). -.sh) -Default is `\fB$\ \fP' for non-root users, `\fB#\ \fP' for root. -.\"}}} -.\"{{{ PS2 -.IP \fBPS2\fP -Secondary prompt string, by default `\fB>\fP ', used when more input is -needed to complete a command. -.\"}}} -.\"{{{ PS3 -.ksh( -.IP \fBPS3\fP -Prompt used by \fBselect\fP statement when reading a menu selection. -Default is `\fB#?\ \fP'. -.ksh) -.\"}}} -.\"{{{ PS4 -.IP \fBPS4\fP -Used to prefix commands that are printed during execution tracing -(see \fBset \-x\fP command below). -.ksh( -Parameter, command and arithmetic substitutions are performed -before it is printed. -.ksh) -.sh( -The prompt is printed verbatim (\fIi.e.\fP, no substitutions are done). -.sh) -Default is `\fB+\ \fP'. -.\"}}} -.\"{{{ PWD -.IP \fBPWD\fP -The current working directory. -Maybe unset or null if shell doesn't know where it is. -.\"}}} -.\"{{{ RANDOM -.ksh( -.IP \fBRANDOM\fP -A simple random number generator. -Every time \fBRANDOM\fP is -referenced, it is assigned the next number in a random number series. -The point in the series can be set by assigning a number to -\fBRANDOM\fP (see \fIrand\fP(3)). -.ksh) -.\"}}} -.\"{{{ REPLY -.IP \fBREPLY\fP -Default parameter for the \fBread\fP command if no names are given. -Also used in \fBselect\fP loops to store the value that is read from -standard input. -.\"}}} -.\"{{{ SECONDS -.ksh( -.IP \fBSECONDS\fP -The number of seconds since the shell started or, if the parameter has been -assigned an integer value, the number of seconds since the assignment plus -the value that was assigned. -.ksh) -.\"}}} -.\"{{{ TMOUT -.ksh( -.IP \fBTMOUT\fP -If set to a positive integer in an interactive shell, it specifies -the maximum number of seconds the shell will wait for input after -printing the primary prompt (\fBPS1\fP). -If the time is exceeded, the shell exits. -.ksh) -.\"}}} -.\"{{{ TMPDIR -.IP \fBTMPDIR\fP -The directory shell temporary files are created in. -If this parameter is not set, or does not contain the absolute path of a -writable directory, temporary files are created in \fB/tmp\fP. -.\"}}} -.\"{{{ VISUAL -.ksh( -.IP \fBVISUAL\fP -If set, this parameter controls the command line editing mode for -interactive shells. -If the last component of the path specified in this -parameter contains the string \fBvi\fP, \fBemacs\fP or \fBgmacs\fP, the -vi, emacs or gmacs (Gosling emacs) editing mode is enabled, respectively. -.ksh) -.\"}}} -.\"}}} -.\"}}} -.\"{{{ Tilde Expansion -.SS "Tilde Expansion" -Tilde expansion, which is done in parallel with parameter substitution, -is done on words starting with an unquoted \fB~\fP. -The characters following the tilde, up to the first \fB/\fP, if any, -are assumed to be a login name. -If the login name is empty, \fB+\fP or \fB\-\fP, the -value of the \fBHOME\fP, \fBPWD\fP, or \fBOLDPWD\fP parameter is -substituted, respectively. -Otherwise, the password file is searched for the login name, and the -tilde expression is substituted with the user's home directory. -If the login name is not found in the password -file or if any quoting or parameter substitution occurs in the login name, -no substitution is performed. -.PP -In parameter assignments (those preceding a simple-command or those -occurring in the arguments of \fBalias\fP, \fBexport\fP, \fBreadonly\fP, -and \fBtypeset\fP), tilde expansion is done after any unquoted colon -(\fB:\fP), and login names are also delimited by colons. -.PP -The home directory of previously expanded login names are cached and -re-used. -The \fBalias \-d\fP command may be used to list, change and -add to this cache (\fIe.g.\fP, `alias \-d fac=/usr/local/facilities; cd -~fac/bin'). -.\"}}} -.\"{{{ Brace Expansion -.ksh( -.SS "Brace Expansion (alternation)" -Brace expressions, which take the form -.RS -\fIprefix\fP\fB{\fP\fIstr\fP1\fB,\fP...\fB,\fP\fIstr\fPN\fB}\fP\fIsuffix\fP -.RE -are expanded to N words, each of which is the concatenation of -\fIprefix\fP, \fIstr\fPi and \fIsuffix\fP -(\fIe.g.\fP, `a{c,b{X,Y},d}e' expands to four word: ace, abXe, abYe, and ade). -As noted in the example, brace expressions can be nested and the resulting -words are not sorted. -Brace expressions must contain an unquoted comma (\fB,\fP) for expansion -to occur (\fIi.e.\fP, \fB{}\fP and \fB{foo}\fP are not expanded). -Brace expansion is carried out after parameter substitution and before -file name generation. -.ksh) -.\"}}} -.\"{{{ File Name Patterns -.SS "File Name Patterns" -.PP -A file name pattern is a word containing one or more unquoted \fB?\fP or -\fB*\fP characters or \fB[\fP..\fB]\fP sequences. -Once brace expansion has -been performed, the shell replaces file name patterns with the sorted names -of all the files that match the pattern (if no files match, the word is -left unchanged). -The pattern elements have the following meaning: -.IP \fB?\fP -matches any single character. -.IP \fB*\fP -matches any sequence of characters. -.IP \fB[\fP..\fB]\fP -matches any of the characters inside the brackets. -Ranges of characters -can be specified by separating two characters by a \fB\-\fP, \fIe.g.\fP, -\fB[a0\-9]\fP matches the letter \fBa\fP or any digit. -In order to represent itself, a -\fB\-\fP must either be quoted or the first or last character in the character -list. -Similarly, a \fB]\fP must be quoted or the first character in the list -if it is represent itself instead of the end of the list. -Also, a \fB!\fP -appearing at the start of the list has special meaning (see below), so to -represent itself it must be quoted or appear later in the list. -.IP \fB[!\fP..\fB]\fP -like \fB[\fP..\fB]\fP, except it matches any character not inside the brackets. -.ksh( -.IP "\fB*(\fP\fIpattern\fP\fB|\fP ... \fP|\fP\fIpattern\fP\fB)\fP" -matches any string of characters that matches zero or more occurrences -of the specified patterns. -Example: the pattern \fB*(foo|bar)\fP matches the strings -`', `foo', `bar', `foobarfoo', \fIetc.\fP. -.IP "\fB+(\fP\fIpattern\fP\fB|\fP ... \fP|\fP\fIpattern\fP\fB)\fP" -matches any string of characters that matches one or more occurrences -of the specified patterns. -Example: the pattern \fB+(foo|bar)\fP matches the strings -`foo', `bar', `foobarfoo', \fIetc.\fP. -.IP "\fB?(\fP\fIpattern\fP\fB|\fP ... \fP|\fP\fIpattern\fP\fB)\fP" -matches the empty string or a string that matches one of the -specified patterns. -Example: the pattern \fB?(foo|bar)\fP only matches the strings -`', `foo' and `bar'. -.IP "\fB@(\fP\fIpattern\fP\fB|\fP ... \fP|\fP\fIpattern\fP\fB)\fP" -matches a string that matches one of the -specified patterns. -Example: the pattern \fB@(foo|bar)\fP only matches the strings -`foo' and `bar'. -.IP "\fB!(\fP\fIpattern\fP\fB|\fP ... \fP|\fP\fIpattern\fP\fB)\fP" -matches any string that does not match one of the specified -patterns. -Examples: the pattern \fB!(foo|bar)\fP matches all strings except -`foo' and `bar'; the pattern \fB!(*)\fP matches no strings; -the pattern \fB!(?)*\fP matches all strings (think about it). -.ksh) -.PP -Note that pdksh currently never matches \fB.\fP and \fB..\fP, but the original -ksh, Bourne sh and bash do, so this may have to change (too bad). -.PP -Note that none of the above pattern elements match either a period (\fB.\fP) -at the start of a file name or a slash (\fB/\fP), even if they are explicitly -used in a \fB[\fP..\fB]\fP sequence; also, the names \fB.\fP and \fB..\fP -are never matched, even by the pattern \fB.*\fP. -.PP -If the \fBmarkdirs\fP option is set, any directories that result from -file name generation are marked with a trailing \fB/\fP. -.PP -.\" todo: implement this ([[:alpha:]], \fIetc.\fP) -The POSIX character classes (\fIi.e.\fP, -\fB[:\fP\fIclass-name\fP\fB:]\fP inside a \fB[\fP..\fB]\fP expression) -are not yet implemented. -.\"}}} -.\"{{{ Input/Output Redirection -.SS "Input/Output Redirection" -When a command is executed, its standard input, standard output and -standard error (file descriptors 0, 1 and 2, respectively) are normally -inherited from the shell. -Three exceptions to this are commands in pipelines, for which standard input -and/or standard output are those set up by the pipeline, asynchronous commands -created when job control is disabled, for which standard input is initially -set to be from \fB/dev/null\fP, and commands for which any of the following -redirections have been specified: -.IP "\fB>\fP \fIfile\fP" -standard output is redirected to \fIfile\fP. -If \fIfile\fP does not exist, -it is created; if it does exist, is a regular file and the \fBnoclobber\fP -option is set, an error occurs, otherwise the file is truncated. -Note that this means the command \fIcmd < foo > foo\fP will open -\fIfoo\fP for reading and then truncate it when it opens it for writing, -before \fIcmd\fP gets a chance to actually read \fIfoo\fP. -.IP "\fB>|\fP \fIfile\fP" -same as \fB>\fP, except the file is truncated, even if the \fBnoclobber\fP -option is set. -.IP "\fB>>\fP \fIfile\fP" -same as \fB>\fP, except the file an existing file is appended to instead -of being truncated. -Also, the file is opened in append mode, so writes -always go to the end of the file (see \fIopen\fP(2)). -.IP "\fB<\fP \fIfile\fP" -standard input is redirected from \fIfile\fP, which is opened for reading. -.IP "\fB<>\fP \fIfile\fP" -same as \fB<\fP, except the file is opened for reading and writing. -.IP "\fB<<\fP \fImarker\fP" -after reading the command line containing this kind of redirection (called a -here document), the shell copies lines from the command source into a temporary -file until a line matching \fImarker\fP is read. -When the command is executed, standard input is redirected from the temporary -file. -If \fImarker\fP contains no quoted characters, the contents of the -temporary file are processed as if enclosed in double quotes each time -the command is executed, so parameter, command and arithmetic substitutions -are performed, along with backslash (\fB\e\fP) escapes for -\fB$\fP, \fB`\fP, \fB\e\fP and \fB\enewline\fP. -If multiple here documents are used on the same command line, they are -saved in order. -.IP "\fB<<-\fP \fImarker\fP" -same as \fB<<\fP, except leading tabs are stripped from lines in the -here document. -.IP "\fB<&\fP \fIfd\fP" -standard input is duplicated from file descriptor \fIfd\fP. -\fIfd\fP can be a single digit, indicating the number of an existing -file descriptor, the letter \fBp\fP, indicating the file descriptor -associated with the output of the current co-process, or -the character \fB\-\fP, indicating standard input is to be closed. -.IP "\fB>&\fP \fIfd\fP" -same as \fB<&\fP, except the operation is done on standard output. -.PP -In any of the above redirections, the file descriptor that is redirected -(\fIi.e.\fP, standard input or standard output) can be explicitly given by -preceding the redirection with a single digit. -Parameter, command and arithmetic substitutions, tilde substitutions and -(if the shell is interactive) file name generation are all performed -on the \fIfile\fP, \fImarker\fP and \fIfd\fP arguments of redirections. -Note however, that the results of any file name generation are only used -if a single file is matched; if multiple files match, the word with the -unexpanded file name generation characters is used. -Note that in restricted shells, redirections which can create files cannot -be used. -.PP -For simple-commands, redirections may appear anywhere in the command, for -compound-commands (\fBif\fP statements, \fIetc.\fP), any redirections must -appear at the end. -Redirections are processed after pipelines are created and in the order they -are given, so -.RS -\fBcat /foo/bar 2>&1 > /dev/null | cat \-n\fP -.RE -will print an error with a line number prepended to it. -.\"}}} -.\"{{{ Arithmetic Expressions -.SS "Arithmetic Expressions" -Integer arithmetic expressions can be used -.ksh( -with the \fBlet\fP command, -.ksh) -inside \fB$((\fP..\fB))\fP expressions, -inside array references (\fIe.g.\fP, \fIname\fP\fB[\fP\fIexpr\fP\fB]\fP), -as numeric arguments to the \fBtest\fP command, -and as the value of an assignment to an integer parameter. -.PP -Expression may contain alpha-numeric parameter identifiers, array -references, and integer constants and may be combined with the -following C operators (listed and grouped in increasing order of precedence). -.TP -Unary operators: -\fB+ \- ! ~ ++ --\fP -.TP -Binary operators: -\fB,\fP -.br -\fB= *= /= %= += \-= <<= >>= &= ^= |=\fP -.br -\fB||\fP -.br -\fB&&\fP -.br -\fB|\fP -.br -\fB^\fP -.br -\fB&\fP -.br -\fB== !=\fP -.br -\fB< <= >= >\fP -.br -\fB<< >>\fP -.br -\fB+ \-\fP -.br -\fB* / %\fP -.TP -Ternary operator: -\fB?:\fP (precedence is immediately higher than assignment) -.TP -Grouping operators: -\fB( )\fP -.PP -Integer constants may be specified with arbitrary bases using the notation -\fIbase\fP\fB#\fP\fInumber\fP, where \fIbase\fP is a decimal integer specifying -the base, and \fInumber\fP is a number in the specified base. -.LP -The operators are evaluated as follows: -.RS -.IP "unary \fB+\fP" -result is the argument (included for completeness). -.IP "unary \fB\-\fP" -negation. -.IP "\fB!\fP" -logical not; the result is 1 if argument is zero, 0 if not. -.IP "\fB~\fP" -arithmetic (bit-wise) not. -.IP "\fB++\fP" -increment; must be applied to a parameter (not a literal or other -expression) - the parameter is incremented by 1. -When used as a prefix operator, the result is the incremented value of -the parameter, when used as a postfix operator, the result is the -original value of the parameter. -.IP "\fB--\fP" -similar to \fB++\fP, except the parameter is decremented by 1. -.IP "\fB,\fP" -separates two arithmetic expressions; the left hand side is evaluated first, -then the right. -The result is value of the expression on the right hand side. -.IP "\fB=\fP" -assignment; variable on the left is set to the value on the right. -.IP "\fB*= /= %= += \-= <<= >>= &= ^= |=\fP" -assignment operators; \fI \fP\fB=\fP \fI\fP is the same as -\fI\fP \fB=\fP \fI \fP \fB(\fP \fI\fP \fB)\fP. -.IP "\fB||\fP" -logical or; the result is 1 if either argument is non-zero, 0 if not. -The right argument is evaluated only if the left argument is zero. -.IP "\fB&&\fP" -logical and; the result is 1 if both arguments are non-zero, 0 if not. -The right argument is evaluated only if the left argument is non-zero. -.IP "\fB|\fP" -arithmetic (bit-wise) or. -.IP "\fB^\fP" -arithmetic (bit-wise) exclusive-or. -.IP "\fB&\fP" -arithmetic (bit-wise) and. -.IP "\fB==\fP" -equal; the result is 1 if both arguments are equal, 0 if not. -.IP "\fB!=\fP" -not equal; the result is 0 if both arguments are equal, 1 if not. -.IP "\fB<\fP" -less than; the result is 1 if the left argument is less than the right, -0 if not. -.IP "\fB<= >= >\fP" -less than or equal, greater than or equal, greater than. -See <. -.IP "\fB<< >>\fP" -shift left (right); the result is the left argument with its bits shifted -left (right) by the amount given in the right argument. -.IP "\fB+ - * /\fP" -addition, subtraction, multiplication, and division. -.IP "\fB%\fP" -remainder; the result is the remainder of the division of the left argument -by the right. -The sign of the result is unspecified if either argument is negative. -.IP "\fI\fP \fB?\fP \fI\fP \fB:\fP \fI\fP" -if \fI\fP is non-zero, the result is \fI\fP, -otherwise \fI\fP. -.RE -.\"}}} -.\"{{{ Co-Processes -.ksh( -.SS "Co-Processes" -A co-process, which is a pipeline created with the \fB|&\fP operator, -is an asynchronous process that the shell can both write to -(using \fBprint \-p\fP) and read from (using \fBread \-p\fP). -The input and output of the co-process can also be manipulated -using \fB>&p\fP and \fB<&p\fP redirections, respectively. -Once a co-process has been started, another can't be started until -the co-process exits, or until the co-process input has been redirected using -an \fBexec \fP\fIn\fP\fB>&p\fP redirection. -If a co-process's input is redirected in this way, the next -co-process to be started will share the output with the first co-process, -unless the output of the initial co-process has been redirected using an -\fBexec \fP\fIn\fP\fB<&p\fP redirection. -.PP -Some notes concerning co-processes: -.nr P2 \n(PD -.nr PD 0 -.IP \ \ \(bu -the only way to close the co-process input (so the co-process reads -an end-of-file) is to redirect the input to a numbered file descriptor -and then close that file descriptor (\fIe.g.\fP, \fBexec 3>&p;exec 3>&-\fP). -.IP \ \ \(bu -in order for co-processes to share a common output, the shell must keep -the write portion of the output pipe open. -This means that end of file will not be detected until all co-processes -sharing the co-process output have exited (when they all exit, the shell -closes its copy of the pipe). -This can be avoided by redirecting the output to a numbered -file descriptor (as this also causes the shell to close its copy). -Note that this behaviour is slightly different from the original Korn shell -which closes its copy of the write portion of the co-processes' output when the -most recently started co-process (instead of when all sharing co-processes) -exits. -.IP \ \ \(bu -\fBprint \-p\fP will ignore SIGPIPE signals during writes -if the signal is not being trapped or ignored; the same is not true if -the co-process input has been duplicated to another file descriptor and -\fBprint \-u\fP\fIn\fP is used. -.nr PD \n(P2 -.ksh) -.\"}}} -.\"{{{ Functions -.SS "Functions" -Functions are defined using either Korn shell \fBfunction\fP \fIname\fP -syntax or the Bourne/POSIX shell \fIname\fP\fB()\fP syntax -(see below for the difference between the two forms). -Functions are like \fB.\fP-scripts in that they are executed in -the current environment, however, unlike \fB.\fP-scripts, shell arguments -(\fIi.e.\fP, positional parameters, \fB$1\fP, \fIetc.\fP) are never visible -inside them. -When the shell is determining the location of a command, functions are -searched after special built-in commands, and before regular and non-regular -built-ins, and before the \fBPATH\fP is searched. -.PP -An existing function may be deleted using \fBunset \-f\fP \fIfunction-name\fP. -A list of functions can be obtained using \fBtypeset +f\fP and the -function definitions can be listed using \fBtypeset \-f\fP. -\fBautoload\fP (which is an alias for \fBtypeset \-fu\fP) may be used to -create undefined functions; when an undefined function is executed, the -shell searches the path specified in the \fBFPATH\fP parameter for a file -with the same name as the function, which, if found is read and executed. -If after executing the file, the named function is found to be defined, the -function is executed, otherwise, the normal command search is continued -(\fIi.e.\fP, the shell searches the regular built-in command table -and \fBPATH\fP). -Note that if a command is not found using \fBPATH\fP, an attempt is -made to autoload a function using \fBFPATH\fP (this is an undocumented -feature of the original Korn shell). -.PP -Functions can have two attributes, trace and export, which can be set -with \fBtypeset \-ft\fP and \fBtypeset \-fx\fP, respectively. -When a traced function is executed, the shell's \fBxtrace\fP option is turned -on for the functions duration, otherwise the \fBxtrace\fP option is turned off. -The export attribute of functions is currently not used. -In the original -Korn shell, exported functions are visible to shell scripts that are executed. -.PP -Since functions are executed in the current shell environment, parameter -assignments made inside functions are visible after the function completes. -If this is not the desired effect, the \fBtypeset\fP command can be used -inside a function to create a local parameter. -Note that special parameters (\fIe.g.\fP, \fB$$\fP, \fB$!\fP) can't be -scoped in this way. -.PP -The exit status of a function is that of the last command executed in -the function. -A function can be made to finish immediately using the \fBreturn\fP command; -this may also be used to explicitly specify the exit status. -.PP -Functions defined with the \fBfunction\fP reserved word are -treated differently in the following ways from functions defined with -the \fB()\fP notation: -.nr P2 \n(PD -.nr PD 0 -.IP \ \ \(bu -the \fB$0\fP parameter is set to the name of the function -(Bourne-style functions leave \fB$0\fP untouched). -.IP \ \ \(bu -parameter assignments preceding function calls are not kept in -the shell environment -(executing Bourne-style functions will keep assignments). -.IP \ \ \(bu -\fBOPTIND\fP is saved/reset and restored on entry and exit from the function -so \fBgetopts\fP can be used properly both inside and outside the function -(Bourne-style functions leave \fBOPTIND\fP untouched, so using \fBgetopts\fP -inside a function interferes with using \fBgetopts\fP outside the function). -.nr PD \n(P2 -In the future, the following differences will also be added: -.nr P2 \n(PD -.nr PD 0 -.IP \ \ \(bu -A separate trap/signal environment will be used during the execution of -functions. -This will mean that traps set inside a function will not affect the shell's -traps and signals that are not ignored in the shell (but may be trapped) will -have their default effect in a function. -.IP \ \ \(bu -The EXIT trap, if set in a function, will be executed after the function -returns. -.nr PD \n(P2 -.\"}}} -.\"{{{ POSIX mode -.SS "POSIX Mode" -The shell is intended to be POSIX compliant, however, in some cases, POSIX -behaviour is contrary either to the original Korn shell behaviour or to -user convenience. -How the shell behaves in these cases is determined by the state of -the posix option (\fBset \-o posix\fP) \(em if it is on, the POSIX behaviour -is followed, otherwise it is not. -The \fBposix\fP option is set automatically when the shell starts up -if the environment contains the \fBPOSIXLY_CORRECT\fP parameter. -(The shell can also be compiled so that it is in POSIX mode by default, -however this is usually not desirable). -.PP -The following is a list of things that are affected by the state of -the \fBposix\fP option: -.nr P2 \n(PD -.nr PD 0 -.sh( -.IP \ \ \(bu -reading of \fB$ENV\fP: if not in posix mode, the \fBENV\fP parameter -is not expanded and included when the shell starts. -.sh) -.\" The following behaviour is not useful and has been removed in NetBSD -.\" .IP \ \ \(bu -.\" \fB\e"\fP inside double quoted \fB`\fP..\fB`\fP command substitutions: -.\" in posix mode, the \fB\e"\fP is interpreted when the command is interpreted; -.\" in non-posix mode, the backslash is stripped before the command substitution -.\" is interpreted. -.\" For example, \fBecho "`echo \e"hi\e"`"\fP produces `"hi"' in -.\" posix mode, `hi' in non-posix mode. -.\" To avoid problems, use the \fB$(...\fP) -.\" form of command substitution. -.IP \ \ \(bu -\fBkill \-l\fP output: in posix mode, signal names are listed one a single line; -in non-posix mode, signal numbers, names and descriptions are printed in -columns. -In future, a new option (\fB\-v\fP perhaps) will be added to distinguish -the two behaviours. -.IP \ \ \(bu -\fBfg\fP exit status: in posix mode, the exit status is 0 if no errors occur; -in non-posix mode, the exit status is that of the last foregrounded job. -.IP \ \ \(bu -\fBeval\fP exit status: if eval gets to see an empty command (\fIe.g.\fP, -\fBeval "`false`"\fP), its exit status in posix mode will be 0. -In non-posix mode, it will be the exit status of the last -command substitution that was done in the processing of the arguments to eval -(or 0 if there were no command substitutions). -.IP \ \ \(bu -\fBgetopts\fP: in posix mode, options must start with a \fB\-\fP; in non-posix -mode, options can start with either \fB\-\fP or \fB+\fP. -.IP \ \ \(bu -brace expansion (also known as alternation): in posix mode, brace expansion -is disabled; in non-posix mode, brace expansion enabled. -Note that \fBset \-o posix\fP (or setting the \fBPOSIXLY_CORRECT\fP parameter) -automatically turns the \fBbraceexpand\fP option off, however it can be -explicitly turned on later. -.IP \ \ \(bu -\fBset \-\fP: in posix mode, this does not clear the \fBverbose\fP or -\fBxtrace\fP options; in non-posix mode, it does. -.IP \ \ \(bu -\fBset\fP exit status: in posix mode, the exit status of set is 0 -if there are no errors; in non-posix mode, the exit status is that of -any command substitutions performed in generating the set command. -For example, `\fBset \-\- `false`; echo $?\fP' prints 0 in posix mode, -1 in non-posix mode. -This construct is used in most shell scripts that -use the old \fIgetopt\fP(1) command. -.IP \ \ \(bu -argument expansion of \fBalias\fP, \fBexport\fP, \fBreadonly\fP, and -\fBtypeset\fP commands: in posix mode, normal argument expansion done; -in non-posix mode, field splitting, file globing, brace expansion and -(normal) tilde expansion are turned off, and assignment tilde expansion -is turned on. -.IP \ \ \(bu -signal specification: in posix mode, signals can be specified as digits only -if signal numbers match POSIX values (\fIi.e.\fP, HUP=1, INT=2, QUIT=3, ABRT=6, -KILL=9, ALRM=14, and TERM=15); in non-posix mode, signals can be always digits. -.IP \ \ \(bu -alias expansion: in posix mode, alias expansion is only carried out when -reading command words; in non-posix mode, alias expansion is carried out -on any word following an alias that ended in a space. -For example, the following for loop -.RS -.ft B -alias a='for ' i='j' -.br -a i in 1 2; do echo i=$i j=$j; done -.ft P -.RE -uses parameter \fBi\fP in posix mode, \fBj\fP in non-posix mode. -.IP \ \ \(bu -test: in posix mode, the expression "\fB-t\fP" (preceded by -some number of "\fB!\fP" arguments) is always true as it is a non-zero length -string; in non-posix mode, it tests if file descriptor 1 is a tty (\fIi.e.\fP, -the \fIfd\fP argument to the \fB-t\fP test may be left out and defaults to 1). -.nr PD \n(P2 -.\"}}} -.\"{{{ Command Execution (built-in commands) -.SS "Command Execution" -After evaluation of command line arguments, redirections and parameter -assignments, the type of command is determined: a special built-in, -a function, a regular built-in or the name of a file to execute found -using the \fBPATH\fP parameter. -The checks are made in the above order. -Special built-in commands differ from other commands in that -the \fBPATH\fP parameter is not used to find them, an error -during their execution can cause a non-interactive shell to exit and -parameter assignments that are specified before the command are -kept after the command completes. -Just to confuse things, if the posix option is turned off (see \fBset\fP -command below) some special commands are very special in that -no field splitting, file globing, brace expansion nor tilde expansion -is performed on arguments that look like assignments. -Regular built-in commands are different only in that the \fBPATH\fP -parameter is not used to find them. -.PP -The original ksh and POSIX differ somewhat in which commands are considered -special or regular: -.IP "POSIX special commands" -.TS -lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB . -\&. continue exit return trap -: eval export set unset -break exec readonly shift -.TE -.IP "Additional ksh special commands" -.TS -lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB . -builtin times typeset -.TE -.IP "Very special commands (non-posix mode)" -.TS -lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB . -alias readonly set typeset -.TE -.IP "POSIX regular commands" -.TS -lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB . -alias command fg kill umask -bg false getopts read unalias -cd fc jobs true wait -.TE -.IP "Additional ksh regular commands" -.TS -lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB lw(8m)fB . -[ let pwd ulimit -echo print test whence -.TE -.PP -In the future, the additional ksh special and regular commands may -be treated differently from the POSIX special and regular commands. -.PP -Once the type of the command has been determined, any command line parameter -assignments are performed and exported for the duration of the command. -.PP -The following describes the special and regular built-in commands: -.\"{{{ . file [ arg1 ... ] -.IP "\fB\&.\fP \fIfile\fP [\fIarg1\fP ...]" -Execute the commands in \fIfile\fP in the current environment. -The file is searched for in the directories of \fBPATH\fP. -If arguments are given, the positional parameters may be used to -access them while \fIfile\fP is being executed. -If no arguments are given, the positional parameters are those of the -environment the command is used in. -.\"}}} -.\"{{{ : [ ... ] -.IP "\fB:\fP [ ... ]" -The null command. -Exit status is set to zero. -.\"}}} -.\"{{{ alias [ -d | +-t [ -r ] ] [+-px] [+-] [name1[=value1] ...] -.IP "\fBalias\fP [ \fB\-d\fP | \fB\(+-t\fP [\fB\-r\fP] ] [\fB\(+-px\fP] [\fB\(+-\fP] [\fIname1\fP[\fB=\fP\fIvalue1\fP] ...]" -Without arguments, \fBalias\fP lists all aliases. -For any name without a value, the existing alias is listed. -Any name with a value defines an alias (see Aliases above). -.sp -When listing aliases, one of two formats is used: -normally, aliases are listed as \fIname\fP\fB=\fP\fIvalue\fP, where -\fIvalue\fP is quoted; if options were preceded with \fB+\fP -or a lone \fB+\fP is given on the command line, only \fIname\fP -is printed. -In addition, if the \fB\-p\fP option is used, each alias -is prefixed with the string "\fBalias\fP\ ". -.sp -The \fB\-x\fP option sets (\fB+x\fP clears) the export attribute of an alias, -or, if no names are given, lists the aliases with the export attribute -(exporting an alias has no affect). -.sp -The \fB\-t\fP option indicates that tracked aliases are to be listed/set -(values specified on the command line are ignored for tracked aliases). -The \fB\-r\fP option indicates that all tracked aliases are to be reset. -.sp -The \fB\-d\fP causes directory aliases, which are used in tilde expansion, -to be listed or set (see Tilde Expansion above). -.\"}}} -.\"{{{ bg [job ...] -.IP "\fBbg\fP [\fIjob\fP ...]" -Resume the specified stopped job(s) in the background. -If no jobs are specified, \fB%+\fP is assumed. -This command is only available on systems which support job control. -See Job Control below for more information. -.\"}}} -.\"{{{ bind [-l] [-m] [key[=editing-command] ...] -.IP "\fBbind\fP [\fB\-l\fP] [\fB\-m\fP] [\fIkey\fP[\fB=\fP\fIediting-command\fP] ...]" -Set or view the current emacs command editing key bindings/macros. -See Emacs Editing Mode below for a complete description. -.\"}}} -.\"{{{ break [level] -.IP "\fBbreak\fP [\fIlevel\fP]" -\fBbreak\fP exits the \fIlevel\fPth inner most for, select, until, or while -loop. -\fIlevel\fP defaults to 1. -.\"}}} -.\"{{{ builtin command [arg1 ...] -.IP "\fBbuiltin\fP \fIcommand\fP [\fIarg1\fP ...]" -Execute the built-in command \fIcommand\fP. -.\"}}} -.\"{{{ cd [-LP] [dir] -.IP "\fBcd\fP [\fB\-LP\fP] [\fIdir\fP]" -Set the working directory to \fIdir\fP. -If the parameter \fBCDPATH\fP -is set, it lists directories to search in for \fIdir\fP. -An empty entry in the \fBCDPATH\fP entry means the current directory. -If a non-empty directory from \fBCDPATH\fP is used, the resulting full -path is printed to standard output. -If \fIdir\fP is -missing, the home directory \fB$HOME\fP is used. -If \fIdir\fP is -\fB\-\fP, the previous working directory is used (see OLDPWD parameter). -If \fB\-L\fP option (logical path) is used or if the \fBphysical\fP option -(see \fBset\fP command below) isn't set, references to \fB..\fP in \fIdir\fP -are relative to the path used get to the directory. -If \fB\-P\fP option (physical path) is used or if the \fBphysical\fP option -is set, \fB..\fP is relative to the filesystem directory tree. -The \fBPWD\fP and \fBOLDPWD\fP parameters are updated to reflect the -current and old wording directory, respectively. -.\"}}} -.\"{{{ cd [-LP] old new -.IP "\fBcd\fP [\fB\-LP\fP] \fIold new\fP" -The string \fInew\fP is substituted for \fIold\fP in the current -directory, and the shell attempts to change to the new directory. -.\"}}} -.\"{{{ command [ -pvV ] cmd [arg1 ...] -.ksh( -.IP "\fBcommand\fP [\fB\-pvV\fP] \fIcmd\fP [\fIarg1\fP ...]" -If neither the \fB\-v\fP nor \fB\-V\fP options are given, -.ksh) -.sh( -.IP "\fBcommand\fP [\fB\-p\fP] \fIcmd\fP [\fIarg1\fP ...]" -.sh) -\fIcmd\fP -is executed exactly as if the \fBcommand\fP had not been specified, -with two exceptions: first, \fIcmd\fP cannot be a shell function, and -second, special built-in commands lose their specialness (\fIi.e.\fP, -redirection and utility errors do not cause the shell to exit, and command -assignments are not permanent). -If the \fB\-p\fP option is given, a default search path is used instead of -the current value of \fBPATH\fP (the actual value of the default path is -system dependent: on POSIXish systems, it is the value returned by -.ce -\fBgetconf CS_PATH\fP -). -.sp -.ksh( -If the \fB\-v\fP option is given, instead of executing \fIcmd\fP, information -about what would be executed is given (and the same is done for -\fIarg1\fP ...): -for special and regular built-in commands and functions, -their names are simply printed, -for aliases, a command that defines them is printed, -and for commands found by searching the \fBPATH\fP parameter, -the full path of the command is printed. -If no command is found, (\fIi.e.\fP, the path search fails), nothing -is printed and \fBcommand\fP exits with a non-zero status. -The \fB\-V\fP option is like the \fB\-v\fP option, except it is more verbose. -.ksh) -.\"}}} -.\"{{{ continue [levels] -.IP "\fBcontinue\fP [\fIlevels\fP]" -\fBcontinue\fP jumps to the beginning of the \fIlevel\fPth inner most for, -select, until, or while loop. -\fIlevel\fP defaults to 1. -.\"}}} -.\"{{{ echo [-neE] [arg ...] -.IP "\fBecho\fP [\fB\-neE\fP] [\fIarg\fP ...]" -Prints its arguments (separated by spaces) followed by a newline, to -standard out. -The newline is suppressed if any of the arguments contain the backslash -sequence \fB\ec\fP. -See \fBprint\fP command below for a list of other backslash sequences -that are recognized. -.sp -The options are provided for compatibility with BSD shell scripts: -\fB\-n\fP suppresses the trailing newline, \fB\-e\fP enables backslash -interpretation (a no-op, since this is normally done), and \fB\-E\fP -suppresses backslash interpretation. -.\"}}} -.\"{{{ eval command ... -.IP "\fBeval\fP \fIcommand ...\fP" -The arguments are concatenated (with spaces between them) to form -a single string which the shell then parses and executes -in the current environment. -.\"}}} -.\"{{{ exec [command [arg ...]] -.IP "\fBexec\fP [\fIcommand\fP [\fIarg\fP ...]]" -The command is executed without forking, replacing the shell process. -.sp -If no arguments are given, any IO redirection is permanent and the shell -is not replaced. -.ksh( -Any file descriptors greater than 2 which are opened or \fIdup\fP(2)-ed -in this way are not -made available to other executed commands (\fIi.e.\fP, -commands that are not built-in to the shell). -Note that the Bourne shell differs here: it does pass these -file descriptors on. -.ksh) -.sh( -Any file descriptors which are opened or \fIdup\fP(2)-ed -in this way are made available to other executed commands -(note that the Korn shell differs here: it does not pass on -file descriptors greater than 2). -.sh) -.\"}}} -.\"{{{ exit [status] -.IP "\fBexit\fP [\fIstatus\fP]" -The shell exits with the specified exit status. -If \fIstatus\fP is not specified, the exit status is the current -value of the \fB?\fP parameter. -.\"}}} -.\"{{{ export [-p] [parameter[=value] ...] -.IP "\fBexport\fP [\fB\-p\fP] [\fIparameter\fP[\fB=\fP\fIvalue\fP]] ..." -Sets the export attribute of the named parameters. -Exported parameters are passed in the environment to executed commands. -If values are specified, the named parameters also assigned. -.sp -If no parameters are specified, the names of all parameters with the export -attribute are printed one per line, unless the \fB\-p\fP option is used, -in which case \fBexport\fP commands defining all exported -parameters, including their values, are printed. -.\"}}} -.\"{{{ false -.IP "\fBfalse\fP" -A command that exits with a non-zero status. -.\"}}} -.\"{{{ fc [-e editor | -l [-n]] [-r] [first [ last ]] -.ksh( -.IP "\fBfc\fP [\fB\-e\fP \fIeditor\fP | \fB\-l\fP [\fB\-n\fP]] [\fB\-r\fP] [\fIfirst\fP [\fIlast\fP]]" -\fIfirst\fP and \fIlast\fP select commands from the history. -Commands can be selected by -history number, or a string specifying the most recent command starting -with that string. -The \fB\-l\fP option lists the command on stdout, -and \fB\-n\fP inhibits the default command numbers. -The \fB\-r\fP option reverses the order of the list. -Without \fB\-l\fP, the selected -commands are edited by the editor specified with the \fB\-e\fP -option, or if no \fB\-e\fP is specified, the editor specified by the -\fBFCEDIT\fP parameter (if this parameter is not set, \fB/bin/ed\fP is used), -and then executed by the shell. -.ksh) -.\"}}} -.\"{{{ fc [-e - | -s] [-g] [old=new] [prefix] -.IP "\fBfc\fP [\fB\-e \-\fP | \fB\-s\fP] [\fB\-g\fP] [\fIold\fP\fB=\fP\fInew\fP] [\fIprefix\fP]" -Re-execute the selected command (the previous command by default) after -performing the optional substitution of \fIold\fP with \fInew\fP. -If \fB\-g\fP is specified, all occurrences of \fIold\fP are replaced with -\fInew\fP. -This command is usually accessed with the predefined alias -\fBr='fc \-e \-'\fP. -.\"}}} -.\"{{{ fg [job ...] -.IP "\fBfg\fP [\fIjob\fP ...]" -Resume the specified job(s) in the foreground. -If no jobs are specified, \fB%+\fP is assumed. -This command is only available on systems which support job control. -See Job Control below for more information. -.\"}}} -.\"{{{ getopts optstring name [arg ...] -.IP "\fBgetopts\fP \fIoptstring\fP \fIname\fP [\fIarg\fP ...]" -\fBgetopts\fP is used by shell procedures to parse the specified arguments -(or positional parameters, if no arguments are given) and to check for legal -options. -\fIoptstring\fP contains the option letters that -\fBgetopts\fP is to recognize. -If a letter is followed by a colon, the option is expected to have an argument. -Options that do not take arguments may be grouped in a single argument. -If an option takes an argument and the option character is not the last -character of the argument it is found in, the remainder of the argument -is taken to be the option's argument, otherwise, the next argument is -the option's argument. -.sp -Each time \fBgetopts\fP is invoked, it places the next option in -the shell parameter \fIname\fP and the index of the next argument to be -processed in the shell parameter \fBOPTIND\fP. -If the option was introduced with a \fB+\fP, the option placed in -\fIname\fP is prefixed with a \fB+\fP. -When an option requires an argument, \fBgetopts\fP places it in the -shell parameter \fBOPTARG\fP. -When an illegal option or a missing option argument is -encountered a question mark or a colon is placed in \fIname\fP -(indicating an illegal option or missing argument, respectively) -and \fBOPTARG\fP is set to the option character that caused the problem. -An error message is also printed to standard error if \fIoptstring\fP -does not begin with a colon. -.sp -When the end of the options is encountered, \fBgetopts\fP exits with a -non-zero exit status. -Options end at the first (non-option) argument that does not -start with a \-, or when a \fB\-\-\fP argument is encountered. -.sp -Option parsing can be reset by setting \fBOPTIND\fP to 1 (this is done -automatically whenever the shell or a shell procedure is invoked). -.sp -Warning: Changing the value of the shell parameter \fBOPTIND\fP to -a value other than 1, or parsing different sets of arguments without -resetting \fBOPTIND\fP may lead to unexpected results. -.\"}}} -.\"{{{ hash [-r] [name ...] -.IP "\fBhash\fP [\fB\-r\fP] [\fIname ...\fP]" -Without arguments, any hashed executable command pathnames are listed. -The \fB\-r\fP option causes all hashed commands to be removed -from the hash table. -Each \fIname\fP is searched as if it where a command name and added to the -hash table if it is an executable command. -.\"}}} -.\"{{{ jobs [-lpn] [job ...] -.IP "\fBjobs\fP [\fB\-lpn\fP] [\fIjob\fP ...]" -Display information about the specified jobs; if no jobs are specified, -all jobs are displayed. -The \fB\-n\fP option causes information to be displayed only for jobs -that have changed state since the last notification. -If the \fB\-l\fP option is used, the process-id of each process in a job -is also listed. -The \fB\-p\fP option causes only the process group of each job to be printed. -See Job Control below for the format of \fIjob\fP and the displayed job. -.\"}}} -.\"{{{ kill [-s signame | -signum | -signame] { job | pid | -pgrp } ... -.IP "\fBkill\fP [\fB\-s\fP \fIsigname\fP | \fB\-signum\fP | \fB\-signame\fP ] { \fIjob\fP | \fIpid\fP | \fB\-\fP\fIpgrp\fP } ..." -Send the specified signal to the specified jobs, process ids, or process groups. -If no signal is specified, the signal TERM is sent. -If a job is specified, the signal is sent to the job's process group. -See Job Control below for the format of \fIjob\fP. -.\"}}} -.\"{{{ kill -l [exit-status ...] -.IP "\fBkill \-l\fP [\fIexit-status\fP ...]" -Print the name of the signal that killed a process which exited with -the specified \fIexit-status\fPes. -If no arguments are specified, a list of all the signals, their numbers and -a short description of them are printed. -.\"}}} -.\"{{{ let [expression ...] -.ksh( -.IP "\fBlet\fP [\fIexpression\fP ...]" -Each expression is evaluated, see Arithmetic Expressions above. -If all expressions are successfully evaluated, the exit status -is 0 (1) if the last expression evaluated to non-zero (zero). -If an error occurs during the parsing or evaluation of an expression, -the exit status is greater than 1. -Since expressions may need to be -quoted, \fB((\fP \fIexpr\fP \fB))\fP is syntactic sugar for \fBlet -"\fP\fIexpr\fP\fB"\fP. -.ksh) -.\"}}} -.\"{{{ print [-nprsun | -R [-en]] [argument ...] -.IP "\fBprint\fP [\fB\-nprsu\fP\fIn\fP | \fB\-R\fP [\fB\-en\fP]] [\fIargument ...\fP]" -\fBPrint\fP prints its arguments on the standard output, separated by -spaces, and terminated with a newline. -The \fB\-n\fP option suppresses the newline. -By default, certain C escapes are translated. -These include \eb, \ef, \en, \er, \et, \ev, and \e0### (# is an octal digit, -of which there may be 0 to 3). -\ec is equivalent to using the \fB\-n\fP option. -\e expansion may be inhibited with the \fB\-r\fP option. -The \fB\-s\fP option prints to the history file instead of standard output, -the \fB\-u\fP option prints to file descriptor \fIn\fP (\fIn\fP -defaults to 1 if omitted), and the \fB\-p\fP option prints to the co-process -(see Co-Processes above). -.sp -The \fB\-R\fP option is used to emulate, to some degree, the BSD echo -command, which does not process \e sequences unless the \fB\-e\fP option -is given. -As above, the \fB\-n\fP option suppresses the trailing newline. -.\"}}} -.\"{{{ pwd [-LP] -.IP "\fBpwd\fP [\fB\-LP\fP]" -Print the present working directory. -If \fB\-L\fP option is used or if the \fBphysical\fP option -(see \fBset\fP command below) isn't set, the logical path is printed -(\fIi.e.\fP, the path used to \fBcd\fP to the current directory). -If \fB\-P\fP option (physical path) is used or if the \fBphysical\fP option -is set, the path determined from the filesystem (by following \fB..\fP -directories to the root directory) is printed. -.\"}}} -.\"{{{ read [-prsun] [parameter ...] -.IP "\fBread\fP [\fB\-prsu\fP\fIn\fP] [\fIparameter ...\fP]" -Reads a line of input from standard input, separate the line into fields using -the \fBIFS\fP parameter (see Substitution above), and assign each field to the -specified parameters. -If there are more parameters than fields, the extra parameters are set to null, -or alternatively, if there are more fields than parameters, the last parameter -is assigned the remaining fields (inclusive of any separating spaces). -If no parameters are specified, the \fBREPLY\fP parameter is used. -If the input line ends in a backslash and the \fB\-r\fP option was not used, the -backslash and newline are stripped and more input is read. -If no input is read, \fBread\fP exits with a non-zero status. -.sp -The first parameter may have a question mark and a string appended to it, in -which case the string is used as a prompt (printed to standard error before -any input is read) if the input is a tty -(\fIe.g.\fP, \fBread nfoo?'number of foos: '\fP). -.sp -The \fB\-u\fP\fIn\fP and \fB\-p\fP options cause input to be read -from file descriptor \fIn\fP or the current co-process (see Co-Processes above -for comments on this), respectively. -If the \fB\-s\fP option is used, input is saved to the history file. -.\"}}} -.\"{{{ readonly [-p] [parameter[=value] ...] -.IP "\fBreadonly\fP [\fB\-p\fP] [\fIparameter\fP[\fB=\fP\fIvalue\fP]] ..." -Sets the readonly attribute of the named parameters. -If values are given, -parameters are set to them before setting the attribute. -Once a parameter is made readonly, it cannot be unset and its value cannot -be changed. -.sp -If no parameters are specified, the names of all parameters with the readonly -attribute are printed one per line, unless the \fB\-p\fP option is used, -in which case \fBreadonly\fP commands defining all readonly -parameters, including their values, are printed. -.\"}}} -.\"{{{ return [status] -.IP "\fBreturn\fP [\fIstatus\fP]" -Returns from a function or \fB.\fP script, with exit status \fIstatus\fP. -If no \fIstatus\fP is given, the exit status of the last executed command -is used. -If used outside of a function or \fB.\fP script, it has the same effect -as \fBexit\fP. -Note that pdksh treats both profile and \fB$ENV\fP files as \fB.\fP scripts, -while the original Korn shell only treats profiles as \fB.\fP scripts. -.\"}}} -.\"{{{ set [+-abCefhkmnpsuvxX] [+-o [option]] [+-A name] [--] [arg ...] -.IP "\fBset\fP [\fB\(+-abCefhkmnpsuvxX\fP] [\fB\(+-o\fP [\fIoption\fP]] [\fB\(+-A\fP \fIname\fP] [\fB\-\-\fP] [\fIarg\fP ...]" -The set command can be used to set (\fB\-\fP) or clear (\fB+\fP) shell options, -set the positional parameters, or set an array parameter. -Options can be changed using the \fB\(+-o\fP \fIoption\fP syntax, -where \fIoption\fP is the long name of an option, or using -the \fB\(+-\fP\fIletter\fP syntax, where \fIletter\fP is the -option's single letter name (not all options have a single letter name). -The following table lists both option letters (if they exist) and long names -along with a description of what the option does. -.sp -.TS -expand; -afB lfB lw(3i). -\-A T{ -Sets the elements of the array parameter \fIname\fP to \fIarg\fP ...; -If \fB\-A\fP is used, the array is reset (\fIi.e.\fP, emptied) first; -if \fB+A\fP is used, the first N elements are set (where N is the number -of \fIarg\fPs), the rest are left untouched. -T} -\-a allexport T{ -all new parameters are created with the export attribute -T} -\-b notify T{ -Print job notification messages asynchronously, instead of just before the -prompt. -Only used if job control is enabled (\fB\-m\fP). -T} -\-C noclobber T{ -Prevent \fB>\fP redirection from overwriting existing files (\fB>|\fP must -be used to force an overwrite). -T} -\-e errexit T{ -Exit (after executing the \fBERR\fP trap) as soon as an error occurs or -a command fails (\fIi.e.\fP, exits with a non-zero status). -This does not apply to commands whose exit status is explicitly tested by a -shell construct such as \fBif\fP, \fBuntil\fP, \fBwhile\fP, \fB&&\fP or -\fB||\fP statements. -T} -\-f noglob T{ -Do not expand file name patterns. -T} -\-h trackall T{ -Create tracked aliases for all executed commands (see Aliases above). -On by default for non-interactive shells. -T} -\-i interactive T{ -Enable interactive mode \- this can only be set/unset when the shell is -invoked. -T} -\-k keyword T{ -Parameter assignments are recognized anywhere in a command. -T} -\-l login T{ -The shell is a login shell \- this can only be set/unset when the shell is -invoked (see Shell Startup above). -T} -\-m monitor T{ -Enable job control (default for interactive shells). -T} -\-n noexec T{ -Do not execute any commands \- useful for checking the syntax of scripts -(ignored if interactive). -T} -\-p privileged T{ -Set automatically if, when the shell starts, the real uid or gid does not -match the effective uid or gid, respectively. -See Shell Startup above for a description of what this means. -T} --r restricted T{ -Enable restricted mode \(em this option can only be used when the shell is -invoked. -See Shell Startup above for a description of what this -means. -T} -\-s stdin T{ -If used when the shell is invoked, commands are read from standard input. -Set automatically if the shell is invoked with no arguments. -.sp -When \fB\-s\fP is used in the \fBset\fP command, it causes the specified -arguments to be sorted before assigning them to the positional parameters -(or to array \fIname\fP, if \fB\-A\fP is used). -T} -\-u nounset T{ -Referencing of an unset parameter is treated as an error, unless -one of the \fB\-\fP, \fB+\fP or \fB=\fP modifiers is used. -T} -\-v verbose T{ -Write shell input to standard error as it is read. -T} -\-x xtrace T{ -Print commands and parameter assignments when they are executed, -preceded by the value of \fBPS4\fP. -T} -\-X markdirs T{ -Mark directories with a trailing \fB/\fP during file name generation. -T} - bgnice T{ -Background jobs are run with lower priority. -T} -.ksh( - braceexpand T{ -Enable brace expansion (aka, alternation). -T} -.ksh) -.ksh( - emacs T{ -Enable BRL emacs-like command line editing (interactive shells only); -see Emacs Editing Mode. -T} - emacs-usemeta T{ -In emacs command-line editing, use the 8th bit -as meta (^[) prefix. This is the default if -LC_CTYPE is unset or POSIX respectively C. -8 -T} - gmacs T{ -Enable gmacs-like (Gosling emacs) command line editing (interactive shells -only); -currently identical to emacs editing except that transpose (^T) acts -slightly differently. -T} -.ksh) - ignoreeof T{ -The shell will not (easily) exit on when end-of-file is read, \fBexit\fP must -be used. -To avoid infinite loops, the shell will exit if eof is read 13 times in -a row. -T} - nohup T{ -Do not kill running jobs with a \fBHUP\fP signal when a login shell exists. -Currently set by default, but this will change in the future to be compatible -with the original Korn shell (which doesn't have this option, but does -send the \fBHUP\fP signal). -T} - nolog T{ -No effect \- in the original Korn shell, this prevents function definitions -from being stored in the history file. -T} - physical T{ -Causes the \fBcd\fP and \fBpwd\fP commands to use `physical' -(\fIi.e.\fP, the filesystem's) \fB..\fP directories instead of `logical' -directories (\fIi.e.\fP, the shell handles \fB..\fP, which allows the user -to be oblivious of symlink links to directories). -Clear by default. -Note that setting -this option does not effect the current value of the \fBPWD\fP parameter; -only the \fBcd\fP command changes \fBPWD\fP. -See the \fBcd\fP and \fBpwd\fP commands above for more details. -T} - posix T{ -Enable posix mode. -See POSIX Mode above. -T} - vi T{ -Enable vi-like command line editing (interactive shells only). -T} - viraw T{ -No effect \- in the original Korn shell, unless viraw was set, the vi command -line mode would let the tty driver do the work until ESC (^[) was entered. -pdksh is always in viraw mode. -T} - vi-esccomplete T{ -In vi command line editing, do command / file name completion when -escape (^[) is entered in command mode. -T} - vi-show8 T{ -Prefix characters with the eighth bit set with `M-'. -If this option is not set, characters in the range -128-160 are printed as is, which may cause problems. -T} - vi-tabcomplete T{ -In vi command line editing, do command / file name completion when -tab (^I) is entered in insert mode. This is the default. -T} -.TE -.sp -These options can also be used upon invocation of the shell. -The current set of options (with single letter names) can be found in the -parameter \fB\-\fP. -\fBset -o\fP with no option name will list all the options and whether each -is on or off; \fBset +o\fP will print the long names of all options that -are currently on. -.sp -Remaining arguments, if any, are positional parameters and are assigned, -in order, to the -positional parameters (\fIi.e.\fP, \fB1\fP, \fB2\fP, \fIetc.\fP). -If options are ended with \fB\-\-\fP and there are no remaining arguments, -all positional parameters are cleared. -If no options or arguments are given, then the values of all names are printed. -For unknown historical reasons, a lone \fB\-\fP option is treated specially: -it clears both the \fB\-x\fP and \fB\-v\fP options. -.\"}}} -.\"{{{ shift [number] -.IP "\fBshift\fP [\fInumber\fP]" -The positional parameters \fInumber\fP+1, \fInumber\fP+2 \fIetc.\fP\& are -renamed to \fB1\fP, \fB2\fP, \fIetc.\fP -\fInumber\fP defaults to 1. -.\"}}} -.\"{{{ test expression, [ expression ] -.IP "\fBtest\fP \fIexpression\fP" -.IP "\fB[\fP \fIexpression\fP \fB]\fP" -\fBtest\fP evaluates the \fIexpression\fP and returns zero status if -true, 1 if false, and greater than 1 if there was an error. -It is normally used as the -condition command of \fBif\fP and \fBwhile\fP statements. -The following basic expressions are available: -.sp -.TS -afB ltw(3.2i). -\fIstr\fP T{ -\fIstr\fP has non-zero length. -Note that there is the potential -for problems if \fIstr\fP turns out to be an operator (\fIe.g.\fP, \fB-r\fP) -- it is generally better to use a test like -.ce -\fB[ X"\fP\fIstr\fP\fB" != X ]\fP -instead (double quotes are used in case \fIstr\fP contains spaces or file -globing characters). -T} -\-r \fIfile\fP T{ -\fIfile\fP exists and is readable. -T} -\-w \fIfile\fP T{ -\fIfile\fP exists and is writable. -T} -\-x \fIfile\fP T{ -\fIfile\fP exists and is executable. -T} -\-a \fIfile\fP T{ -\fIfile\fP exists. -T} -\-e \fIfile\fP T{ -\fIfile\fP exists. -T} -\-f \fIfile\fP T{ -\fIfile\fP is a regular file. -T} -\-d \fIfile\fP T{ -\fIfile\fP is a directory. -T} -\-c \fIfile\fP T{ -\fIfile\fP is a character special device. -T} -\-b \fIfile\fP T{ -\fIfile\fP is a block special device. -T} -\-p \fIfile\fP T{ -\fIfile\fP is a named pipe. -T} -\-u \fIfile\fP T{ -\fIfile\fP's mode has setuid bit set. -T} -\-g \fIfile\fP T{ -\fIfile\fP's mode has setgid bit set. -T} -\-k \fIfile\fP T{ -\fIfile\fP's mode has sticky bit set. -T} -\-s \fIfile\fP T{ -\fIfile\fP is not empty. -T} -\-O \fIfile\fP T{ -\fIfile\fP's owner is the shell's effective user-ID. -T} -\-G \fIfile\fP T{ -\fIfile\fP's group is the shell's effective group-ID. -T} -\-h \fIfile\fP T{ -\fIfile\fP is a symbolic link. -T} -\-H \fIfile\fP T{ -\fIfile\fP is a context dependent directory (only useful on HP-UX). -T} -\-L \fIfile\fP T{ -\fIfile\fP is a symbolic link. -T} -\-S \fIfile\fP T{ -\fIfile\fP is a socket. -T} -\-o \fIoption\fP T{ -shell \fIoption\fP is set (see \fBset\fP command above for list of options). -As a non-standard extension, if the option starts with a \fB!\fP, the test -is negated; the test always fails if option doesn't exist (thus -.ce -\fB[ -o \fP\fIfoo\fP \fB-o -o !\fP\fIfoo\fP \fB]\fP -returns true if and only if option \fIfoo\fP exists). -T} -\fIfile\fP \-nt \fIfile\fP T{ -first \fIfile\fP is newer than second \fIfile\fP or first -\fIfile\fP exists and the second \fIfile\fP does not. -T} -\fIfile\fP \-ot \fIfile\fP T{ -first \fIfile\fP is older than second \fIfile\fP or second \fIfile\fP -exists and the first \fIfile\fP does not. -T} -\fIfile\fP \-ef \fIfile\fP T{ -first \fIfile\fP is the same file as second \fIfile\fP. -T} -\-t\ [\fIfd\fP] T{ -file descriptor is a tty device. -If the posix option (\fBset \-o posix\fP, see POSIX Mode above) is not -set, \fIfd\fP may be left out, in which case it is taken to be 1 -(the behaviour differs due to the special POSIX rules described below). -T} -\fIstring\fP T{ -\fIstring\fP is not empty. -T} -\-z\ \fIstring\fP T{ -\fIstring\fP is empty. -T} -\-n\ \fIstring\fP T{ -\fIstring\fP is not empty. -T} -\fIstring\fP\ =\ \fIstring\fP T{ -strings are equal. -T} -.ksh( -\fIstring\fP\ ==\ \fIstring\fP T{ -strings are equal. -T} -.ksh) -\fIstring\fP\ !=\ \fIstring\fP T{ -strings are not equal. -T} -\fInumber\fP\ \-eq\ \fInumber\fP T{ -numbers compare equal. -T} -\fInumber\fP\ \-ne\ \fInumber\fP T{ -numbers compare not equal. -T} -\fInumber\fP\ \-ge\ \fInumber\fP T{ -numbers compare greater than or equal. -T} -\fInumber\fP\ \-gt\ \fInumber\fP T{ -numbers compare greater than. -T} -\fInumber\fP\ \-le\ \fInumber\fP T{ -numbers compare less than or equal. -T} -\fInumber\fP\ \-lt\ \fInumber\fP T{ -numbers compare less than. -T} -.TE -.sp -The above basic expressions, in which unary operators have precedence over -binary operators, may be combined with the following operators -(listed in increasing order of precedence): -.sp -.TS -afB l. -\fIexpr\fP \-o \fIexpr\fP logical or -\fIexpr\fP \-a \fIexpr\fP logical and -! \fIexpr\fP logical not -( \fIexpr\fP ) grouping -.TE -.sp -On operating systems not supporting \fB/dev/fd/\fP\fIn\fP devices -(where \fIn\fP is a file descriptor number), -the \fBtest\fP command will attempt to fake it for all tests that -operate on files (except the \fB-e\fP test). -I.e., \fB[ -w /dev/fd/2 ]\fP tests if file descriptor 2 is writable. -.sp -Note that some special rules are applied (courtesy of POSIX) if the -number of arguments to \fBtest\fP or \fB[\fP \&... \fB]\fP is less than -five: if leading \fB!\fP arguments can be stripped such that only one -argument remains then a string length test is performed (again, even if -the argument is a unary operator); -if leading \fB!\fP arguments can be stripped such that three -arguments remain and the second argument is a binary operator, then the -binary operation is performed (even if first argument is a unary -operator, including an unstripped \fB!\fP). -.sp -\fBNote:\fP A common mistake is to use \fBif [ $foo = bar ]\fP which -fails if parameter \fBfoo\fP is null or unset, if it has embedded spaces -(\fIi.e.\fP, \fBIFS\fP characters), or if it is a unary operator like \fB!\fP or -\fB\-n\fP. -Use tests like \fBif [ "X$foo" = Xbar ]\fP instead. -.\"}}} -.\"{{{ time [-p] [pipeline] -.IP "\fBtime\fP [\fB-p\fP] [ \fIpipeline\fP ]" -If a pipeline is given, the times used to execute the pipeline are reported. -If no pipeline is given, then the user and system time used by the shell -itself, and all the commands it has run since it was started, are reported. -The times reported are -the real time (elapsed time from start to finish), -the user CPU time (time spent running in user mode) -and the system CPU time (time spent running in kernel mode). -Times are reported to standard error; the format of the output is: -.nf - 0.00s real 0.00s user 0.00s system -.fi -unless the -p option is given (only possible if \fIpipeline\fP is a simple -command), in which case the output is slightly longer: -.nf - real 0.00 - user 0.00 - sys 0.00 -.fi -(the number of digits after the decimal may vary from system to system). -Note that simple redirections of standard error do not effect the output -of the time command: -.ce -\fBtime sleep 1 2> \fP\fIafile\fP -.ce -\fB{ time sleep 1; } 2> \fP\fIafile\fP -times for the first command do not go to \fIafile\fP, but those of the -second command do. -.\"}}} -.\"{{{ times -.IP \fBtimes\fP -Print the accumulated user and system times used by the shell and by -processes which have exited that the shell started. -.\"}}} -.\"{{{ trap [handler signal ...] -.IP "\fBtrap\fP [\fIhandler\fP \fIsignal ...\fP]" -Sets trap handler that is to be executed when any of the specified signals -are received. -\fBHandler\fP is either a null string, indicating the signals are to -be ignored, a minus (\fB\-\fP), indicating that the default action is to -be taken for the signals (see signal(3)), or a string containing shell -commands to be evaluated and executed at the first opportunity (\fIi.e.\fP, -when the current command completes, or before printing the next \fBPS1\fP -prompt) after receipt of one of the signals. -\fBSignal\fP is the name of a signal (\fIe.g.\fP, PIPE or ALRM) or the number -of the signal (see \fBkill \-l\fP command above). -There are two special signals: \fBEXIT\fP (also known as \fB0\fP), which -is executed when the shell is about to exit, and \fBERR\fP which is -executed after an error occurs (an error is something that would cause -the shell to exit if the \fB\-e\fP or \fBerrexit\fP option were set \(em -see \fBset\fP command above). -\fBEXIT\fP handlers are executed in the environment of the last executed -command. -Note that for non-interactive shells, the trap handler cannot be changed for -signals that were ignored when the shell started. -.sp -With no arguments, \fBtrap\fP lists, as a series of \fBtrap\fP commands, -the current state of the traps that have been set since the shell started. -Note that the output of \fBtrap\fP can not be usefully piped to another process -(an artifact of the fact that traps are cleared when subprocesses are -created). -.sp -.\" todo: add these features (trap DEBUG, trap ERR/EXIT in function) -The original Korn shell's \fBDEBUG\fP trap and the handling of \fBERR\fP and -\fBEXIT\fP traps in functions are not yet implemented. -.\"}}} -.\"{{{ true -.IP \fBtrue\fP -A command that exits with a zero value. -.\"}}} -.\"{{{ typeset [[+-Ulprtux] [-L[n]] [-R[n]] [-Z[n]] [-i[n]] | -f [-tux]] [name[=value] ...] -.IP "\fBtypeset\fP [[\(+-Ulprtux] [\fB\-L\fP[\fIn\fP]] [\fB\-R\fP[\fIn\fP]] [\fB\-Z\fP[\fIn\fP]] [\fB\-i\fP[\fIn\fP]] | \fB\-f\fP [\fB\-tux\fP]] [\fIname\fP[\fB=\fP\fIvalue\fP] ...]" -Display or set parameter attributes. -With no \fIname\fP arguments, parameter attributes are displayed: if no options -arg used, the current attributes of all parameters are printed as typeset -commands; if an option is given (or \fB\-\fP with no option letter) -all parameters and their values with the specified attributes are printed; -if options are introduced with \fB+\fP, parameter values are not printed. -.sp -If \fIname\fP arguments are given, the attributes of the named parameters -are set (\fB\-\fP) or cleared (\fB+\fP). -Values for parameters may optionally be specified. -If typeset is used inside a function, any newly created parameters are local -to the function. -.sp -When \fB\-f\fP is used, typeset operates on the attributes of functions. -As with parameters, if no \fIname\fPs are given, functions are listed -with their values (\fIi.e.\fP, definitions) unless options are introduced with -\fB+\fP, in which case only the function names are reported. -.sp -.TS -expand; -afB lw(4.5i). -\-L\fIn\fP T{ -Left justify attribute: \fIn\fP specifies the field width. -If \fIn\fP is not specified, the current width of a parameter (or the -width of its first assigned value) is used. -Leading white space (and zeros, if used with the \fB\-Z\fP option) is stripped. -If necessary, values are either truncated or space padded to fit the -field width. -T} -\-R\fIn\fP T{ -Right justify attribute: \fIn\fP specifies the field width. -If \fIn\fP is not specified, the current width of a parameter (or the -width of its first assigned value) is used. -Trailing white space are stripped. -If necessary, values are either stripped of leading characters -or space padded to make them fit the field width. -T} -\-Z\fIn\fP T{ -Zero fill attribute: if not combined with \fB\-L\fP, this is the -same as \fB\-R\fP, except zero padding is used instead of space padding. -T} -\-i\fIn\fP T{ -integer attribute: -\fIn\fP specifies the base to use when displaying the integer -(if not specified, the base given in the first assignment is used). -Parameters with this attribute may be assigned values containing -arithmetic expressions. -T} -\-U T{ -unsigned integer attribute: integers are printed as unsigned values -(only useful when combined with the \fB\-i\fP option). -This option is not in the original Korn shell. -T} -\-f T{ -Function mode: display or set functions and their attributes, instead of -parameters. -T} -\-l T{ -Lower case attribute: all upper case characters in values are converted to -lower case. -(In the original Korn shell, this parameter meant `long integer' when used -with the \fB\-i\fP option). -T} -\-p T{ -Print complete typeset commands that can be used to re-create the -attributes (but not the values) of parameters. -This is the default action (option exists for ksh93 compatibility). -T} -\-r T{ -Readonly attribute: parameters with the this attribute may not be assigned to -or unset. -Once this attribute is set, it can not be turned off. -T} -\-t T{ -Tag attribute: has no meaning to the shell; provided for application use. -.sp -For functions, \fB\-t\fP is the trace attribute. -When functions with the trace attribute are executed, the \fBxtrace\fP (\fB\-x\fP) shell option is temporarily turned on. -T} -\-u T{ -Upper case attribute: all lower case characters in values are converted to -upper case. -(In the original Korn shell, this parameter meant `unsigned integer' when used -with the \fB\-i\fP option, which meant upper case letters would never be used -for bases greater than 10. -See the \fB\-U\fP option). -.sp -For functions, \fB\-u\fP is the undefined attribute. -See Functions above for the implications of this. -T} -\-x T{ -Export attribute: parameters (or functions) are placed in the environment of -any executed commands. -Exported functions are not implemented yet. -T} -.TE -.\"}}} -.\"{{{ ulimit [-abcdfHlmnprsStvw] [value] -.IP "\fBulimit\fP [\fB\-abcdfHlmnprsStvw\fP] [\fIvalue\fP]" -Display or set process limits. -If no options are used, the file size limit (\fB\-f\fP) is assumed. -\fBvalue\fP, if specified, may be either be an arithmetic expression or the -word \fBunlimited\fP. -The limits affect the shell and any processes created by the shell after -a limit is imposed. -Note that some systems may not allow limits to be increased once they -are set. -Also note that the types of limits available are system dependent \- some -systems have only the \fB\-f\fP limit. -.RS -.IP \fB\-a\fP -Displays all limits; unless \fB\-H\fP is used, soft limits are displayed. -.IP \fB\-H\fP -Set the hard limit only (default is to set both hard and soft limits). -.IP \fB\-S\fP -Set the soft limit only (default is to set both hard and soft limits). -.IP \fB\-b\fP -Impose a size limit of \fIn\fP bytes on the size of socket buffers. -.IP \fB\-c\fP -Impose a size limit of \fIn\fP blocks on the size of core dumps. -.IP \fB\-d\fP -Impose a size limit of \fIn\fP kbytes on the size of the data area. -.IP \fB\-f\fP -Impose a size limit of \fIn\fP blocks on files written by the shell and -its child processes (files of any size may be read). -.IP \fB\-l\fP -Impose a limit of \fIn\fP kbytes on the amount of locked (wired) physical -memory. -.IP \fB\-m\fP -Impose a limit of \fIn\fP kbytes on the amount of physical memory used. -.IP \fB\-n\fP -Impose a limit of \fIn\fP file descriptors that can be open at once. -.IP \fB\-r\fP -Impose a limit of \fIn\fP threads that can be run by the user at any one -time. -.IP \fB\-p\fP -Impose a limit of \fIn\fP processes that can be run by the user at any one -time. -.IP \fB\-s\fP -Impose a size limit of \fIn\fP kbytes on the size of the stack area. -.IP \fB\-t\fP -Impose a time limit of \fIn\fP CPU seconds to be used by each process. -.IP \fB\-v\fP -Impose a limit of \fIn\fP kbytes on the amount of virtual memory used; -on some systems this is the maximum allowable virtual address (in bytes, -not kbytes). -.IP \fB\-w\fP -Impose a limit of \fIn\fP kbytes on the amount of swap space used. -.PP -As far as \fBulimit\fP is concerned, a block is 512 bytes. -.RE -.\"}}} -.\"{{{ umask [-S] [mask] -.IP "\fBumask\fP [\fB\-S\fP] [\fImask\fP]" -.RS -Display or set the file permission creation mask, or umask (see \fIumask\fP(2)). -If the \fB\-S\fP option is used, the mask displayed or set is symbolic, -otherwise it is an octal number. -.sp -Symbolic masks are like those used by \fIchmod\fP(1): -.RS -[\fBugoa\fP]{{\fB=+-\fP}{\fBrwx\fP}*}+[\fB,\fP...] -.RE -in which the first group of characters is the \fIwho\fP part, the second -group is the \fIop\fP part, and the last group is the \fIperm\fP part. -The \fIwho\fP part specifies which part of the umask is to be modified. -The letters mean: -.RS -.IP \fBu\fP -the user permissions -.IP \fBg\fP -the group permissions -.IP \fBo\fP -the other permissions (non-user, non-group) -.IP \fBa\fP -all permissions (user, group and other) -.RE -.sp -The \fIop\fP part indicates how the \fIwho\fP permissions are to be modified: -.RS -.IP \fB=\fP -set -.IP \fB+\fP -added to -.IP \fB\-\fP -removed from -.RE -.sp -The \fIperm\fP part specifies which permissions are to be set, added or removed: -.RS -.IP \fBr\fP -read permission -.IP \fBw\fP -write permission -.IP \fBx\fP -execute permission -.RE -.sp -When symbolic masks are used, they describe what permissions may -be made available (as opposed to octal masks in which a set bit means -the corresponding bit is to be cleared). -Example: `ug=rwx,o=' sets the mask so files will not be readable, writable -or executable by `others', and is equivalent (on most systems) to the octal -mask `07'. -.RE -.\"}}} -.\"{{{ unalias [-adt] name ... -.IP "\fBunalias\fP [\fB\-adt\fP] [\fIname1\fP ...]" -The aliases for the given names are removed. -If the \fB\-a\fP option is used, all aliases are removed. -If the \fB\-t\fP or \fB\-d\fP options are used, the indicated operations -are carried out on tracked or directory aliases, respectively. -.\"}}} -.\"{{{ unset [-fv] parameter ... -.IP "\fBunset\fP [\fB\-fv\fP] \fIparameter\fP ..." -Unset the named parameters (\fB\-v\fP, the default) or functions (\fB\-f\fP). -The exit status is non-zero if any of the parameters were already unset, -zero otherwise. -.\"}}} -.\"{{{ wait [job] -.IP "\fBwait\fP [\fIjob\fP]" -Wait for the specified job(s) to finish. -The exit status of wait is that of the last specified job: -if the last job is killed by a signal, the exit status is 128 + the -number of the signal (see \fBkill \-l\fP \fIexit-status\fP above); if the last -specified job can't be found (because it never existed, or had already -finished), the exit status of wait is 127. -See Job Control below for the format of \fIjob\fP. -\fBWait\fP will return if a signal for which a trap has been set is received, -or if a HUP, INT or QUIT signal is received. -.sp -If no jobs are specified, \fBwait\fP waits for all currently running jobs -(if any) to finish and exits with a zero status. -If job monitoring is enabled, the completion status of jobs is -printed (this is not the case when jobs are explicitly specified). -.\"}}} -.\"{{{ whence [-pv] [name ...] -.IP "\fBwhence\fP [\fB\-pv\fP] [name ...]" -For each name, the type of command is listed (reserved word, built-in, alias, -function, tracked alias or executable). -If the \fB\-p\fP option is used, a path search done even if \fIname\fP -is a reserved word, alias, \fIetc.\fP -Without the \fB\-v\fP option, \fBwhence\fP is similar to \fBcommand \-v\fP -except that \fBwhence\fP will find reserved words and won't print aliases -as alias commands; -with the \fB\-v\fP option, \fBwhence\fP is the same as \fBcommand \-V\fP. -Note that for \fBwhence\fP, the \fB\-p\fP option does not affect the search -path used, as it does for \fBcommand\fP. -If the type of one or more of the names could not be determined, the -exit status is non-zero. -.\"}}} -.\"}}} -.\"{{{ job control (and its built-in commands) -.SS "Job Control" -Job control refers to the shell's ability to monitor and control \fBjobs\fP, -which are processes or groups of processes created for commands or pipelines. -At a minimum, the shell keeps track of the status of the background -(\fIi.e.\fP, asynchronous) jobs that currently exist; this information can be -displayed using the \fBjobs\fP command. -If job control is fully enabled (using \fBset \-m\fP or -\fBset \-o monitor\fP), as it is for interactive shells, -the processes of a job are placed in their own process group, -foreground jobs can be stopped by typing the suspend character from the -terminal (normally ^Z), -jobs can be restarted in either the foreground -or background, using the \fBfg\fP and \fBbg\fP commands, respectively, -and the state of the terminal is saved or restored when a foreground -job is stopped or restarted, respectively. -.sp -Note that only commands that create processes (\fIe.g.\fP, -asynchronous commands, subshell commands, and non-built-in, -non-function commands) can be stopped; commands like \fBread\fP cannot be. -.sp -When a job is created, it is assigned a job-number. -For interactive shells, this number is printed inside \fB[\fP..\fB]\fP, -followed by the process-ids of the processes in the job when an asynchronous -command is run. -A job may be referred to in \fBbg\fP, \fBfg\fP, \fBjobs\fP, \fBkill\fP and -\fBwait\fP commands either by the process id of the last process in the -command pipeline (as stored in the \fB$!\fP parameter) or by prefixing the -job-number with a percent sign (\fB%\fP). -Other percent sequences can also be used to refer to jobs: -.sp -.TS -expand; -afB lw(4.5i). -%+ T{ -The most recently stopped job, or, if there are no stopped jobs, the oldest -running job. -T} -%%\fR, \fP% T{ -Same as \fB%+\fP. -T} -%\- T{ -The job that would be the \fB%+\fP job, if the later did not exist. -T} -%\fIn\fP T{ -The job with job-number \fIn\fP. -T} -%?\fIstring\fP T{ -The job containing the string \fIstring\fP (an error occurs if multiple jobs -are matched). -T} -%\fIstring\fP T{ -The job starting with string \fIstring\fP (an error occurs if multiple jobs -are matched). -T} -.TE -.sp -When a job changes state (\fIe.g.\fP, a background job finishes or foreground -job is stopped), the shell prints the following status information: -.RS -\fB[\fP\fInumber\fP\fB]\fP \fIflag status command\fP -.RE -where -.IP "\ \fInumber\fP" -is the job-number of the job. -.IP "\ \fIflag\fP" -is \fB+\fP or \fB-\fP if the job is the \fB%+\fP or \fB%-\fP job, -respectively, or space if it is neither. -.IP "\ \fIstatus\fP" -indicates the current state of the job and can be -.RS -.IP "\fBRunning\fP" -the job has neither stopped or exited (note that running does not -necessarily mean consuming CPU time \(em the process could be blocked waiting -for some event). -.IP "\fBDone\fP [\fB(\fP\fInumber\fP\fB)\fP]" -the job exited. -\fInumber\fP is the exit status of the job, which is -omitted if the status is zero. -.IP "\fBStopped\fP [\fB(\fP\fIsignal\fP\fB)\fP]" -the job was stopped by the indicated \fIsignal\fP (if no signal is given, -the job was stopped by SIGTSTP). -.IP "\fIsignal-description\fP [\fB(core dumped)\fP]" -the job was killed by a signal (\fIe.g.\fP, Memory\ fault, -Hangup, \fIetc.\fP \(em use -\fBkill \-l\fP for a list of signal descriptions). -The \fB(core\ dumped)\fP message indicates the process created a core file. -.RE -.IP "\ \fIcommand\fP" -is the command that created the process. -If there are multiple processes in the job, then each process will -have a line showing its \fIcommand\fP and possibly its \fIstatus\fP, -if it is different from the status of the previous process. -.PP -When an attempt is made to exit the shell while there are jobs in -the stopped state, the shell warns the user that there are stopped jobs -and does not exit. -If another attempt is immediately made to exit the shell, the stopped -jobs are sent a \fBHUP\fP signal and the shell exits. -Similarly, if the \fBnohup\fP option is not set and there are running -jobs when an attempt is made to exit a login shell, the shell warns the -user and does not exit. -If another attempt is immediately made to exit the shell, the running -jobs are sent a \fBHUP\fP signal and the shell exits. -.\"}}} -.\"{{{ Interactive Input Line Editing -.ksh( -.\"{{{ introduction -.SS "Interactive Input Line Editing" -The shell supports three modes of reading command lines from a tty -in an interactive session. -Which is used is controlled by the \fBemacs\fP, \fBgmacs\fP and \fBvi\fP -\fBset\fP options (at most one of these can be set at once). -If none of these options is enabled, the shell simply reads lines -using the normal tty driver. -If the \fBemacs\fP or \fBgmacs\fP option is set, the shell allows -emacs like editing of the command; similarly, if the \fBvi\fP option -is set, the shell allows vi like editing of the command. -These modes are described in detail in the following sections. -.\"}}} -.\"{{{ display -.PP -In these editing modes, if a line is longer that the screen width -(see \fBCOLUMNS\fP parameter), -a \fB>\fP, \fB+\fP or \fB<\fP character is displayed in the last column -indicating that there are more characters after, before and after, or -before the current position, respectively. -The line is scrolled horizontally as necessary. -.\"}}} -.\"{{{ Emacs Editing Mode -.SS "Emacs Editing Mode" -When the \fBemacs\fP option is set, interactive input line editing is -enabled. -\fBWarning\fP: This mode is slightly different from the emacs -mode in the original Korn shell and the 8th bit is stripped in emacs mode. -In this mode various editing commands (typically bound to one or more -control characters) cause immediate actions without waiting for a -new-line. -Several editing commands are bound to particular control -characters when the shell is invoked; these bindings can be changed -using the following commands: -.\"{{{ bind -.IP \fBbind\fP -The current bindings are listed. -.\"}}} -.\"{{{ bind string=[editing-command] -.IP "\fBbind\fP \fIstring\fP\fB=\fP[\fIediting-command\fP]" -The specified editing command is bound to the given \fBstring\fP, which -should consist of a control character (which may be written using caret -notation \fB^\fP\fIX\fP), optionally preceded by one of the two prefix -characters. -Future input of the \fIstring\fP will cause the editing -command to be immediately invoked. -Note that although only two prefix -characters (usually ESC and ^X) are supported, some multi-character -sequences can be supported. -The following binds the arrow keys on -an ANSI terminal, or xterm (these are in the default bindings). -Of course some escape sequences won't work out quite this nicely: -.sp -.RS -\fBbind '^[['=prefix\-2 -.br -bind '^XA'=up\-history -.br -bind '^XB'=down\-history -.br -bind '^XC'=forward\-char -.br -bind '^XD'=backward\-char\fP -.RE -.\"}}} -.\"{{{ bind -l -.IP "\fBbind \-l\fP" -Lists the names of the functions to which keys may be bound. -.\"}}} -.\"{{{ bind -m string=[substitute] -.IP "\fBbind \-m\fP \fIstring\fP\fB=\fP[\fIsubstitute\fP]" -The specified input \fIstring\fP will afterwards be immediately -replaced by the given \fIsubstitute\fP string, which may contain -editing commands. -.\"}}} -.PP -The following is a list of editing commands available. -Each description starts with the name of the command, -a \fIn\fP, if the command can be prefixed with a count, -and any keys the command is bound to by default (written using -caret notation, \fIe.g.\fP, ASCII ESC character is written as ^[). -A count prefix for a command is entered using the sequence -\fB^[\fP\fIn\fP, where \fIn\fP is a sequence of 1 or more digits; -unless otherwise specified, if a count is omitted, it defaults to 1. -Note that editing command names are -used only with the \fBbind\fP command. -Furthermore, many editing -commands are useful only on terminals with a visible cursor. -The default bindings were chosen to resemble corresponding EMACS key -bindings. -The users tty characters (\fIe.g.\fP, ERASE) are bound to -reasonable substitutes and override the default bindings. -.\"{{{ abort ^G -.IP "\fBabort ^G\fP" -Useful as a response to a request for a \fBsearch-history\fP pattern in -order to abort the search. -.\"}}} -.\"{{{ auto-insert n -.IP "\fBauto-insert\fP \fIn\fP" -Simply causes the character to appear as literal input. -Most ordinary characters are bound to this. -.\"}}} -.\"{{{ backward-char n ^B -.IP "\fBbackward-char\fP \fIn\fP \fB^B\fP" -Moves the cursor backward \fIn\fP characters. -.\"}}} -.\"{{{ backward-word n ^[B -.IP "\fBbackward-word\fP \fIn\fP \fB^[B\fP" -Moves the cursor backward to the beginning of a word; words consist -of alphanumerics, underscore (_) and dollar ($). -.\"}}} -.\"{{{ beginning-of-history ^[< -.IP "\fBbeginning-of-history ^[<\fP" -Moves to the beginning of the history. -.\"}}} -.\"{{{ beginning-of-line ^A -.IP "\fBbeginning-of-line ^A\fP" -Moves the cursor to the beginning of the edited input line. -.\"}}} -.\"{{{ capitalize-word n ^[c, ^[C -.IP "\fBcapitalize-word\fP \fIn\fP \fB^[c\fP, \fB^[C\fP" -Uppercase the first character in the next \fIn\fP words, -leaving the cursor past the end of the last word. -.\"}}} -.\"{{{ comment ^[# -If the current line does not begin with a comment character, one -is added at the beginning of the line and the line is entered (as if -return had been pressed), otherwise the existing comment characters -are removed and the cursor is placed at the beginning of the line. -.\"}}} -.\"{{{ complete ^[^[ -.IP "\fBcomplete ^[^[\fP" -.IP "\fBcomplete ^I\fP" -Automatically completes as much as is unique of the command name -or the file name containing the cursor. -If the entire remaining command -or file name is unique a space is printed after its completion, unless -it is a directory name in which case \fB/\fP is appended. -If there is no command or file name with the current partial word as its -prefix, a bell character is output (usually causing a audio beep). -.\"}}} -.\"{{{ complete-command ^X^[ -.IP "\fBcomplete-command ^X^[\fP" -Automatically completes as much as is unique of the command name -having the partial word up to the cursor as its prefix, as in the -\fBcomplete\fP command described above. -.\"}}} -.\"{{{ complete-file ^[^X -.IP "\fBcomplete-file ^[^X\fP" -Automatically completes as much as is unique of the file name having -the partial word up to the cursor as its prefix, as in the -\fBcomplete\fP command described above. -.\"}}} -.\"{{{ complete-list ^[= -.IP "\fBcomplete-list ^[=\fP" -List the possible completions for the current word. -.\"}}} -.\"{{{ delete-char-backward n ERASE, ^?, ^H -.IP "\fBdelete-char-backward\fP \fIn\fP \fBERASE\fP, \fB^?\fP, \fB^H\fP" -Deletes \fIn\fP characters before the cursor. -.\"}}} -.\"{{{ delete-char-forward n -.IP "\fBdelete-char-forward\fP \fIn\fP" -Deletes \fIn\fP characters after the cursor. -.\"}}} -.\"{{{ delete-word-backward n ^[ERASE, ^[^?, ^[^H, ^[h -.IP "\fBdelete-word-backward\fP \fIn\fP \fB^[ERASE\fP, \fB^[^?\fP, \fB^[^H\fP, \fB^[h\fP" -Deletes \fIn\fP words before the cursor. -.\"}}} -.\"{{{ delete-word-forward n ^[d -.IP "\fBdelete-word-forward\fP \fIn\fP \fB^[d\fP" -Deletes characters after the cursor up to the end of \fIn\fP words. -.\"}}} -.\"{{{ down-history n ^N -.IP "\fBdown-history\fP \fIn\fP \fB^N\fP" -Scrolls the history buffer forward \fIn\fP lines (later). -Each input line -originally starts just after the last entry in the history buffer, so -\fBdown-history\fP is not useful until either \fBsearch-history\fP or -\fBup-history\fP has been performed. -.\"}}} -.\"{{{ downcase-word n ^[L, ^[l -.IP "\fBdowncase-word\fP \fIn\fP \fB^[L\fP, \fB^[l\fP" -Lowercases the next \fIn\fP words. -.\"}}} -.\"{{{ end-of-history ^[> -.IP "\fBend-of-history ^[>\fP" -Moves to the end of the history. -.\"}}} -.\"{{{ end-of-line ^E -.IP "\fBend-of-line ^E\fP" -Moves the cursor to the end of the input line. -.\"}}} -.\"{{{ eot ^_ -.IP "\fBeot ^_\fP" -Acts as an end-of-file; this is useful because edit-mode input disables -normal terminal input canonicalization. -.\"}}} -.\"{{{ eot-or-delete n ^D -.IP "\fBeot-or-delete\fP \fIn\fP \fB^D\fP" -Acts as eot if alone on a line; otherwise acts as delete-char-forward. -.\"}}} -.\"{{{ error -.IP "\fBerror\fP" -Error (ring the bell). -.\"}}} -.\"{{{ exchange-point-and-mark ^X^X -.IP "\fBexchange-point-and-mark ^X^X\fP" -Places the cursor where the mark is, and sets the mark to where the -cursor was. -.\"}}} -.\"{{{ expand-file ^[* -.IP "\fBexpand-file ^[*\fP" -Appends a * to the current word and replaces the word with -the result of performing file globbing on the word. -If no files match the pattern, the bell is rung. -.\"}}} -.\"{{{ forward-char n ^F -.IP "\fBforward-char\fP \fIn\fP \fB^F\fP" -Moves the cursor forward \fIn\fP characters. -.\"}}} -.\"{{{ forward-word n ^[f -.IP "\fBforward-word\fP \fIn\fP \fB^[f\fP" -Moves the cursor forward to the end of the \fIn\fPth word. -.\"}}} -.\"{{{ goto-history n ^[g -.IP "\fBgoto-history\fP \fIn\fP \fB^[g\fP" -Goes to history number \fIn\fP. -.\"}}} -.\"{{{ kill-line KILL -.IP "\fBkill-line KILL\fP" -Deletes the entire input line. -.\"}}} -.\"{{{ kill-region ^W -.IP "\fBkill-region ^W\fP" -Deletes the input between the cursor and the mark. -.\"}}} -.\"{{{ kill-to-eol n ^K -.IP "\fBkill-to-eol\fP \fIn\fP \fB^K\fP" -Deletes the input from the cursor to the end of the line if \fIn\fP is -not specified, otherwise deletes characters between the cursor and -column \fIn\fP. -.\"}}} -.\"{{{ list ^[? -.IP "\fBlist ^[?\fP" -Prints a sorted, columnated list of command names or file names -(if any) that can complete the partial word containing the cursor. -Directory names have \fB/\fP appended to them. -.\"}}} -.\"{{{ list-command ^X? -.IP "\fBlist-command ^X?\fP" -Prints a sorted, columnated list of command names (if any) that -can complete the partial word containing the cursor. -.\"}}} -.\"{{{ list-file ^X^Y -.IP "\fBlist-file ^X^Y\fP" -Prints a sorted, columnated list of file names (if any) that can -complete the partial word containing the cursor. -File type indicators -are appended as described under \fBlist\fP above. -.\"}}} -.\"{{{ newline ^J and ^M -.IP "\fBnewline ^J\fP, \fB^M\fP" -Causes the current input line to be processed by the shell. -The current cursor position may be anywhere on the line. -.\"}}} -.\"{{{ newline-and-next ^O -.IP "\fBnewline-and-next ^O\fP" -Causes the current input line to be processed by the shell, and -the next line from history becomes the current line. -This is only useful after an up-history or search-history. -.\"}}} -.\"{{{ no-op QUIT -.IP "\fBno-op QUIT\fP" -This does nothing. -.\"}}} -.\"{{{ prefix-1 ^[ -.IP "\fBprefix-1 ^[\fP" -Introduces a 2-character command sequence. -.\"}}} -.\"{{{ prefix-2 ^X and ^[[ -.IP "\fBprefix-2 ^X\fP" -.IP "\fBprefix-2 ^[[\fP" -Introduces a 2-character command sequence. -.\"}}} -.\"{{{ prev-hist-word ^[. ^[_ -.IP "\fBprev-hist-word\fP \fIn\fP \fB^[.\fP, \fB^[_\fP" -The last (\fIn\fPth) word of the previous command is inserted at the cursor. -.\"}}} -.\"{{{ quote ^^ -.IP "\fBquote ^^\fP" -The following character is taken literally rather than as an editing -command. -.\"}}} -.\"{{{ redraw ^L -.IP "\fBredraw ^L\fP" -Reprints the prompt string and the current input line. -.\"}}} -.\"{{{ search-character-backward n ^[^] -.IP "\fBsearch-character-backward\fP \fIn\fP \fB^[^]\fP" -Search backward in the current line for the \fIn\fPth occurrence of the -next character typed. -.\"}}} -.\"{{{ search-character-forward n ^] -.IP "\fBsearch-character-forward\fP \fIn\fP \fB^]\fP" -Search forward in the current line for the \fIn\fPth occurrence of the -next character typed. -.\"}}} -.\"{{{ search-history ^R -.IP "\fBsearch-history ^R\fP" -Enter incremental search mode. -The internal history list is searched -backwards for commands matching the input. -An initial \fB^\fP in the search string anchors the search. -The abort key will leave search mode. -Other commands will be executed after leaving search mode. -Successive \fBsearch-history\fP commands continue searching backward to -the next previous occurrence of the pattern. -The history buffer retains only a -finite number of lines; the oldest are discarded as necessary. -.\"}}} -.\"{{{ set-mark-command ^[ -.IP "\fBset-mark-command ^[\fP" -Set the mark at the cursor position. -.\"}}} -.\"{{{ stuff -.IP "\fBstuff\fP" -On systems supporting it, pushes the bound character back onto the -terminal input where it may receive special processing by the terminal -handler. -This is useful for the BRL \fB^T\fP mini-systat feature, for example. -.\"}}} -.\"{{{ stuff-reset -.IP "\fBstuff-reset\fP" -Acts like \fBstuff\fP, then aborts input the same as an interrupt. -.\"}}} -.\"{{{ transport-chars ^T -.IP "\fBtranspose-chars ^T\fP" -If at the end of line, or if the \fBgmacs\fP option is set, -this exchanges the two previous characters; otherwise, it -exchanges the previous and current characters and moves the cursor -one character to the right. -.\"}}} -.\"{{{ up-history n ^P -.IP "\fBup-history\fP \fIn\fP \fB^P\fP" -Scrolls the history buffer backward \fIn\fP lines (earlier). -.\"}}} -.\"{{{ upcase-word n ^[U, ^[u -.IP "\fBupcase-word\fP \fIn\fP \fB^[U\fP, \fB^[u\fP" -Uppercases the next \fIn\fP words. -.\"}}} -.\"{{{ version ^V -.IP "\fBversion ^V\fP" -Display the version of ksh. -The current edit buffer is restored as soon -as any key is pressed (the key is then processed, unless it is a space). -.\"}}} -.\"{{{ yank ^Y -.IP "\fByank ^Y\fP" -Inserts the most recently killed text string at the current cursor position. -.\"}}} -.\"{{{ yank-pop ^[y -.IP "\fByank-pop ^[y\fP" -Immediately after a \fByank\fP, replaces the inserted text string with -the next previous killed text string. -.\"}}} -.\"}}} -.\"{{{ Vi Editing Mode -.\"{{{ introduction -.SS "Vi Editing Mode" -The vi command line editor in ksh has basically the same commands as the -vi editor (see \fIvi\fP(1)), with the following exceptions: -.nr P2 \n(PD -.IP \ \ \(bu -you start out in insert mode, -.IP \ \ \(bu -there are file name and command completion commands -(\fB=\fP, \fB\e\fP, \fB*\fP, \fB^X\fP, \fB^E\fP, \fB^F\fP and, -optionally, \fB\fP), -.IP \ \ \(bu -the \fB_\fP command is different (in ksh it is the last argument command, -in vi it goes to the start of the current line), -.IP \ \ \(bu -the \fB/\fP and \fBG\fP commands move in the opposite direction as the \fBj\fP -command -.IP \ \ \(bu -and commands which don't make sense in a single line editor are not available -(\fIe.g.\fP, screen movement commands, ex \fB:\fP commands, \fIetc.\fP). -.nr PD \n(P2 -.LP -Note that the \fB^X\fP stands for control-X; also \fB\fP, \fB\fP -and \fB\fP are used for escape, space and tab, respectively (no kidding). -.\"}}} -.\"{{{ modes -.PP -Like vi, there are two modes: insert mode and command mode. -In insert mode, most characters are simply put in the buffer at the -current cursor position as they are typed, however, some characters -are treated specially. -In particular, the following characters are taken from current tty settings -(see \fIstty\fP(1)) and have their usual meaning (normal values are in -parentheses): -kill (\fB^U\fP), erase (\fB^?\fP), werase (\fB^W\fP), eof (\fB^D\fP), -intr (\fB^C\fP) and quit (\fB^\e\fP). -In addition to the above, the following characters are also treated -specially in insert mode: -.TS -expand; -afB lw(4.5i). -^H T{ -erases previous character -T} -^V T{ -literal next: the next character typed is not treated specially (can be -used to insert the characters being described here) -T} -^J ^M T{ -end of line: the current line is read, parsed and executed by the shell -T} - T{ -puts the editor in command mode (see below) -T} -^E T{ -command and file name enumeration (see below) -T} -^F T{ -command and file name completion (see below). -If used twice in a row, the list of possible completions is displayed; -if used a third time, the completion is undone. -T} -^X T{ -command and file name expansion (see below) -T} - T{ -optional file name and command completion (see \fB^F\fP above), enabled with -\fBset \-o vi-tabcomplete\fP -T} -.TE -.\"}}} -.\"{{{ command mode -.PP -In command mode, each character is interpreted as a command. -Characters that don't correspond to commands, are illegal combinations of -commands or are commands that can't be carried out all cause beeps. -In the following command descriptions, a \fIn\fP indicates the -command may be prefixed by a number (\fIe.g.\fP, \fB10l\fP moves right 10 -characters); if no number prefix is used, \fIn\fP is assumed to be 1 -unless otherwise specified. -The term `current position' refers to the position between the cursor -and the character preceding the cursor. -A `word' is a sequence of letters, digits and underscore characters or a -sequence of non-letter, non-digit, non-underscore, non-white-space characters -(\fIe.g.\fP, ab2*&^ contains two words) and a `big-word' is a sequence of -non-white-space characters. -.\"{{{ Special ksh vi commands -.IP "Special ksh vi commands" -The following commands are not in, or are different from, the normal vi file -editor: -.RS -.IP "\fIn\fP\fB_\fP" -insert a space followed by the \fIn\fPth big-word from the last command in the -history at the current position and enter insert mode; if \fIn\fP is not -specified, the last word is inserted. -.IP "\fB#\fP" -insert the comment character (\fB#\fP) at the start of the current line and -return the line to the shell (equivalent to \fBI#^J\fP). -.IP "\fIn\fP\fBg\fP" -like \fBG\fP, except if \fIn\fP is not specified, it goes to the most recent -remembered line. -.IP "\fIn\fP\fBv\fP" -edit line \fIn\fP using the vi editor; -if \fIn\fP is not specified, the current line is edited. -The actual command executed is -`\fBfc \-e ${VISUAL:-${EDITOR:-vi}}\fP \fIn\fP'. -.IP "\fB*\fP and \fB^X\fP" -command or file name expansion is applied to the current big-word -(with an appended *, if the word contains no file globing characters) - the -big-word is replaced with the resulting words. -If the current big-word is the first on the line (or follows one -of the following characters: \fB;\fP, \fB|\fP, \fB&\fP, \fB(\fP, \fB)\fP) -and does not contain a slash (\fB/\fP) then command expansion is done, -otherwise file name expansion is done. -Command expansion will match the big-word against all aliases, functions -and built-in commands as well as any executable files found by searching -the directories in the \fBPATH\fP parameter. -File name expansion matches the big-word against the files in the -current directory. -After expansion, the cursor is placed just past the last word and the editor -is in insert mode. -.IP "\fIn\fP\fB\e\fP, \fIn\fP\fB^F\fP, \fIn\fP\fB\fP and \fIn\fP\fB\fP" -command/file name completion: -replace the current big-word with the longest unique -match obtained after performing command/file name expansion. -\fB\fP is only recognized if the \fBvi-tabcomplete\fP option is set, -while \fB\fP is only recognized if the \fBvi-esccomplete\fP option -is set (see \fBset \-o\fP). -If \fIn\fP is specified, the \fIn\fPth possible -completion is selected (as reported by the command/file name enumeration -command). -.IP "\fB=\fP and \fB^E\fP" -command/file name enumeration: list all the commands or files that match -the current big-word. -.IP "\fB^V\fP" -display the version of pdksh; it is displayed until another key is pressed -(this key is ignored). -.IP "\fB@\fP\fIc\fP" -macro expansion: execute the commands found in the alias _\fIc\fP. -.RE -.\"}}} -.\"{{{ Intra-line movement commands -.IP "Intra-line movement commands" -.RS -.IP "\fIn\fP\fBh\fP and \fIn\fP\fB^H\fP" -move left \fIn\fP characters. -.IP "\fIn\fP\fBl\fP and \fIn\fP\fB\fP" -move right \fIn\fP characters. -.IP "\fB0\fP" -move to column 0. -.IP "\fB^\fP" -move to the first non white-space character. -.IP "\fIn\fP\fB|\fP" -move to column \fIn\fP. -.IP "\fB$\fP" -move to the last character. -.IP "\fIn\fP\fBb\fP" -move back \fIn\fP words. -.IP "\fIn\fP\fBB\fP" -move back \fIn\fP big-words. -.IP "\fIn\fP\fBe\fP" -move forward to the end the word, \fIn\fP times. -.IP "\fIn\fP\fBE\fP" -move forward to the end the big-word, \fIn\fP times. -.IP "\fIn\fP\fBw\fP" -move forward \fIn\fP words. -.IP "\fIn\fP\fBW\fP" -move forward \fIn\fP big-words. -.IP "\fB%\fP" -find match: the editor looks forward for the nearest parenthesis, -bracket or brace and then moves the to the matching parenthesis, bracket or -brace. -.IP "\fIn\fP\fBf\fP\fIc\fP" -move forward to the \fIn\fPth occurrence of the character \fIc\fP. -.IP "\fIn\fP\fBF\fP\fIc\fP" -move backward to the \fIn\fPth occurrence of the character \fIc\fP. -.IP "\fIn\fP\fBt\fP\fIc\fP" -move forward to just before the \fIn\fPth occurrence of the character \fIc\fP. -.IP "\fIn\fP\fBT\fP\fIc\fP" -move backward to just before the \fIn\fPth occurrence of the character \fIc\fP. -.IP "\fIn\fP\fB;\fP" -repeats the last \fBf\fP, \fBF\fP, \fBt\fP or \fBT\fP command. -.IP "\fIn\fP\fB,\fP" -repeats the last \fBf\fP, \fBF\fP, \fBt\fP or \fBT\fP command, but moves -in the opposite direction. -.RE -.\"}}} -.\"{{{ Inter-line movement commands -.IP "Inter-line movement commands" -.RS -.IP "\fIn\fP\fBj\fP and \fIn\fP\fB+\fP and \fIn\fP\fB^N\fP" -move to the \fIn\fPth next line in the history. -.IP "\fIn\fP\fBk\fP and \fIn\fP\fB-\fP and \fIn\fP\fB^P\fP" -move to the \fIn\fPth previous line in the history. -.IP "\fIn\fP\fBG\fP" -move to line \fIn\fP in the history; if \fIn\fP is not specified, the -number first remembered line is used. -.IP "\fIn\fP\fBg\fP" -like \fBG\fP, except if \fIn\fP is not specified, it goes to the most recent -remembered line. -.IP "\fIn\fP\fB/\fP\fIstring\fP" -search backward through the history for the \fIn\fPth line containing -\fIstring\fP; if \fIstring\fP starts with \fB^\fP, the remainder of the -string must appear at the start of the history line for it to match. -.IP "\fIn\fP\fB?\fP\fIstring\fP" -same as \fB/\fP, except it searches forward through the history. -.IP "\fIn\fP\fBn\fP" -search for the \fIn\fPth occurrence of the last search string; the -direction of the search is the same as the last search. -.IP "\fIn\fP\fBN\fP" -search for the \fIn\fPth occurrence of the last search string; the -direction of the search is the opposite of the last search. -.RE -.\"}}} -.\"{{{ Edit commands -.IP "Edit commands" -.RS -.IP "\fIn\fP\fBa\fP" -append text \fIn\fP times: goes into insert mode just after the current -position. -The append is only replicated if command mode is re-entered (\fIi.e.\fP, - is used). -.IP "\fIn\fP\fBA\fP" -same as \fBa\fP, except it appends at the end of the line. -.IP "\fIn\fP\fBi\fP" -insert text \fIn\fP times: goes into insert mode at the current -position. -The insertion is only replicated if command mode is re-entered (\fIi.e.\fP, - is used). -.IP "\fIn\fP\fBI\fP" -same as \fBi\fP, except the insertion is done just before the first non-blank -character. -.IP "\fIn\fP\fBs\fP" -substitute the next \fIn\fP characters (\fIi.e.\fP, delete the characters -and go into insert mode). -.IP "\fBS\fP" -substitute whole line: all characters from the first non-blank character -to the end of line are deleted and insert mode is entered. -.IP "\fIn\fP\fBc\fP\fImove-cmd\fP" -change from the current position to the position resulting from \fIn\fP -\fImove-cmd\fPs (\fIi.e.\fP, delete the indicated region and go into insert -mode); -if \fImove-cmd\fP is \fBc\fP, the line starting from the first non-blank -character is changed. -.IP "\fBC\fP" -change from the current position to the end of the line (\fIi.e.\fP, delete to -the end of the line and go into insert mode). -.IP "\fIn\fP\fBx\fP" -delete the next \fIn\fP characters. -.IP "\fIn\fP\fBX\fP" -delete the previous \fIn\fP characters. -.IP "\fBD\fP" -delete to the end of the line. -.IP "\fIn\fP\fBd\fP\fImove-cmd\fP" -delete from the current position to the position resulting from -\fIn\fP \fImove-cmd\fPs; -\fImove-cmd\fP is a movement command (see above) or \fBd\fP, in which case -the current line is deleted. -.IP "\fIn\fP\fBr\fP\fIc\fP" -replace the next \fIn\fP characters with the character \fIc\fP. -.IP "\fIn\fP\fBR\fP" -replace: enter insert mode but overwrite existing characters instead of -inserting before existing characters. -The replacement is repeated \fIn\fP times. -.IP "\fIn\fP\fB~\fP" -change the case of the next \fIn\fP characters. -.IP "\fIn\fP\fBy\fP\fImove-cmd\fP" -yank from the current position to the position resulting from \fIn\fP -\fImove-cmd\fPs into the yank buffer; if \fImove-cmd\fP is \fBy\fP, the -whole line is yanked. -.IP "\fBY\fP" -yank from the current position to the end of the line. -.IP "\fIn\fP\fBp\fP" -paste the contents of the yank buffer just after the current position, -\fIn\fP times. -.IP "\fIn\fP\fBP\fP" -same as \fBp\fP, except the buffer is pasted at the current position. -.RE -.\"}}} -.\"{{{ Miscellaneous vi commands -.IP "Miscellaneous vi commands" -.RS -.IP "\fB^J\fP and \fB^M\fP" -the current line is read, parsed and executed by the shell. -.IP "\fB^L\fP and \fB^R\fP" -redraw the current line. -.IP "\fIn\fP\fB.\fP" -redo the last edit command \fIn\fP times. -.IP "\fBu\fP" -undo the last edit command. -.IP "\fBU\fP" -undo all changes that have been made to the current line. -.IP "\fIintr\fP and \fIquit\fP" -the interrupt and quit terminal characters cause the current line to -be deleted and a new prompt to be printed. -.RE -.\"Has all vi commands except: -.\" movement: { } [[ ]] ^E ^Y ^U ^D ^F ^B H L M () -.\" tag commands: ^T ^] -.\" mark commands: m ` ' -.\" named-buffer commands: " @ -.\" file/shell/ex-commands: Q ZZ ^^ : ! & -.\" multi-line change commands: o O J -.\" shift commands: << >> -.\" status command: ^G -.\"}}} -.\"}}} -.\"}}} -.ksh) -.\"}}} -.\"}}} -.\"{{{ Files -.SH FILES -~/.kshrc -.br -~/.profile -.br -/etc/profile -.br -/etc/suid_profile -.\"}}} -.\"{{{ Bugs -.SH BUGS -Any bugs in pdksh should be reported to pdksh@cs.mun.ca. -Please -include the version of pdksh (echo $KSH_VERSION shows it), the machine, -operating system and compiler you are using and a description of how to -repeat the bug (a small shell script that demonstrates the bug is -best). -The following, if relevant (if you are not sure, include them), -can also helpful: options you are using (both options.h options and set -\-o options) and a copy of your config.h (the file generated by the -configure script). -New versions of pdksh can be obtained from -ftp://ftp.cs.mun.ca/pub/pdksh/. -.PP -BTW, the most frequently reported bug is -.RS -\fB echo hi | read a; echo $a\fP\ \ \ # Does not print hi -.RE -I'm aware of this and there is no need to report it. -.\"}}} -.\"{{{ Version -.SH VERSION -This page documents version -.ce - @(#)PD KSH v5.2.14 99/07/13.2 -of the public domain korn shell. -.\"}}} -.\"{{{ Authors -.SH AUTHORS -This shell is based on the public domain 7th edition Bourne shell clone by -Charles Forsyth and parts of the BRL shell by Doug A.\& Gwyn, Doug Kingston, -Ron Natalie, Arnold Robbins, Lou Salkind and others. -The first release -of pdksh was created by Eric Gisin, and it was subsequently maintained by -John R.\& MacMillan (chance!john@sq.sq.com), and -Simon J.\& Gerraty (sjg@zen.void.oz.au). -The current maintainer is Michael Rendell (michael@cs.mun.ca). -The CONTRIBUTORS file in the source distribution contains a more complete -list of people and their part in the shell's development. -.\"}}} -.\"{{{ See also -.SH "SEE ALSO" -awk(1), -.ksh( -sh(1), -.ksh) -.sh( -ksh(1), -.sh) -csh(1), ed(1), getconf(1), getopt(1), sed(1), stty(1), vi(1), -dup(2), execve(2), getgid(2), getuid(2), open(2), pipe(2), wait(2), -getopt(3), rand(3), signal(3), system(3), -environ(7) -.PP -.IR "The KornShell Command and Programming Language" , -Morris Bolsky and David Korn, 1989, ISBN 0-13-516972-0. -.PP -.\" XXX ISBN missing -.IR "UNIX Shell Programming" , -Stephen G.\& Kochan, Patrick H.\& Wood, Hayden. -.PP -.IR "IEEE Standard for information Technology \- Portable Operating System Interface (POSIX) \- Part 2: Shell and Utilities" , -IEEE Inc, 1993, ISBN 1-55937-255-9. -.\"}}} diff --git a/bin/ksh/ksh_dir.h b/bin/ksh/ksh_dir.h deleted file mode 100644 index b0b3db6ed..000000000 --- a/bin/ksh/ksh_dir.h +++ /dev/null @@ -1,27 +0,0 @@ -/* $NetBSD: ksh_dir.h,v 1.2 1997/01/12 19:11:59 tls Exp $ */ - -/* Wrapper around the ugly dir includes/ifdefs */ -/* $NetBSD: ksh_dir.h,v 1.2 1997/01/12 19:11:59 tls Exp $ */ - -#if defined(HAVE_DIRENT_H) -# include -# define NLENGTH(dirent) (strlen(dirent->d_name)) -#else -# define dirent direct -# define NLENGTH(dirent) (dirent->d_namlen) -# ifdef HAVE_SYS_NDIR_H -# include -# endif /* HAVE_SYS_NDIR_H */ -# ifdef HAVE_SYS_DIR_H -# include -# endif /* HAVE_SYSDIR_H */ -# ifdef HAVE_NDIR_H -# include -# endif /* HAVE_NDIR_H */ -#endif /* HAVE_DIRENT_H */ - -#ifdef OPENDIR_DOES_NONDIR -extern DIR *ksh_opendir ARGS((const char *d)); -#else /* OPENDIR_DOES_NONDIR */ -# define ksh_opendir(d) opendir(d) -#endif /* OPENDIR_DOES_NONDIR */ diff --git a/bin/ksh/ksh_limval.h b/bin/ksh/ksh_limval.h deleted file mode 100644 index 42e38bbf5..000000000 --- a/bin/ksh/ksh_limval.h +++ /dev/null @@ -1,25 +0,0 @@ -/* $NetBSD: ksh_limval.h,v 1.2 1997/01/12 19:11:59 tls Exp $ */ - -/* Wrapper around the values.h/limits.h includes/ifdefs */ -/* $NetBSD: ksh_limval.h,v 1.2 1997/01/12 19:11:59 tls Exp $ */ - -#ifdef HAVE_VALUES_H -# include -#endif /* HAVE_VALUES_H */ -/* limits.h is included in sh.h */ - -#ifndef DMAXEXP -# define DMAXEXP 128 /* should be big enough */ -#endif - -#ifndef BITSPERBYTE -# ifdef CHAR_BIT -# define BITSPERBYTE CHAR_BIT -# else -# define BITSPERBYTE 8 /* probably true.. */ -# endif -#endif - -#ifndef BITS -# define BITS(t) (BITSPERBYTE * sizeof(t)) -#endif diff --git a/bin/ksh/ksh_stat.h b/bin/ksh/ksh_stat.h deleted file mode 100644 index 5f78406f1..000000000 --- a/bin/ksh/ksh_stat.h +++ /dev/null @@ -1,60 +0,0 @@ -/* $NetBSD: ksh_stat.h,v 1.2 1997/01/12 19:12:00 tls Exp $ */ - -/* Wrapper around the ugly sys/stat includes/ifdefs */ -/* $NetBSD: ksh_stat.h,v 1.2 1997/01/12 19:12:00 tls Exp $ */ - -/* assumes already included */ -#include - -#ifndef HAVE_LSTAT -# define lstat(path, buf) stat(path, buf) -#endif /* HAVE_LSTAT */ - -#ifdef STAT_MACROS_BROKEN -# undef S_ISREG -# undef S_ISDIR -# undef S_ISCHR -# undef S_ISBLK -# undef S_ISFIFO -# undef S_ISSOCK -# undef S_ISLNK -#endif /* STAT_MACROS_BROKEN */ - -#if !defined(S_ISREG) && defined(S_IFREG) -# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -#endif /* S_ISREG */ -#if !defined(S_ISDIR) && defined(S_IFDIR) -# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) -#endif /* S_ISDIR */ -#if !defined(S_ISCHR) && defined(S_IFCHR) -# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) -#endif /* S_ISCHR */ -#if !defined(S_ISBLK) && defined(S_IFBLK) -# define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK) -#endif /* S_ISBLK */ -#if !defined(S_ISFIFO) && defined(S_IFIFO) -# define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO) -#endif /* S_ISFIFO */ -#if !defined(S_ISLNK) && defined(S_IFLNK) -# define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) -#endif /* S_ISLNK */ -#if !defined(S_ISSOCK) && defined(S_IFSOCK) -# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK) -#endif /* S_ISSOCK */ -#if !defined(S_ISCDF) && defined(S_CDF) -# define S_ISCDF(m) (S_ISDIR(m) && ((m) & S_CDF)) -#endif /* S_ISSOCK */ - -#ifndef S_ISVTX -# define S_ISVTX 01000 /* sticky bit */ -#endif /* S_ISVTX */ - -#ifndef S_IXUSR -# define S_IXUSR 00100 /* user execute bit */ -#endif /* S_IXUSR */ -#ifndef S_IXGRP -# define S_IXGRP 00010 /* user execute bit */ -#endif /* S_IXGRP */ -#ifndef S_IXOTH -# define S_IXOTH 00001 /* user execute bit */ -#endif /* S_IXOTH */ diff --git a/bin/ksh/ksh_time.h b/bin/ksh/ksh_time.h deleted file mode 100644 index 79a7b1585..000000000 --- a/bin/ksh/ksh_time.h +++ /dev/null @@ -1,27 +0,0 @@ -/* $NetBSD: ksh_time.h,v 1.2 1997/01/12 19:12:01 tls Exp $ */ - -#ifndef KSH_TIME_H -# define KSH_TIME_H - -/* Wrapper around the ugly time.h,sys/time.h includes/ifdefs */ -/* $NetBSD: ksh_time.h,v 1.2 1997/01/12 19:12:01 tls Exp $ */ - -#ifdef TIME_WITH_SYS_TIME -# include -# include -#else /* TIME_WITH_SYS_TIME */ -# ifdef HAVE_SYS_TIME_H -# include -# else -# include -# endif -#endif /* TIME_WITH_SYS_TIME */ - -#ifndef TIME_DECLARED -extern time_t time ARGS((time_t *)); -#endif - -#ifndef CLK_TCK -# define CLK_TCK 60 /* 60HZ */ -#endif -#endif /* KSH_TIME_H */ diff --git a/bin/ksh/ksh_times.h b/bin/ksh/ksh_times.h deleted file mode 100644 index e01215a99..000000000 --- a/bin/ksh/ksh_times.h +++ /dev/null @@ -1,20 +0,0 @@ -/* $NetBSD: ksh_times.h,v 1.2 1997/01/12 19:12:02 tls Exp $ */ - -#ifndef KSH_TIMES_H -# define KSH_TIMES_H - -/* Needed for clock_t on some systems (ie, NeXT in non-posix mode) */ -#include "ksh_time.h" - -#include - -#ifdef TIMES_BROKEN -extern clock_t ksh_times ARGS((struct tms *)); -#else /* TIMES_BROKEN */ -# define ksh_times times -#endif /* TIMES_BROKEN */ - -#ifdef HAVE_TIMES -extern clock_t times ARGS((struct tms *)); -#endif /* HAVE_TIMES */ -#endif /* KSH_TIMES_H */ diff --git a/bin/ksh/ksh_wait.h b/bin/ksh/ksh_wait.h deleted file mode 100644 index dba7a27b0..000000000 --- a/bin/ksh/ksh_wait.h +++ /dev/null @@ -1,52 +0,0 @@ -/* $NetBSD: ksh_wait.h,v 1.2 1997/01/12 19:12:03 tls Exp $ */ - -/* Wrapper around the ugly sys/wait includes/ifdefs */ -/* $NetBSD: ksh_wait.h,v 1.2 1997/01/12 19:12:03 tls Exp $ */ - -#ifdef HAVE_SYS_WAIT_H -# include -#endif - -#ifndef POSIX_SYS_WAIT -/* Get rid of system macros (which probably use union wait) */ -# undef WIFCORED -# undef WIFEXITED -# undef WEXITSTATUS -# undef WIFSIGNALED -# undef WTERMSIG -# undef WIFSTOPPED -# undef WSTOPSIG -#endif /* POSIX_SYS_WAIT */ - -typedef int WAIT_T; - -#ifndef WIFCORED -# define WIFCORED(s) ((s) & 0x80) -#endif -#define WSTATUS(s) (s) - -#ifndef WIFEXITED -# define WIFEXITED(s) (((s) & 0xff) == 0) -#endif -#ifndef WEXITSTATUS -# define WEXITSTATUS(s) (((s) >> 8) & 0xff) -#endif -#ifndef WIFSIGNALED -# define WIFSIGNALED(s) (((s) & 0xff) != 0 && ((s) & 0xff) != 0x7f) -#endif -#ifndef WTERMSIG -# define WTERMSIG(s) ((s) & 0x7f) -#endif -#ifndef WIFSTOPPED -# define WIFSTOPPED(s) (((s) & 0xff) == 0x7f) -#endif -#ifndef WSTOPSIG -# define WSTOPSIG(s) (((s) >> 8) & 0xff) -#endif - -#if !defined(HAVE_WAITPID) && defined(HAVE_WAIT3) - /* always used with p == -1 */ -# define ksh_waitpid(p, s, o) wait3((s), (o), (struct rusage *) 0) -#else /* !HAVE_WAITPID && HAVE_WAIT3 */ -# define ksh_waitpid(p, s, o) waitpid((p), (s), (o)) -#endif /* !HAVE_WAITPID && HAVE_WAIT3 */ diff --git a/bin/ksh/lex.c b/bin/ksh/lex.c deleted file mode 100644 index 80ded4ad7..000000000 --- a/bin/ksh/lex.c +++ /dev/null @@ -1,1398 +0,0 @@ -/* $NetBSD: lex.c,v 1.15 2011/10/16 17:12:11 joerg Exp $ */ - -/* - * lexical analysis and source input - */ -#include - -#ifndef lint -__RCSID("$NetBSD: lex.c,v 1.15 2011/10/16 17:12:11 joerg Exp $"); -#endif - - -#include "sh.h" -#include - - -/* Structure to keep track of the lexing state and the various pieces of info - * needed for each particular state. - */ -typedef struct lex_state Lex_state; -struct lex_state { - int ls_state; - union { - /* $(...) */ - struct scsparen_info { - int nparen; /* count open parenthesis */ - int csstate; /* XXX remove */ -#define ls_scsparen ls_info.u_scsparen - } u_scsparen; - - /* $((...)) */ - struct sasparen_info { - int nparen; /* count open parenthesis */ - int start; /* marks start of $(( in output str */ -#define ls_sasparen ls_info.u_sasparen - } u_sasparen; - - /* ((...)) */ - struct sletparen_info { - int nparen; /* count open parenthesis */ -#define ls_sletparen ls_info.u_sletparen - } u_sletparen; - - /* `...` */ - struct sbquote_info { - int indquotes; /* true if in double quotes: "`...`" */ -#define ls_sbquote ls_info.u_sbquote - } u_sbquote; - - Lex_state *base; /* used to point to next state block */ - } ls_info; -}; - -typedef struct State_info State_info; -struct State_info { - Lex_state *base; - Lex_state *end; -}; - - -static void readhere ARGS((struct ioword *iop)); -static int getsc__ ARGS((void)); -static void getsc_line ARGS((Source *s)); -static int getsc_bn ARGS((void)); -static char *get_brace_var ARGS((XString *wsp, char *wp)); -static int arraysub ARGS((char **strp)); -static const char *ungetsc ARGS((int c)); -static void gethere ARGS((void)); -static Lex_state *push_state_ ARGS((State_info *si, Lex_state *old_end)); -static Lex_state *pop_state_ ARGS((State_info *si, Lex_state *old_end)); - -static int backslash_skip; -static int ignore_backslash_newline; - -/* optimized getsc_bn() */ -#define getsc() (*source->str != '\0' && *source->str != '\\' \ - && !backslash_skip ? *source->str++ : getsc_bn()) -/* optimized getsc__() */ -#define getsc_() ((*source->str != '\0') ? *source->str++ : getsc__()) - -#define STATE_BSIZE 32 - -#define PUSH_STATE(s) do { \ - if (++statep == state_info.end) \ - statep = push_state_(&state_info, statep); \ - state = statep->ls_state = (s); \ - } while (0) - -#define POP_STATE() do { \ - if (--statep == state_info.base) \ - statep = pop_state_(&state_info, statep); \ - state = statep->ls_state; \ - } while (0) - - - -/* - * Lexical analyzer - * - * tokens are not regular expressions, they are LL(1). - * for example, "${var:-${PWD}}", and "$(size $(whence ksh))". - * hence the state stack. - */ - -int -yylex(cf) - int cf; -{ - Lex_state states[STATE_BSIZE], *statep; - State_info state_info; - register int c, state; - XString ws; /* expandable output word */ - register char *wp; /* output word pointer */ - char *sp, *dp; - int c2; - - - Again: - states[0].ls_state = -1; - states[0].ls_info.base = (Lex_state *) 0; - statep = &states[1]; - state_info.base = states; - state_info.end = &states[STATE_BSIZE]; - - Xinit(ws, wp, 64, ATEMP); - - backslash_skip = 0; - ignore_backslash_newline = 0; - - if (cf&ONEWORD) - state = SWORD; -#ifdef KSH - else if (cf&LETEXPR) { - *wp++ = OQUOTE; /* enclose arguments in (double) quotes */ - state = SLETPAREN; - statep->ls_sletparen.nparen = 0; - } -#endif /* KSH */ - else { /* normal lexing */ - state = (cf & HEREDELIM) ? SHEREDELIM : SBASE; - while ((c = getsc()) == ' ' || c == '\t') - ; - if (c == '#') { - ignore_backslash_newline++; - while ((c = getsc()) != '\0' && c != '\n') - ; - ignore_backslash_newline--; - } - ungetsc(c); - } - if (source->flags & SF_ALIAS) { /* trailing ' ' in alias definition */ - source->flags &= ~SF_ALIAS; - /* In POSIX mode, a trailing space only counts if we are - * parsing a simple command - */ - if (!Flag(FPOSIX) || (cf & CMDWORD)) - cf |= ALIAS; - } - - /* Initial state: one of SBASE SHEREDELIM SWORD SASPAREN */ - statep->ls_state = state; - - /* collect non-special or quoted characters to form word */ - while (!((c = getsc()) == 0 - || ((state == SBASE || state == SHEREDELIM) - && ctype(c, C_LEX1)))) - { - Xcheck(ws, wp); - switch (state) { - case SBASE: - if (c == '[' && (cf & (VARASN|ARRAYVAR))) { - *wp = EOS; /* temporary */ - if (is_wdvarname(Xstring(ws, wp), FALSE)) - { - char *p, *tmp; - - if (arraysub(&tmp)) { - *wp++ = CHAR; - *wp++ = c; - for (p = tmp; *p; ) { - Xcheck(ws, wp); - *wp++ = CHAR; - *wp++ = *p++; - } - afree(tmp, ATEMP); - break; - } else { - Source *s; - - s = pushs(SREREAD, - source->areap); - s->start = s->str - = s->u.freeme = tmp; - s->next = source; - source = s; - } - } - *wp++ = CHAR; - *wp++ = c; - break; - } - /* fall through.. */ - Sbase1: /* includes *(...|...) pattern (*+?@!) */ -#ifdef KSH - if (c == '*' || c == '@' || c == '+' || c == '?' - || c == '!') - { - c2 = getsc(); - if (c2 == '(' /*)*/ ) { - *wp++ = OPAT; - *wp++ = c; - PUSH_STATE(SPATTERN); - break; - } - ungetsc(c2); - } -#endif /* KSH */ - /* fall through.. */ - Sbase2: /* doesn't include *(...|...) pattern (*+?@!) */ - switch (c) { - case '\\': - c = getsc(); -#ifdef OS2 - if (isalnum((unsigned char)c)) { - *wp++ = CHAR, *wp++ = '\\'; - *wp++ = CHAR, *wp++ = c; - } else -#endif - if (c) /* trailing \ is lost */ - *wp++ = QCHAR, *wp++ = c; - break; - case '\'': - *wp++ = OQUOTE; - ignore_backslash_newline++; - PUSH_STATE(SSQUOTE); - break; - case '"': - *wp++ = OQUOTE; - PUSH_STATE(SDQUOTE); - break; - default: - goto Subst; - } - break; - - Subst: - switch (c) { - Lex_state *s; - Lex_state *base; - - case '\\': - c = getsc(); - switch (c) { - case '\\': - case '$': case '`': - *wp++ = QCHAR, *wp++ = c; - break; - case '"': - if ((cf & HEREDOC) == 0) { - *wp++ = QCHAR, *wp++ = c; - break; - } - /* FALLTROUGH */ - default: - Xcheck(ws, wp); - if (c) { /* trailing \ is lost */ - *wp++ = CHAR, *wp++ = '\\'; - *wp++ = CHAR, *wp++ = c; - } - break; - } - break; - case '$': - c = getsc(); - if (c == '(') /*)*/ { - c = getsc(); - if (c == '(') /*)*/ { - PUSH_STATE(SASPAREN); - statep->ls_sasparen.nparen = 2; - statep->ls_sasparen.start = - Xsavepos(ws, wp); - *wp++ = EXPRSUB; - } else { - ungetsc(c); - PUSH_STATE(SCSPAREN); - statep->ls_scsparen.nparen = 1; - statep->ls_scsparen.csstate = 0; - *wp++ = COMSUB; - } - } else if (c == '{') /*}*/ { - *wp++ = OSUBST; - *wp++ = '{'; /*}*/ - wp = get_brace_var(&ws, wp); - c = getsc(); - /* allow :# and :% (ksh88 compat) */ - if (c == ':') { - *wp++ = CHAR, *wp++ = c; - c = getsc(); - } - /* If this is a trim operation, - * treat (,|,) specially in STBRACE. - */ - if (c == '#' || c == '%') { - ungetsc(c); - PUSH_STATE(STBRACE); - } else { - ungetsc(c); - PUSH_STATE(SBRACE); - } - } else if (ctype(c, C_ALPHA)) { - *wp++ = OSUBST; - *wp++ = 'X'; - do { - Xcheck(ws, wp); - *wp++ = c; - c = getsc(); - } while (ctype(c, C_ALPHA|C_DIGIT)); - *wp++ = '\0'; - *wp++ = CSUBST; - *wp++ = 'X'; - ungetsc(c); - } else if (ctype(c, C_DIGIT|C_VAR1)) { - Xcheck(ws, wp); - *wp++ = OSUBST; - *wp++ = 'X'; - *wp++ = c; - *wp++ = '\0'; - *wp++ = CSUBST; - *wp++ = 'X'; - } else { - *wp++ = CHAR, *wp++ = '$'; - ungetsc(c); - } - break; - case '`': - PUSH_STATE(SBQUOTE); - *wp++ = COMSUB; - /* Need to know if we are inside double quotes - * since sh/at&t-ksh translate the \" to " in - * "`..\"..`". POSIX also requires this. - * An earlier version of ksh misinterpreted - * the POSIX specification and performed - * removal of backslash escapes only if - * posix mode was not in effect. - */ - statep->ls_sbquote.indquotes = 0; - s = statep; - base = state_info.base; - while (1) { - for (; s != base; s--) { - if (s->ls_state == SDQUOTE) { - statep->ls_sbquote.indquotes = 1; - break; - } - } - if (s != base) - break; - if (!(s = s->ls_info.base)) - break; - base = s-- - STATE_BSIZE; - } - break; - default: - *wp++ = CHAR, *wp++ = c; - } - break; - - case SSQUOTE: - if (c == '\'') { - POP_STATE(); - *wp++ = CQUOTE; - ignore_backslash_newline--; - } else - *wp++ = QCHAR, *wp++ = c; - break; - - case SDQUOTE: - if (c == '"') { - POP_STATE(); - *wp++ = CQUOTE; - } else - goto Subst; - break; - - case SCSPAREN: /* $( .. ) */ - /* todo: deal with $(...) quoting properly - * kludge to partly fake quoting inside $(..): doesn't - * really work because nested $(..) or ${..} inside - * double quotes aren't dealt with. - */ - switch (statep->ls_scsparen.csstate) { - case 0: /* normal */ - switch (c) { - case '(': - statep->ls_scsparen.nparen++; - break; - case ')': - statep->ls_scsparen.nparen--; - break; - case '\\': - statep->ls_scsparen.csstate = 1; - break; - case '"': - statep->ls_scsparen.csstate = 2; - break; - case '\'': - statep->ls_scsparen.csstate = 4; - ignore_backslash_newline++; - break; - } - break; - - case 1: /* backslash in normal mode */ - case 3: /* backslash in double quotes */ - --statep->ls_scsparen.csstate; - break; - - case 2: /* double quotes */ - if (c == '"') - statep->ls_scsparen.csstate = 0; - else if (c == '\\') - statep->ls_scsparen.csstate = 3; - break; - - case 4: /* single quotes */ - if (c == '\'') { - statep->ls_scsparen.csstate = 0; - ignore_backslash_newline--; - } - break; - } - if (statep->ls_scsparen.nparen == 0) { - POP_STATE(); - *wp++ = 0; /* end of COMSUB */ - } else - *wp++ = c; - break; - - case SASPAREN: /* $(( .. )) */ - /* todo: deal with $((...); (...)) properly */ - /* XXX should nest using existing state machine - * (embed "..", $(...), etc.) */ - if (c == '(') - statep->ls_sasparen.nparen++; - else if (c == ')') { - statep->ls_sasparen.nparen--; - if (statep->ls_sasparen.nparen == 1) { - /*(*/ - if ((c2 = getsc()) == ')') { - POP_STATE(); - *wp++ = 0; /* end of EXPRSUB */ - break; - } else { - char *s; - - ungetsc(c2); - /* mismatched parenthesis - - * assume we were really - * parsing a $(..) expression - */ - s = Xrestpos(ws, wp, - statep->ls_sasparen.start); - memmove(s + 1, s, wp - s); - *s++ = COMSUB; - *s = '('; /*)*/ - wp++; - statep->ls_scsparen.nparen = 1; - statep->ls_scsparen.csstate = 0; - state = statep->ls_state - = SCSPAREN; - - } - } - } - *wp++ = c; - break; - - case SBRACE: - /*{*/ - if (c == '}') { - POP_STATE(); - *wp++ = CSUBST; - *wp++ = /*{*/ '}'; - } else - goto Sbase1; - break; - - case STBRACE: - /* Same as SBRACE, except (,|,) treated specially */ - /*{*/ - if (c == '}') { - POP_STATE(); - *wp++ = CSUBST; - *wp++ = /*{*/ '}'; - } else if (c == '|') { - *wp++ = SPAT; - } else if (c == '(') { - *wp++ = OPAT; - *wp++ = ' '; /* simile for @ */ - PUSH_STATE(SPATTERN); - } else - goto Sbase1; - break; - - case SBQUOTE: - if (c == '`') { - *wp++ = 0; - POP_STATE(); - } else if (c == '\\') { - switch (c = getsc()) { - case '\\': - case '$': case '`': - *wp++ = c; - break; - case '"': - if (statep->ls_sbquote.indquotes) { - *wp++ = c; - break; - } - /* fall through.. */ - default: - if (c) { /* trailing \ is lost */ - *wp++ = '\\'; - *wp++ = c; - } - break; - } - } else - *wp++ = c; - break; - - case SWORD: /* ONEWORD */ - goto Subst; - -#ifdef KSH - case SLETPAREN: /* LETEXPR: (( ... )) */ - /*(*/ - if (c == ')') { - if (statep->ls_sletparen.nparen > 0) - --statep->ls_sletparen.nparen; - /*(*/ - else if ((c2 = getsc()) == ')') { - c = 0; - *wp++ = CQUOTE; - goto Done; - } else - ungetsc(c2); - } else if (c == '(') - /* parenthesis inside quotes and backslashes - * are lost, but at&t ksh doesn't count them - * either - */ - ++statep->ls_sletparen.nparen; - goto Sbase2; -#endif /* KSH */ - - case SHEREDELIM: /* <<,<<- delimiter */ - /* XXX chuck this state (and the next) - use - * the existing states ($ and \`..` should be - * stripped of their specialness after the - * fact). - */ - /* here delimiters need a special case since - * $ and `..` are not to be treated specially - */ - if (c == '\\') { - c = getsc(); - if (c) { /* trailing \ is lost */ - *wp++ = QCHAR; - *wp++ = c; - } - } else if (c == '\'') { - PUSH_STATE(SSQUOTE); - *wp++ = OQUOTE; - ignore_backslash_newline++; - } else if (c == '"') { - state = statep->ls_state = SHEREDQUOTE; - *wp++ = OQUOTE; - } else { - *wp++ = CHAR; - *wp++ = c; - } - break; - - case SHEREDQUOTE: /* " in <<,<<- delimiter */ - if (c == '"') { - *wp++ = CQUOTE; - state = statep->ls_state = SHEREDELIM; - } else { - if (c == '\\') { - switch (c = getsc()) { - case '\\': case '"': - case '$': case '`': - break; - default: - if (c) { /* trailing \ lost */ - *wp++ = CHAR; - *wp++ = '\\'; - } - break; - } - } - *wp++ = CHAR; - *wp++ = c; - } - break; - - case SPATTERN: /* in *(...|...) pattern (*+?@!) */ - if ( /*(*/ c == ')') { - *wp++ = CPAT; - POP_STATE(); - } else if (c == '|') { - *wp++ = SPAT; - } else if (c == '(') { - *wp++ = OPAT; - *wp++ = ' '; /* simile for @ */ - PUSH_STATE(SPATTERN); - } else - goto Sbase1; - break; - } - } -Done: - Xcheck(ws, wp); - if (statep != &states[1]) - /* XXX figure out what is missing */ - yyerror("no closing quote\n"); - - /* This done to avoid tests for SHEREDELIM wherever SBASE tested */ - if (state == SHEREDELIM) - state = SBASE; - - dp = Xstring(ws, wp); - if ((c == '<' || c == '>') && state == SBASE - && ((c2 = Xlength(ws, wp)) == 0 - || (c2 == 2 && dp[0] == CHAR && digit(dp[1])))) - { - struct ioword *iop = - (struct ioword *) alloc(sizeof(*iop), ATEMP); - - if (c2 == 2) - iop->unit = dp[1] - '0'; - else - iop->unit = c == '>'; /* 0 for <, 1 for > */ - - c2 = getsc(); - /* <<, >>, <> are ok, >< is not */ - if (c == c2 || (c == '<' && c2 == '>')) { - iop->flag = c == c2 ? - (c == '>' ? IOCAT : IOHERE) : IORDWR; - if (iop->flag == IOHERE) { - if ((c2 = getsc()) == '-') { - iop->flag |= IOSKIP; - } else { - ungetsc(c2); - } - } - } else if (c2 == '&') - iop->flag = IODUP | (c == '<' ? IORDUP : 0); - else { - iop->flag = c == '>' ? IOWRITE : IOREAD; - if (c == '>' && c2 == '|') - iop->flag |= IOCLOB; - else - ungetsc(c2); - } - - iop->name = (char *) 0; - iop->delim = (char *) 0; - iop->heredoc = (char *) 0; - Xfree(ws, wp); /* free word */ - yylval.iop = iop; - return REDIR; - } - - if (wp == dp && state == SBASE) { - Xfree(ws, wp); /* free word */ - /* no word, process LEX1 character */ - switch (c) { - default: - return c; - - case '|': - case '&': - case ';': - if ((c2 = getsc()) == c) - c = (c == ';') ? BREAK : - (c == '|') ? LOGOR : - (c == '&') ? LOGAND : - YYERRCODE; -#ifdef KSH - else if (c == '|' && c2 == '&') - c = COPROC; -#endif /* KSH */ - else - ungetsc(c2); - return c; - - case '\n': - gethere(); - if (cf & CONTIN) - goto Again; - return c; - - case '(': /*)*/ -#ifdef KSH - if ((c2 = getsc()) == '(') /*)*/ - /* XXX need to handle ((...); (...)) */ - c = MDPAREN; - else - ungetsc(c2); -#endif /* KSH */ - return c; - /*(*/ - case ')': - return c; - } - } - - *wp++ = EOS; /* terminate word */ - yylval.cp = Xclose(ws, wp); - if (state == SWORD -#ifdef KSH - || state == SLETPAREN -#endif /* KSH */ - ) /* ONEWORD? */ - return LWORD; - ungetsc(c); /* unget terminator */ - - /* copy word to unprefixed string ident */ - for (sp = yylval.cp, dp = ident; dp < ident+IDENT && (c = *sp++) == CHAR; ) - *dp++ = *sp++; - /* Make sure the ident array stays '\0' padded */ - memset(dp, 0, (ident+IDENT) - dp + 1); - if (c != EOS) - *ident = '\0'; /* word is not unquoted */ - - if (*ident != '\0' && (cf&(KEYWORD|ALIAS))) { - struct tbl *p; - int h = hash(ident); - - /* { */ - if ((cf & KEYWORD) && (p = tsearch(&keywords, ident, h)) - && (!(cf & ESACONLY) || p->val.i == ESAC || p->val.i == '}')) - { - afree(yylval.cp, ATEMP); - return p->val.i; - } - if ((cf & ALIAS) && (p = tsearch(&aliases, ident, h)) - && (p->flag & ISSET)) - { - register Source *s; - - for (s = source; s->type == SALIAS; s = s->next) - if (s->u.tblp == p) - return LWORD; - /* push alias expansion */ - s = pushs(SALIAS, source->areap); - s->start = s->str = p->val.s; - s->u.tblp = p; - s->next = source; - source = s; - afree(yylval.cp, ATEMP); - goto Again; - } - } - - return LWORD; -} - -static void -gethere() -{ - register struct ioword **p; - - for (p = heres; p < herep; p++) - readhere(*p); - herep = heres; -} - -/* - * read "<delim, 0); - - if (!(iop->flag & IOEVAL)) - ignore_backslash_newline++; - - Xinit(xs, xp, 256, ATEMP); - - for (;;) { - eofp = eof; - skiptabs = iop->flag & IOSKIP; - xpos = Xsavepos(xs, xp); - while ((c = getsc()) != 0) { - if (skiptabs) { - if (c == '\t') - continue; - skiptabs = 0; - } - if (c != *eofp) - break; - Xcheck(xs, xp); - Xput(xs, xp, c); - eofp++; - } - /* Allow EOF here so commands with out trailing newlines - * will work (eg, ksh -c '...', $(...), etc). - */ - if (*eofp == '\0' && (c == 0 || c == '\n')) { - xp = Xrestpos(xs, xp, xpos); - break; - } - ungetsc(c); - while ((c = getsc()) != '\n') { - if (c == 0) - yyerror("here document `%s' unclosed\n", eof); - Xcheck(xs, xp); - Xput(xs, xp, c); - } - Xcheck(xs, xp); - Xput(xs, xp, c); - } - Xput(xs, xp, '\0'); - iop->heredoc = Xclose(xs, xp); - - if (!(iop->flag & IOEVAL)) - ignore_backslash_newline--; -} - -void -#ifdef HAVE_PROTOTYPES -yyerror(const char *fmt, ...) -#else -yyerror(fmt, va_alist) - const char *fmt; - va_dcl -#endif -{ - va_list va; - - /* pop aliases and re-reads */ - while (source->type == SALIAS || source->type == SREREAD) - source = source->next; - source->str = null; /* zap pending input */ - - error_prefix(TRUE); - SH_VA_START(va, fmt); - shf_vfprintf(shl_out, fmt, va); - va_end(va); - errorf("%s", null); -} - -/* - * input for yylex with alias expansion - */ - -Source * -pushs(type, areap) - int type; - Area *areap; -{ - register Source *s; - - s = (Source *) alloc(sizeof(Source), areap); - s->type = type; - s->str = null; - s->start = NULL; - s->line = 0; - s->errline = 0; - s->file = NULL; - s->flags = 0; - s->next = NULL; - s->areap = areap; - if (type == SFILE || type == SSTDIN) { - char *dummy; - Xinit(s->xs, dummy, 256, s->areap); - } else - memset(&s->xs, 0, sizeof(s->xs)); - return s; -} - -static int -getsc__() -{ - register Source *s = source; - register int c; - - while ((c = *s->str++) == 0) { - s->str = NULL; /* return 0 for EOF by default */ - switch (s->type) { - case SEOF: - s->str = null; - return 0; - - case SSTDIN: - case SFILE: - getsc_line(s); - break; - - case SWSTR: - break; - - case SSTRING: - break; - - case SWORDS: - s->start = s->str = *s->u.strv++; - s->type = SWORDSEP; - break; - - case SWORDSEP: - if (*s->u.strv == NULL) { - s->start = s->str = newline; - s->type = SEOF; - } else { - s->start = s->str = space; - s->type = SWORDS; - } - break; - - case SALIAS: - if (s->flags & SF_ALIASEND) { - /* pass on an unused SF_ALIAS flag */ - source = s->next; - source->flags |= s->flags & SF_ALIAS; - s = source; - } else if (*s->u.tblp->val.s - && isspace((unsigned char)strchr(s->u.tblp->val.s, 0)[-1])) - { - source = s = s->next; /* pop source stack */ - /* Note that this alias ended with a space, - * enabling alias expansion on the following - * word. - */ - s->flags |= SF_ALIAS; - } else { - /* At this point, we need to keep the current - * alias in the source list so recursive - * aliases can be detected and we also need - * to return the next character. Do this - * by temporarily popping the alias to get - * the next character and then put it back - * in the source list with the SF_ALIASEND - * flag set. - */ - source = s->next; /* pop source stack */ - source->flags |= s->flags & SF_ALIAS; - c = getsc__(); - if (c) { - s->flags |= SF_ALIASEND; - s->ugbuf[0] = c; s->ugbuf[1] = '\0'; - s->start = s->str = s->ugbuf; - s->next = source; - source = s; - } else { - s = source; - /* avoid reading eof twice */ - s->str = NULL; - break; - } - } - continue; - - case SREREAD: - if (s->start != s->ugbuf) /* yuck */ - afree(s->u.freeme, ATEMP); - source = s = s->next; - continue; - } - if (s->str == NULL) { - s->type = SEOF; - s->start = s->str = null; - return '\0'; - } - if (s->flags & SF_ECHO) { - shf_puts(s->str, shl_out); - shf_flush(shl_out); - } - } - return c; -} - -static void -getsc_line(s) - Source *s; -{ - char *xp = Xstring(s->xs, xp); - int interactive = Flag(FTALKING) && s->type == SSTDIN; - int have_tty = interactive && (s->flags & SF_TTY); - - /* Done here to ensure nothing odd happens when a timeout occurs */ - XcheckN(s->xs, xp, LINE); - *xp = '\0'; - s->start = s->str = xp; - -#ifdef KSH - if (have_tty && ksh_tmout) { - ksh_tmout_state = TMOUT_READING; - alarm(ksh_tmout); - } -#endif /* KSH */ -#ifdef EDIT - if (have_tty && (0 -# ifdef VI - || Flag(FVI) -# endif /* VI */ -# ifdef EMACS - || Flag(FEMACS) || Flag(FGMACS) -# endif /* EMACS */ - )) - { - int nread; - - nread = x_read(xp, LINE); - if (nread < 0) /* read error */ - nread = 0; - xp[nread] = '\0'; - xp += nread; - } - else -#endif /* EDIT */ - { - if (interactive) { - pprompt(prompt, 0); - } else - s->line++; - - while (1) { - char *p = shf_getse(xp, Xnleft(s->xs, xp), s->u.shf); - - if (!p && shf_error(s->u.shf) - && shf_errno(s->u.shf) == EINTR) - { - shf_clearerr(s->u.shf); - if (trap) - runtraps(0); - continue; - } - if (!p || (xp = p, xp[-1] == '\n')) - break; - /* double buffer size */ - xp++; /* move past null so doubling works... */ - XcheckN(s->xs, xp, Xlength(s->xs, xp)); - xp--; /* ...and move back again */ - } - /* flush any unwanted input so other programs/builtins - * can read it. Not very optimal, but less error prone - * than flushing else where, dealing with redirections, - * etc.. - * todo: reduce size of shf buffer (~128?) if SSTDIN - */ - if (s->type == SSTDIN) - shf_flush(s->u.shf); - } - /* XXX: temporary kludge to restore source after a - * trap may have been executed. - */ - source = s; -#ifdef KSH - if (have_tty && ksh_tmout) - { - ksh_tmout_state = TMOUT_EXECUTING; - alarm(0); - } -#endif /* KSH */ - s->start = s->str = Xstring(s->xs, xp); - strip_nuls(Xstring(s->xs, xp), Xlength(s->xs, xp)); - /* Note: if input is all nulls, this is not eof */ - if (Xlength(s->xs, xp) == 0) { /* EOF */ - if (s->type == SFILE) - shf_fdclose(s->u.shf); - s->str = NULL; - } else if (interactive) { -#ifdef HISTORY - char *p = Xstring(s->xs, xp); - if (cur_prompt == PS1) - while (*p && ctype(*p, C_IFS) && ctype(*p, C_IFSWS)) - p++; - if (*p) { -# ifdef EASY_HISTORY - if (cur_prompt == PS2) - histappend(Xstring(s->xs, xp), 1); - else -# endif /* EASY_HISTORY */ - { - s->line++; - histsave(s->line, s->str, 1); - } - } -#endif /* HISTORY */ - } - if (interactive) - set_prompt(PS2, (Source *) 0); -} - -void -set_prompt(to, s) - int to; - Source *s; -{ - cur_prompt = to; - - switch (to) { - case PS1: /* command */ -#ifdef KSH - /* Substitute ! and !! here, before substitutions are done - * so ! in expanded variables are not expanded. - * NOTE: this is not what at&t ksh does (it does it after - * substitutions, POSIX doesn't say which is to be done. - */ - { - struct shf *shf; - char * volatile ps1; - Area *saved_atemp; - - ps1 = str_val(global("PS1")); - shf = shf_sopen((char *) 0, strlen(ps1) * 2, - SHF_WR | SHF_DYNAMIC, (struct shf *) 0); - while (*ps1) { - if (*ps1 != '!' || *++ps1 == '!') - shf_putchar(*ps1++, shf); - else - shf_fprintf(shf, "%d", - s ? s->line + 1 : 0); - } - ps1 = shf_sclose(shf); - saved_atemp = ATEMP; - newenv(E_ERRH); - if (ksh_sigsetjmp(e->jbuf, 0)) { - prompt = safe_prompt; - /* Don't print an error - assume it has already - * been printed. Reason is we may have forked - * to run a command and the child may be - * unwinding its stack through this code as it - * exits. - */ - } else - prompt = str_save(substitute(ps1, 0), - saved_atemp); - quitenv(); - } -#else /* KSH */ - prompt = str_val(global("PS1")); -#endif /* KSH */ - break; - - case PS2: /* command continuation */ - prompt = str_val(global("PS2")); - break; - } -} - -/* See also related routine, promptlen() in edit.c */ -void -pprompt(cp, ntruncate) - const char *cp; - int ntruncate; -{ -#if 0 - char nbuf[32]; - int c; - - while (*cp != 0) { - if (*cp != '!') - c = *cp++; - else if (*++cp == '!') - c = *cp++; - else { - int len; - char *p; - - shf_snprintf(p = nbuf, sizeof(nbuf), "%d", - source->line + 1); - len = strlen(nbuf); - if (ntruncate) { - if (ntruncate >= len) { - ntruncate -= len; - continue; - } - p += ntruncate; - len -= ntruncate; - ntruncate = 0; - } - shf_write(p, len, shl_out); - continue; - } - if (ntruncate) - --ntruncate; - else - shf_putc(c, shl_out); - } -#endif /* 0 */ - shf_puts(cp + ntruncate, shl_out); - shf_flush(shl_out); -} - -/* Read the variable part of a ${...} expression (ie, up to but not including - * the :[-+?=#%] or close-brace. - */ -static char * -get_brace_var(wsp, wp) - XString *wsp; - char *wp; -{ - enum parse_state { - PS_INITIAL, PS_SAW_HASH, PS_IDENT, - PS_NUMBER, PS_VAR1, PS_END - } - state; - char c; - - state = PS_INITIAL; - while (1) { - c = getsc(); - /* State machine to figure out where the variable part ends. */ - switch (state) { - case PS_INITIAL: - if (c == '#') { - state = PS_SAW_HASH; - break; - } - /* fall through.. */ - case PS_SAW_HASH: - if (letter(c)) - state = PS_IDENT; - else if (digit(c)) - state = PS_NUMBER; - else if (ctype(c, C_VAR1)) - state = PS_VAR1; - else - state = PS_END; - break; - case PS_IDENT: - if (!letnum(c)) { - state = PS_END; - if (c == '[') { - char *tmp, *p; - - if (!arraysub(&tmp)) - yyerror("missing ]\n"); - *wp++ = c; - for (p = tmp; *p; ) { - Xcheck(*wsp, wp); - *wp++ = *p++; - } - afree(tmp, ATEMP); - c = getsc(); /* the ] */ - } - } - break; - case PS_NUMBER: - if (!digit(c)) - state = PS_END; - break; - case PS_VAR1: - state = PS_END; - break; - case PS_END: /* keep gcc happy */ - break; - } - if (state == PS_END) { - *wp++ = '\0'; /* end of variable part */ - ungetsc(c); - break; - } - Xcheck(*wsp, wp); - *wp++ = c; - } - return wp; -} - -/* - * Save an array subscript - returns true if matching bracket found, false - * if eof or newline was found. - * (Returned string double null terminated) - */ -static int -arraysub(strp) - char **strp; -{ - XString ws; - char *wp; - char c; - int depth = 1; /* we are just past the initial [ */ - - Xinit(ws, wp, 32, ATEMP); - - do { - c = getsc(); - Xcheck(ws, wp); - *wp++ = c; - if (c == '[') - depth++; - else if (c == ']') - depth--; - } while (depth > 0 && c && c != '\n'); - - *wp++ = '\0'; - *strp = Xclose(ws, wp); - - return depth == 0 ? 1 : 0; -} - -/* Unget a char: handles case when we are already at the start of the buffer */ -static const char * -ungetsc(c) - int c; -{ - if (backslash_skip) - backslash_skip--; - /* Don't unget eof... */ - if (source->str == null && c == '\0') - return source->str; - if (source->str > source->start) - source->str--; - else { - Source *s; - - s = pushs(SREREAD, source->areap); - s->ugbuf[0] = c; s->ugbuf[1] = '\0'; - s->start = s->str = s->ugbuf; - s->next = source; - source = s; - } - return source->str; -} - - -/* Called to get a char that isn't a \newline sequence. */ -static int -getsc_bn ARGS((void)) -{ - int c, c2; - - if (ignore_backslash_newline) - return getsc_(); - - if (backslash_skip == 1) { - backslash_skip = 2; - return getsc_(); - } - - backslash_skip = 0; - - while (1) { - c = getsc_(); - if (c == '\\') { - if ((c2 = getsc_()) == '\n') - /* ignore the \newline; get the next char... */ - continue; - ungetsc(c2); - backslash_skip = 1; - } - return c; - } -} - -static Lex_state * -push_state_(si, old_end) - State_info *si; - Lex_state *old_end; -{ - Lex_state *new = alloc(sizeof(Lex_state) * STATE_BSIZE, ATEMP); - - new[0].ls_info.base = old_end; - si->base = &new[0]; - si->end = &new[STATE_BSIZE]; - return &new[1]; -} - -static Lex_state * -pop_state_(si, old_end) - State_info *si; - Lex_state *old_end; -{ - Lex_state *old_base = si->base; - - si->base = old_end->ls_info.base - STATE_BSIZE; - si->end = old_end->ls_info.base; - - afree(old_base, ATEMP); - - return si->base + STATE_BSIZE - 1; -} diff --git a/bin/ksh/lex.h b/bin/ksh/lex.h deleted file mode 100644 index 99c06dae1..000000000 --- a/bin/ksh/lex.h +++ /dev/null @@ -1,133 +0,0 @@ -/* $NetBSD: lex.h,v 1.7 2005/09/11 22:16:00 christos Exp $ */ - -/* - * Source input, lexer and parser - */ - -/* $Id: lex.h,v 1.7 2005/09/11 22:16:00 christos Exp $ */ - -#define IDENT 64 - -typedef struct source Source; -struct source { - const char *str; /* input pointer */ - int type; /* input type */ - const char *start; /* start of current buffer */ - union { - char **strv; /* string [] */ - struct shf *shf; /* shell file */ - struct tbl *tblp; /* alias (SALIAS) */ - char *freeme; /* also for SREREAD */ - } u; - char ugbuf[2]; /* buffer for ungetsc() (SREREAD) and - * alias (SALIAS) */ - int line; /* line number */ - int errline; /* line the error occurred on (0 if not set) */ - const char *file; /* input file name */ - int flags; /* SF_* */ - Area *areap; - XString xs; /* input buffer */ - Source *next; /* stacked source */ -}; - -/* Source.type values */ -#define SEOF 0 /* input EOF */ -#define SFILE 1 /* file input */ -#define SSTDIN 2 /* read stdin */ -#define SSTRING 3 /* string */ -#define SWSTR 4 /* string without \n */ -#define SWORDS 5 /* string[] */ -#define SWORDSEP 6 /* string[] separator */ -#define SALIAS 7 /* alias expansion */ -#define SREREAD 8 /* read ahead to be re-scanned */ - -/* Source.flags values */ -#define SF_ECHO BIT(0) /* echo input to shlout */ -#define SF_ALIAS BIT(1) /* faking space at end of alias */ -#define SF_ALIASEND BIT(2) /* faking space at end of alias */ -#define SF_TTY BIT(3) /* type == SSTDIN & it is a tty */ - -/* - * states while lexing word - */ -#define SBASE 0 /* outside any lexical constructs */ -#define SWORD 1 /* implicit quoting for substitute() */ -#ifdef KSH -#define SLETPAREN 2 /* inside (( )), implicit quoting */ -#endif /* KSH */ -#define SSQUOTE 3 /* inside '' */ -#define SDQUOTE 4 /* inside "" */ -#define SBRACE 5 /* inside ${} */ -#define SCSPAREN 6 /* inside $() */ -#define SBQUOTE 7 /* inside `` */ -#define SASPAREN 8 /* inside $(( )) */ -#define SHEREDELIM 9 /* parsing <<,<<- delimiter */ -#define SHEREDQUOTE 10 /* parsing " in <<,<<- delimiter */ -#define SPATTERN 11 /* parsing *(...|...) pattern (*+?@!) */ -#define STBRACE 12 /* parsing ${..[#%]..} */ - -typedef union { - int i; - char *cp; - char **wp; - struct op *o; - struct ioword *iop; -} YYSTYPE; - -/* If something is added here, add it to tokentab[] in syn.c as well */ -#define LWORD 256 -#define LOGAND 257 /* && */ -#define LOGOR 258 /* || */ -#define BREAK 259 /* ;; */ -#define IF 260 -#define THEN 261 -#define ELSE 262 -#define ELIF 263 -#define FI 264 -#define CASE 265 -#define ESAC 266 -#define FOR 267 -#define SELECT 268 -#define WHILE 269 -#define UNTIL 270 -#define DO 271 -#define DONE 272 -#define IN 273 -#define FUNCTION 274 -#define TIME 275 -#define REDIR 276 -#ifdef KSH -#define MDPAREN 277 /* (( )) */ -#endif /* KSH */ -#define BANG 278 /* ! */ -#define DBRACKET 279 /* [[ .. ]] */ -#define COPROC 280 /* |& */ -#define YYERRCODE 300 - -/* flags to yylex */ -#define CONTIN BIT(0) /* skip new lines to complete command */ -#define ONEWORD BIT(1) /* single word for substitute() */ -#define ALIAS BIT(2) /* recognize alias */ -#define KEYWORD BIT(3) /* recognize keywords */ -#define LETEXPR BIT(4) /* get expression inside (( )) */ -#define VARASN BIT(5) /* check for var=word */ -#define ARRAYVAR BIT(6) /* parse x[1 & 2] as one word */ -#define ESACONLY BIT(7) /* only accept esac keyword */ -#define CMDWORD BIT(8) /* parsing simple command (alias related) */ -#define HEREDELIM BIT(9) /* parsing <<,<<- delimiter */ -#define HEREDOC BIT(10) /* parsing heredoc */ - -#define HERES 10 /* max << in line */ - -EXTERN Source *source; /* yyparse/yylex source */ -EXTERN YYSTYPE yylval; /* result from yylex */ -EXTERN struct ioword *heres [HERES], **herep; -EXTERN char ident [IDENT+1]; - -#ifdef HISTORY -# define HISTORYSIZE 128 /* size of saved history */ - -EXTERN char **histlist; /* saved commands */ -EXTERN char **histptr; /* last history item */ -EXTERN int histsize; /* history size */ -#endif /* HISTORY */ diff --git a/bin/ksh/mail.c b/bin/ksh/mail.c deleted file mode 100644 index e6a51f960..000000000 --- a/bin/ksh/mail.c +++ /dev/null @@ -1,202 +0,0 @@ -/* $NetBSD: mail.c,v 1.5 2006/01/15 18:16:30 jschauma Exp $ */ - -/* - * Mailbox checking code by Robert J. Gibson, adapted for PD ksh by - * John R. MacMillan - */ -#include - -#ifndef lint -__RCSID("$NetBSD: mail.c,v 1.5 2006/01/15 18:16:30 jschauma Exp $"); -#endif - - -#include "config.h" - -#ifdef KSH -#include "sh.h" -#include "ksh_stat.h" -#include "ksh_time.h" - -#define MBMESSAGE "You have mail in $_" - -typedef struct mbox { - struct mbox *mb_next; /* next mbox in list */ - char *mb_path; /* path to mail file */ - char *mb_msg; /* to announce arrival of new mail */ - time_t mb_mtime; /* mtime of mail file */ -} mbox_t; - -/* - * $MAILPATH is a linked list of mboxes. $MAIL is a treated as a - * special case of $MAILPATH, where the list has only one node. The - * same list is used for both since they are exclusive. - */ - -static mbox_t *mplist; -static mbox_t mbox; -static time_t mlastchkd; /* when mail was last checked */ -static time_t mailcheck_interval; - -static void munset ARGS((mbox_t *mlist)); /* free mlist and mval */ -static mbox_t * mballoc ARGS((char *p, char *m)); /* allocate a new mbox */ -static void mprintit ARGS((mbox_t *mbp)); - -void -mcheck() -{ - register mbox_t *mbp; - time_t now; - struct tbl *vp; - struct stat stbuf; - - now = time((time_t *) 0); - if (mlastchkd == 0) - mlastchkd = now; - if (now - mlastchkd >= mailcheck_interval) { - mlastchkd = now; - - if (mplist) - mbp = mplist; - else if ((vp = global("MAIL")) && (vp->flag & ISSET)) - mbp = &mbox; - else - mbp = NULL; - - while (mbp) { - if (mbp->mb_path && stat(mbp->mb_path, &stbuf) == 0 - && S_ISREG(stbuf.st_mode)) - { - if (stbuf.st_size - && mbp->mb_mtime != stbuf.st_mtime - && stbuf.st_atime <= stbuf.st_mtime) - mprintit(mbp); - mbp->mb_mtime = stbuf.st_mtime; - } else { - /* - * Some mail readers remove the mail - * file if all mail is read. If file - * does not exist, assume this is the - * case and set mtime to zero. - */ - mbp->mb_mtime = 0; - } - mbp = mbp->mb_next; - } - } -} - -void -mcset(interval) - long interval; -{ - mailcheck_interval = interval; -} - -void -mbset(p) - register char *p; -{ - struct stat stbuf; - - if (mbox.mb_msg) - afree((void *)mbox.mb_msg, APERM); - if (mbox.mb_path) - afree((void *)mbox.mb_path, APERM); - /* Save a copy to protect from export (which munges the string) */ - mbox.mb_path = str_save(p, APERM); - mbox.mb_msg = NULL; - if (p && stat(p, &stbuf) == 0 && S_ISREG(stbuf.st_mode)) - mbox.mb_mtime = stbuf.st_mtime; - else - mbox.mb_mtime = 0; -} - -void -mpset(mptoparse) - register char *mptoparse; -{ - register mbox_t *mbp; - register char *mpath, *mmsg, *mval; - char *p; - - munset( mplist ); - mplist = NULL; - mval = str_save(mptoparse, APERM); - while (mval) { - mpath = mval; - if ((mval = strchr(mval, PATHSEP)) != NULL) { - *mval = '\0', mval++; - } - /* POSIX/bourne-shell say file%message */ - for (p = mpath; (mmsg = strchr(p, '%')); ) { - /* a literal percent? (POSIXism) */ - if (mmsg[-1] == '\\') { - /* use memmove() to avoid overlap problems */ - memmove(mmsg - 1, mmsg, strlen(mmsg) + 1); - p = mmsg + 1; - continue; - } - break; - } - /* at&t ksh says file?message */ - if (!mmsg && !Flag(FPOSIX)) - mmsg = strchr(mpath, '?'); - if (mmsg) { - *mmsg = '\0'; - mmsg++; - } - mbp = mballoc(mpath, mmsg); - mbp->mb_next = mplist; - mplist = mbp; - } -} - -static void -munset(mlist) -register mbox_t *mlist; -{ - register mbox_t *mbp; - - while (mlist != NULL) { - mbp = mlist; - mlist = mbp->mb_next; - if (!mlist) - afree((void *)mbp->mb_path, APERM); - afree((void *)mbp, APERM); - } -} - -static mbox_t * -mballoc(p, m) - char *p; - char *m; -{ - struct stat stbuf; - register mbox_t *mbp; - - mbp = (mbox_t *)alloc(sizeof(mbox_t), APERM); - mbp->mb_next = NULL; - mbp->mb_path = p; - mbp->mb_msg = m; - if (stat(mbp->mb_path, &stbuf) == 0 && S_ISREG(stbuf.st_mode)) - mbp->mb_mtime = stbuf.st_mtime; - else - mbp->mb_mtime = 0; - return(mbp); -} - -static void -mprintit( mbp ) -mbox_t *mbp; -{ - struct tbl *vp; - - /* Ignore setstr errors here (arbitrary) */ - setstr((vp = local("_", FALSE)), mbp->mb_path, KSH_RETURN_ERROR); - - shellf("%s\n", substitute(mbp->mb_msg ? mbp->mb_msg : MBMESSAGE, 0)); - - unset(vp, 0); -} -#endif /* KSH */ diff --git a/bin/ksh/main.c b/bin/ksh/main.c deleted file mode 100644 index 1dca7e1f3..000000000 --- a/bin/ksh/main.c +++ /dev/null @@ -1,869 +0,0 @@ -/* $NetBSD: main.c,v 1.15 2011/10/16 17:12:11 joerg Exp $ */ - -/* - * startup, main loop, environments and error handling - */ -#include -#include - -#ifndef lint -__RCSID("$NetBSD: main.c,v 1.15 2011/10/16 17:12:11 joerg Exp $"); -#endif - - -#define EXTERN /* define EXTERNs in sh.h */ - -#include "sh.h" -#include "ksh_stat.h" -#include "ksh_time.h" - -extern char **environ; - -/* - * global data - */ - -static void reclaim ARGS((void)); -static void remove_temps ARGS((struct temp *tp)); -static int is_restricted ARGS((char *name)); - -/* - * shell initialization - */ - -static const char initifs[] = "IFS= \t\n"; - -static const char initsubs[] = "${PS2=> } ${PS3=#? } ${PS4=+ }"; - -static const char version_param[] = -#ifdef KSH - "KSH_VERSION" -#else /* KSH */ - "SH_VERSION" -#endif /* KSH */ - ; - -static const char *const initcoms [] = { - "typeset", "-x", "SHELL", "PATH", "HOME", NULL, - "typeset", "-r", version_param, NULL, - "typeset", "-i", "PPID", NULL, - "typeset", "-i", "OPTIND=1", NULL, -#ifdef KSH - "eval", "typeset -i RANDOM MAILCHECK=\"${MAILCHECK-600}\" SECONDS=\"${SECONDS-0}\" TMOUT=\"${TMOUT-0}\"", NULL, -#endif /* KSH */ - "alias", - /* Standard ksh aliases */ - "hash=alias -t", /* not "alias -t --": hash -r needs to work */ - "type=whence -v", -#ifdef JOBS - "stop=kill -STOP", - "suspend=kill -STOP $$", -#endif -#ifdef KSH - "autoload=typeset -fu", - "functions=typeset -f", -# ifdef HISTORY - "history=fc -l", -# endif /* HISTORY */ - "integer=typeset -i", - "nohup=nohup ", - "local=typeset", - "r=fc -e -", -#endif /* KSH */ -#ifdef KSH - /* Aliases that are builtin commands in at&t */ - "login=exec login", -#ifndef __NetBSD__ - "newgrp=exec newgrp", -#endif /* __NetBSD__ */ -#endif /* KSH */ - NULL, - /* this is what at&t ksh seems to track, with the addition of emacs */ - "alias", "-tU", - "cat", "cc", "chmod", "cp", "date", "ed", "emacs", "grep", "ls", - "mail", "make", "mv", "pr", "rm", "sed", "sh", "vi", "who", - NULL, -#ifdef EXTRA_INITCOMS - EXTRA_INITCOMS, NULL, -#endif /* EXTRA_INITCOMS */ - NULL -}; - -int -main(int argc, char *argv[]) -{ - register int i; - int argi; - Source *s; - struct block *l; - int restricted, errexit; - char **wp; - struct env env; - pid_t ppid; - -#ifdef MEM_DEBUG - chmem_set_defaults("ct", 1); - /* chmem_push("+c", 1); */ -#endif /* MEM_DEBUG */ - -#ifdef OS2 - setmode (0, O_BINARY); - setmode (1, O_TEXT); -#endif - - /* make sure argv[] is sane */ - if (!*argv) { - static const char *empty_argv[] = { - "pdksh", (char *) 0 - }; - - argv = (char **)__UNCONST(empty_argv); - argc = 1; - } - kshname = *argv; - - ainit(&aperm); /* initialize permanent Area */ - - /* set up base environment */ - memset(&env, 0, sizeof(env)); - env.type = E_NONE; - ainit(&env.area); - e = &env; - newblock(); /* set up global l->vars and l->funs */ - - /* Do this first so output routines (eg, errorf, shellf) can work */ - initio(); - - initvar(); - - initctypes(); - - inittraps(); - -#ifdef KSH - coproc_init(); -#endif /* KSH */ - - /* set up variable and command dictionaries */ - tinit(&taliases, APERM, 0); - tinit(&aliases, APERM, 0); - tinit(&homedirs, APERM, 0); - - /* define shell keywords */ - initkeywords(); - - /* define built-in commands */ - tinit(&builtins, APERM, 64); /* must be 2^n (currently 40 builtins) */ - for (i = 0; shbuiltins[i].name != NULL; i++) - builtin(shbuiltins[i].name, shbuiltins[i].func); - for (i = 0; kshbuiltins[i].name != NULL; i++) - builtin(kshbuiltins[i].name, kshbuiltins[i].func); - - init_histvec(); - - def_path = DEFAULT__PATH; -#if defined(HAVE_CONFSTR) && defined(_CS_PATH) - { - size_t len = confstr(_CS_PATH, (char *) 0, 0); - char *new; - - if (len > 0) { - confstr(_CS_PATH, new = alloc(len + 1, APERM), len + 1); - def_path = new; - } - } -#endif /* HAVE_CONFSTR && _CS_PATH */ - - /* Set PATH to def_path (will set the path global variable). - * (import of environment below will probably change this setting). - */ - { - struct tbl *vp = global("PATH"); - /* setstr can't fail here */ - setstr(vp, def_path, KSH_RETURN_ERROR); - } - - - /* Turn on nohup by default for now - will change to off - * by default once people are aware of its existence - * (at&t ksh does not have a nohup option - it always sends - * the hup). - */ - Flag(FNOHUP) = 1; - - /* Turn on brace expansion by default. At&t ksh's that have - * alternation always have it on. BUT, posix doesn't have - * brace expansion, so set this before setting up FPOSIX - * (change_flag() clears FBRACEEXPAND when FPOSIX is set). - */ -#ifdef BRACE_EXPAND - Flag(FBRACEEXPAND) = 1; -#endif /* BRACE_EXPAND */ - - /* set posix flag just before environment so that it will have - * exactly the same effect as the POSIXLY_CORRECT environment - * variable. If this needs to be done sooner to ensure correct posix - * operation, an initial scan of the environment will also have - * done sooner. - */ -#ifdef POSIXLY_CORRECT - change_flag(FPOSIX, OF_SPECIAL, 1); -#endif /* POSIXLY_CORRECT */ - - /* Set edit mode to emacs by default, may be overridden - * by the environment or the user. Also, we want tab completion - * on in vi by default. */ -#if defined(EDIT) && defined(EMACS) - change_flag(FEMACS, OF_SPECIAL, 1); -#endif /* EDIT && EMACS */ -#if defined(EDIT) && defined(VI) - Flag(FVITABCOMPLETE) = 1; -#endif /* EDIT && VI */ - - /* import environment */ - if (environ != NULL) - for (wp = environ; *wp != NULL; wp++) - typeset(*wp, IMPORT|EXPORT, 0, 0, 0); - - kshpid = procpid = getpid(); - typeset(initifs, 0, 0, 0, 0); /* for security */ - - /* assign default shell variable values */ - substitute(initsubs, 0); - - /* Figure out the current working directory and set $PWD */ - { - struct stat s_pwd, s_dot; - struct tbl *pwd_v = global("PWD"); - char *pwd = str_val(pwd_v); - char *pwdx = pwd; - - /* Try to use existing $PWD if it is valid */ - if (!ISABSPATH(pwd) - || stat(pwd, &s_pwd) < 0 || stat(".", &s_dot) < 0 - || s_pwd.st_dev != s_dot.st_dev - || s_pwd.st_ino != s_dot.st_ino) - pwdx = (char *) 0; - set_current_wd(pwdx); - if (current_wd[0]) - simplify_path(current_wd); - /* Only set pwd if we know where we are or if it had a - * bogus value - */ - if (current_wd[0] || pwd != null) - /* setstr can't fail here */ - setstr(pwd_v, current_wd, KSH_RETURN_ERROR); - } - ppid = getppid(); - setint(global("PPID"), (long) ppid); -#ifdef KSH - setint(global("RANDOM"), (long) (time((time_t *)0) * kshpid * ppid)); -#endif /* KSH */ - /* setstr can't fail here */ - setstr(global(version_param), ksh_version, KSH_RETURN_ERROR); - - /* execute initialization statements */ - for (wp = (char**)__UNCONST(initcoms); *wp != NULL; wp++) { - shcomexec(wp); - for (; *wp != NULL; wp++) - ; - } - - - ksheuid = geteuid(); - safe_prompt = ksheuid ? "$ " : "# "; - { - struct tbl *vp = global("PS1"); - - /* Set PS1 if it isn't set, or we are root and prompt doesn't - * contain a #. - */ - if (!(vp->flag & ISSET) - || (!ksheuid && !strchr(str_val(vp), '#'))) - /* setstr can't fail here */ - setstr(vp, safe_prompt, KSH_RETURN_ERROR); - } - - /* Set this before parsing arguments */ - Flag(FPRIVILEGED) = getuid() != ksheuid || getgid() != getegid(); - - /* this to note if monitor is set on command line (see below) */ - Flag(FMONITOR) = 127; - argi = parse_args(argv, OF_CMDLINE, (int *) 0); - if (argi < 0) { - exit(1); - /* NOTREACHED */ - } - - if (Flag(FCOMMAND)) { - s = pushs(SSTRING, ATEMP); - if (!(s->start = s->str = argv[argi++])) - errorf("-c requires an argument"); - if (argv[argi]) - kshname = argv[argi++]; - } else if (argi < argc && !Flag(FSTDIN)) { - s = pushs(SFILE, ATEMP); -#ifdef OS2 - /* a bug in os2 extproc shell processing doesn't - * pass full pathnames so we have to search for it. - * This changes the behavior of 'ksh arg' to search - * the users search path but it can't be helped. - */ - s->file = search(argv[argi++], path, R_OK, (int *) 0); - if (!s->file || !*s->file) - s->file = argv[argi - 1]; -#else - s->file = argv[argi++]; -#endif /* OS2 */ - s->u.shf = shf_open(s->file, O_RDONLY, 0, SHF_MAPHI|SHF_CLEXEC); - if (s->u.shf == NULL) { - exstat = 127; /* POSIX */ - errorf("%s: %s", s->file, strerror(errno)); - } - kshname = s->file; - } else { - Flag(FSTDIN) = 1; - s = pushs(SSTDIN, ATEMP); - s->file = ""; - s->u.shf = shf_fdopen(0, SHF_RD | can_seek(0), - (struct shf *) 0); - if (isatty(0) && isatty(2)) { - Flag(FTALKING) = Flag(FTALKING_I) = 1; - /* The following only if isatty(0) */ - s->flags |= SF_TTY; - s->u.shf->flags |= SHF_INTERRUPT; - s->file = (char *) 0; - } - } - - /* This bizarreness is mandated by POSIX */ - { - struct stat s_stdin; - - if (fstat(0, &s_stdin) >= 0 && S_ISCHR(s_stdin.st_mode) && - Flag(FTALKING)) - reset_nonblock(0); - } - - /* initialize job control */ - i = Flag(FMONITOR) != 127; - Flag(FMONITOR) = 0; - j_init(i); -#ifdef EDIT - /* Do this after j_init(), as tty_fd is not initialized 'til then */ - if (Flag(FTALKING)) - x_init(); -#endif - - l = e->loc; - l->argv = &argv[argi - 1]; - l->argc = argc - argi; - l->argv[0] = (char *)__UNCONST(kshname); - getopts_reset(1); - - /* Disable during .profile/ENV reading */ - restricted = Flag(FRESTRICTED); - Flag(FRESTRICTED) = 0; - errexit = Flag(FERREXIT); - Flag(FERREXIT) = 0; - - /* Do this before profile/$ENV so that if it causes problems in them, - * user will know why things broke. - */ - if (!current_wd[0] && Flag(FTALKING)) - warningf(FALSE, "Cannot determine current working directory"); - - if (Flag(FLOGIN)) { -#ifdef OS2 - char *profile; - - /* Try to find a profile - first see if $INIT has a value, - * then try /etc/profile.ksh, then c:/usr/etc/profile.ksh. - */ - if (!Flag(FPRIVILEGED) - && strcmp(profile = substitute("$INIT/profile.ksh", 0), - "/profile.ksh")) - include(profile, 0, (char **) 0, 1); - else if (include("/etc/profile.ksh", 0, (char **) 0, 1) < 0) - include("c:/usr/etc/profile.ksh", 0, (char **) 0, 1); - if (!Flag(FPRIVILEGED)) - include(substitute("$HOME/profile.ksh", 0), 0, - (char **) 0, 1); -#else /* OS2 */ - include(KSH_SYSTEM_PROFILE, 0, (char **) 0, 1); - if (!Flag(FPRIVILEGED)) - include(substitute("$HOME/.profile", 0), 0, - (char **) 0, 1); -#endif /* OS2 */ - } - - if (Flag(FPRIVILEGED)) - include("/etc/suid_profile", 0, (char **) 0, 1); - else { - char *env_file; - -#ifndef KSH - if (!Flag(FPOSIX)) - env_file = null; - else -#endif /* !KSH */ - /* include $ENV */ - env_file = str_val(global("ENV")); - -#ifdef DEFAULT_ENV - /* If env isn't set, include default environment */ - if (env_file == null) - env_file = __UNCONST(DEFAULT_ENV); -#endif /* DEFAULT_ENV */ - env_file = substitute(env_file, DOTILDE); - if (*env_file != '\0') - include(env_file, 0, (char **) 0, 1); -#ifdef OS2 - else if (Flag(FTALKING)) - include(substitute("$HOME/kshrc.ksh", 0), 0, - (char **) 0, 1); -#endif /* OS2 */ - } - - if (is_restricted(argv[0]) || is_restricted(str_val(global("SHELL")))) - restricted = 1; - if (restricted) { - static const char *const restr_com[] = { - "typeset", "-r", "PATH", - "ENV", "SHELL", - (char *) 0 - }; - shcomexec((char **)__UNCONST(restr_com)); - /* After typeset command... */ - Flag(FRESTRICTED) = 1; - } - if (errexit) - Flag(FERREXIT) = 1; - - if (Flag(FTALKING)) { - hist_init(s); -#ifdef KSH - alarm_init(); -#endif /* KSH */ - } else - Flag(FTRACKALL) = 1; /* set after ENV */ - - setlocale(LC_CTYPE, ""); - shell(s, TRUE); /* doesn't return */ - return 0; -} - -int -include(name, argc, argv, intr_ok) - const char *name; - int argc; - char **argv; - int intr_ok; -{ - register Source *volatile s = NULL; - struct shf *shf; - char **volatile old_argv; - volatile int old_argc; - int i; - - shf = shf_open(name, O_RDONLY, 0, SHF_MAPHI|SHF_CLEXEC); - if (shf == NULL) - return -1; - - if (argv) { - old_argv = e->loc->argv; - old_argc = e->loc->argc; - } else { - old_argv = (char **) 0; - old_argc = 0; - } - newenv(E_INCL); - i = ksh_sigsetjmp(e->jbuf, 0); - if (i) { - if (s) /* Do this before quitenv(), which frees the memory */ - shf_close(s->u.shf); - quitenv(); - if (old_argv) { - e->loc->argv = old_argv; - e->loc->argc = old_argc; - } - switch (i) { - case LRETURN: - case LERROR: - return exstat & 0xff; /* see below */ - case LINTR: - /* intr_ok is set if we are including .profile or $ENV. - * If user ^C's out, we don't want to kill the shell... - */ - if (intr_ok && (exstat - 128) != SIGTERM) - return 1; - /* fall through... */ - case LEXIT: - case LLEAVE: - case LSHELL: - unwind(i); - /*NOREACHED*/ - default: - internal_errorf(1, "include: %d", i); - /*NOREACHED*/ - } - } - if (argv) { - e->loc->argv = argv; - e->loc->argc = argc; - } - s = pushs(SFILE, ATEMP); - s->u.shf = shf; - s->file = str_save(name, ATEMP); - i = shell(s, FALSE); - shf_close(s->u.shf); - quitenv(); - if (old_argv) { - e->loc->argv = old_argv; - e->loc->argc = old_argc; - } - return i & 0xff; /* & 0xff to ensure value not -1 */ -} - -int -command(comm) - const char *comm; -{ - register Source *s; - int r; - - s = pushs(SSTRING, ATEMP); - s->start = s->str = comm; - r = shell(s, FALSE); - afree(s, ATEMP); - return r; -} - -/* - * run the commands from the input source, returning status. - */ -int -shell(s, toplevel) - Source *volatile s; /* input source */ - int volatile toplevel; -{ - struct op *t; - volatile int wastty = s->flags & SF_TTY; - volatile int attempts = 13; - volatile int interactive = Flag(FTALKING) && toplevel; - Source *volatile old_source = source; - int i; - - newenv(E_PARSE); - if (interactive) - really_exit = 0; - i = ksh_sigsetjmp(e->jbuf, 0); - if (i) { - switch (i) { - case LINTR: /* we get here if SIGINT not caught or ignored */ - case LERROR: - case LSHELL: - if (interactive) { - if (i == LINTR) - shellf("%s", newline); - /* Reset any eof that was read as part of a - * multiline command. - */ - if (Flag(FIGNOREEOF) && s->type == SEOF - && wastty) - s->type = SSTDIN; - /* Used by exit command to get back to - * top level shell. Kind of strange since - * interactive is set if we are reading from - * a tty, but to have stopped jobs, one only - * needs FMONITOR set (not FTALKING/SF_TTY)... - */ - /* toss any input we have so far */ - s->start = s->str = null; - break; - } - /* fall through... */ - case LEXIT: - case LLEAVE: - case LRETURN: - source = old_source; - quitenv(); - unwind(i); /* keep on going */ - /*NOREACHED*/ - default: - source = old_source; - quitenv(); - internal_errorf(1, "shell: %d", i); - /*NOREACHED*/ - } - } - - while (1) { - if (trap) - runtraps(0); - - if (s->next == NULL) { - if (Flag(FVERBOSE)) - s->flags |= SF_ECHO; - else - s->flags &= ~SF_ECHO; - } - - if (interactive) { - j_notify(); -#ifdef KSH - mcheck(); -#endif /* KSH */ - set_prompt(PS1, s); - } - - t = compile(s); - if (t != NULL && t->type == TEOF) { - if (wastty && Flag(FIGNOREEOF) && --attempts > 0) { - shellf("Use `exit' to leave ksh\n"); - s->type = SSTDIN; - } else if (wastty && !really_exit - && j_stopped_running()) - { - really_exit = 1; - s->type = SSTDIN; - } else { - /* this for POSIX, which says EXIT traps - * shall be taken in the environment - * immediately after the last command - * executed. - */ - if (toplevel) - unwind(LEXIT); - break; - } - } - - if (t && (!Flag(FNOEXEC) || (s->flags & SF_TTY))) - exstat = execute(t, 0); - - if (t != NULL && t->type != TEOF && interactive && really_exit) - really_exit = 0; - - reclaim(); - } - quitenv(); - source = old_source; - return exstat; -} - -/* return to closest error handler or shell(), exit if none found */ -void -unwind(i) - int i; -{ - /* ordering for EXIT vs ERR is a bit odd (this is what at&t ksh does) */ - if (i == LEXIT || (Flag(FERREXIT) && (i == LERROR || i == LINTR) - && sigtraps[SIGEXIT_].trap)) - { - runtrap(&sigtraps[SIGEXIT_]); - i = LLEAVE; - } else if (Flag(FERREXIT) && (i == LERROR || i == LINTR)) { - runtrap(&sigtraps[SIGERR_]); - i = LLEAVE; - } - while (1) { - switch (e->type) { - case E_PARSE: - case E_FUNC: - case E_INCL: - case E_LOOP: - case E_ERRH: - ksh_siglongjmp(e->jbuf, i); - /*NOTREACHED*/ - - case E_NONE: - if (i == LINTR) - e->flags |= EF_FAKE_SIGDIE; - /* Fall through... */ - - default: - quitenv(); - } - } -} - -void -newenv(type) - int type; -{ - register struct env *ep; - - ep = (struct env *) alloc(sizeof(*ep), ATEMP); - ep->type = type; - ep->flags = 0; - ainit(&ep->area); - ep->loc = e->loc; - ep->savefd = NULL; - ep->oenv = e; - ep->temps = NULL; - e = ep; -} - -void -quitenv() -{ - register struct env *ep = e; - register int fd; - - if (ep->oenv && ep->oenv->loc != ep->loc) - popblock(); - if (ep->savefd != NULL) { - for (fd = 0; fd < NUFILE; fd++) - /* if ep->savefd[fd] < 0, means fd was closed */ - if (ep->savefd[fd]) - restfd(fd, ep->savefd[fd]); - if (ep->savefd[2]) /* Clear any write errors */ - shf_reopen(2, SHF_WR, shl_out); - } - reclaim(); - - /* Bottom of the stack. - * Either main shell is exiting or cleanup_parents_env() was called. - */ - if (ep->oenv == NULL) { - if (ep->type == E_NONE) { /* Main shell exiting? */ - if (Flag(FTALKING)) - hist_finish(); - j_exit(); - if (ep->flags & EF_FAKE_SIGDIE) { - int sig = exstat - 128; - - /* ham up our death a bit (at&t ksh - * only seems to do this for SIGTERM) - * Don't do it for SIGQUIT, since we'd - * dump a core.. - */ - if (sig == SIGINT || sig == SIGTERM) { - setsig(&sigtraps[sig], SIG_DFL, - SS_RESTORE_CURR|SS_FORCE); - kill(0, sig); - } - } -#ifdef MEM_DEBUG - chmem_allfree(); -#endif /* MEM_DEBUG */ - } - exit(exstat); - } - - e = e->oenv; - afree(ep, ATEMP); -} - -/* Called after a fork to cleanup stuff left over from parents environment */ -void -cleanup_parents_env() -{ - struct env *ep; - int fd; - - /* Don't clean up temporary files - parent will probably need them. - * Also, can't easily reclaim memory since variables, etc. could be - * anywhere. - */ - - /* close all file descriptors hiding in savefd */ - for (ep = e; ep; ep = ep->oenv) { - if (ep->savefd) { - for (fd = 0; fd < NUFILE; fd++) - if (ep->savefd[fd] > 0) - close(ep->savefd[fd]); - afree(ep->savefd, &ep->area); - ep->savefd = (short *) 0; - } - } - e->oenv = (struct env *) 0; -} - -/* Called just before an execve cleanup stuff temporary files */ -void -cleanup_proc_env() -{ - struct env *ep; - - for (ep = e; ep; ep = ep->oenv) - remove_temps(ep->temps); -} - -/* remove temp files and free ATEMP Area */ -static void -reclaim() -{ - remove_temps(e->temps); - e->temps = NULL; - afreeall(&e->area); -} - -static void -remove_temps(tp) - struct temp *tp; -{ -#ifdef OS2 - static struct temp *delayed_remove; - struct temp *t, **tprev; - - if (delayed_remove) { - for (tprev = &delayed_remove, t = delayed_remove; t; t = *tprev) - /* No need to check t->pid here... */ - if (unlink(t->name) >= 0 || errno == ENOENT) { - *tprev = t->next; - afree(t, APERM); - } else - tprev = &t->next; - } -#endif /* OS2 */ - - for (; tp != NULL; tp = tp->next) - if (tp->pid == procpid) { -#ifdef OS2 - /* OS/2 (and dos) do not allow files that are currently - * open to be removed, so we cache it away for future - * removal. - * XXX should only do this if errno - * is Efile-still-open-can't-remove - * (but I don't know what that is...) - */ - if (unlink(tp->name) < 0 && errno != ENOENT) { - t = (struct temp *) alloc( - sizeof(struct temp) + strlen(tp->name) + 1, - APERM); - memset(t, 0, sizeof(struct temp)); - t->name = (char *) &t[1]; - strlcpy(t->name, tp->name, strlen(tp->name) + 1); - t->next = delayed_remove; - delayed_remove = t; - } -#else /* OS2 */ - unlink(tp->name); -#endif /* OS2 */ - } -} - -/* Returns true if name refers to a restricted shell */ -static int -is_restricted(name) - char *name; -{ - char *p; - - if ((p = ksh_strrchr_dirsep(name))) - name = p; - /* accepts rsh, rksh, rpdksh, pdrksh, etc. */ - return (p = strchr(name, 'r')) && strstr(p, "sh"); -} - -void -aerror(ap, msg) - Area *ap; - const char *msg; -{ - internal_errorf(1, "alloc: %s", msg); - errorf("%s", null); /* this is never executed - keeps gcc quiet */ - /*NOTREACHED*/ -} diff --git a/bin/ksh/misc.c b/bin/ksh/misc.c deleted file mode 100644 index 94ae44b2c..000000000 --- a/bin/ksh/misc.c +++ /dev/null @@ -1,1364 +0,0 @@ -/* $NetBSD: misc.c,v 1.15 2011/10/16 17:12:11 joerg Exp $ */ - -/* - * Miscellaneous functions - */ -#include - -#ifndef lint -__RCSID("$NetBSD: misc.c,v 1.15 2011/10/16 17:12:11 joerg Exp $"); -#endif - - -#include "sh.h" -#include /* for FILECHCONV */ -#ifdef HAVE_LIMITS_H -# include -#endif - -#ifndef UCHAR_MAX -# define UCHAR_MAX 0xFF -#endif - -short ctypes [UCHAR_MAX+1]; /* type bits for unsigned char */ - -static int do_gmatch ARGS((const unsigned char *s, const unsigned char *p, - const unsigned char *se, const unsigned char *pe, - int isfile)); -static const unsigned char *cclass ARGS((const unsigned char *p, int sub)); - -/* - * Fast character classes - */ -void -setctypes(s, t) - register const char *s; - register int t; -{ - register int i; - - if (t & C_IFS) { - for (i = 0; i < UCHAR_MAX+1; i++) - ctypes[i] &= ~C_IFS; - ctypes[0] |= C_IFS; /* include \0 in C_IFS */ - } - while (*s != 0) - ctypes[(unsigned char) *s++] |= t; -} - -void -initctypes() -{ - register int c; - - for (c = 'a'; c <= 'z'; c++) - ctypes[c] |= C_ALPHA; - for (c = 'A'; c <= 'Z'; c++) - ctypes[c] |= C_ALPHA; - ctypes['_'] |= C_ALPHA; - setctypes("0123456789", C_DIGIT); - setctypes(" \t\n|&;<>()", C_LEX1); /* \0 added automatically */ - setctypes("*@#!$-?", C_VAR1); - setctypes(" \t\n", C_IFSWS); - setctypes("=-+?", C_SUBOP1); - setctypes("#%", C_SUBOP2); - setctypes(" \n\t\"#$&'()*;<>?[\\`|", C_QUOTE); -} - -/* convert unsigned long to base N string */ - -char * -ulton(n, base) - register unsigned long n; - int base; -{ - register char *p; - static char buf [20]; - - p = &buf[sizeof(buf)]; - *--p = '\0'; - do { - *--p = "0123456789ABCDEF"[n%base]; - n /= base; - } while (n != 0); - return p; -} - -char * -str_save(s, ap) - register const char *s; - Area *ap; -{ - size_t len; - char *p; - - if (!s) - return NULL; - len = strlen(s)+1; - p = alloc(len, ap); - strlcpy(p, s, len); - return (p); -} - -/* Allocate a string of size n+1 and copy upto n characters from the possibly - * null terminated string s into it. Always returns a null terminated string - * (unless n < 0). - */ -char * -str_nsave(s, n, ap) - register const char *s; - int n; - Area *ap; -{ - char *ns; - - if (n < 0) - return 0; - ns = alloc(n + 1, ap); - ns[0] = '\0'; - return strncat(ns, s, n); -} - -/* called from expand.h:XcheckN() to grow buffer */ -char * -Xcheck_grow_(xsp, xp, more) - XString *xsp; - char *xp; - int more; -{ - char *old_beg = xsp->beg; - - xsp->len += (size_t)more > xsp->len ? (size_t)more : xsp->len; - xsp->beg = aresize(xsp->beg, xsp->len + 8, xsp->areap); - xsp->end = xsp->beg + xsp->len; - return xsp->beg + (xp - old_beg); -} - -const struct option goptions[] = { - /* Special cases (see parse_args()): -A, -o, -s. - * Options are sorted by their longnames - the order of these - * entries MUST match the order of sh_flag F* enumerations in sh.h. - */ - { "allexport", 'a', OF_ANY }, -#ifdef BRACE_EXPAND - { "braceexpand", 0, OF_ANY }, /* non-standard */ -#endif - { "bgnice", 0, OF_ANY }, - { (char *) 0, 'c', OF_CMDLINE }, -#ifdef EMACS - { "emacs", 0, OF_ANY }, - { "emacs-usemeta", 0, OF_ANY }, /* non-standard */ -#endif - { "errexit", 'e', OF_ANY }, -#ifdef EMACS - { "gmacs", 0, OF_ANY }, -#endif - { "ignoreeof", 0, OF_ANY }, - { "interactive",'i', OF_CMDLINE }, - { "keyword", 'k', OF_ANY }, - { "login", 'l', OF_CMDLINE }, - { "markdirs", 'X', OF_ANY }, -#ifdef JOBS - { "monitor", 'm', OF_ANY }, -#else /* JOBS */ - { (char *) 0, 'm', 0 }, /* so FMONITOR not ifdef'd */ -#endif /* JOBS */ - { "noclobber", 'C', OF_ANY }, - { "noexec", 'n', OF_ANY }, - { "noglob", 'f', OF_ANY }, - { "nohup", 0, OF_ANY }, - { "nolog", 0, OF_ANY }, /* no effect */ -#ifdef JOBS - { "notify", 'b', OF_ANY }, -#endif /* JOBS */ - { "nounset", 'u', OF_ANY }, - { "physical", 0, OF_ANY }, /* non-standard */ - { "posix", 0, OF_ANY }, /* non-standard */ - { "privileged", 'p', OF_ANY }, - { "restricted", 'r', OF_CMDLINE }, - { "stdin", 's', OF_CMDLINE }, /* pseudo non-standard */ - { "trackall", 'h', OF_ANY }, - { "verbose", 'v', OF_ANY }, -#ifdef VI - { "vi", 0, OF_ANY }, - { "viraw", 0, OF_ANY }, /* no effect */ - { "vi-show8", 0, OF_ANY }, /* non-standard */ - { "vi-tabcomplete", 0, OF_ANY }, /* non-standard */ - { "vi-esccomplete", 0, OF_ANY }, /* non-standard */ -#endif - { "xtrace", 'x', OF_ANY }, - /* Anonymous flags: used internally by shell only - * (not visible to user) - */ - { (char *) 0, 0, OF_INTERNAL }, /* FTALKING_I */ -}; - -/* - * translate -o option into F* constant (also used for test -o option) - */ -int -option(n) - const char *n; -{ - int i; - - for (i = 0; i < (int)NELEM(goptions); i++) - if (goptions[i].name && strcmp(goptions[i].name, n) == 0) - return i; - - return -1; -} - -struct options_info { - int opt_width; - struct { - const char *name; - int flag; - } opts[NELEM(goptions)]; -}; - -static char *options_fmt_entry ARGS((void *arg, int i, char *buf, int buflen)); -static void printoptions ARGS((int verbose)); - -/* format a single select menu item */ -static char * -options_fmt_entry(arg, i, buf, buflen) - void *arg; - int i; - char *buf; - int buflen; -{ - struct options_info *oi = (struct options_info *) arg; - - shf_snprintf(buf, buflen, "%-*s %s", - oi->opt_width, oi->opts[i].name, - Flag(oi->opts[i].flag) ? "on" : "off"); - return buf; -} - -static void -printoptions(verbose) - int verbose; -{ - int i; - - if (verbose) { - struct options_info oi; - int n, len; - - /* verbose version */ - shprintf("Current option settings\n"); - - for (i = n = oi.opt_width = 0; i < (int)NELEM(goptions); i++) - if (goptions[i].name) { - len = strlen(goptions[i].name); - oi.opts[n].name = goptions[i].name; - oi.opts[n++].flag = i; - if (len > oi.opt_width) - oi.opt_width = len; - } - print_columns(shl_stdout, n, options_fmt_entry, &oi, - oi.opt_width + 5, 1); - } else { - /* short version ala ksh93 */ - shprintf("set"); - for (i = 0; i < (int)NELEM(goptions); i++) - if (Flag(i) && goptions[i].name) - shprintf(" -o %s", goptions[i].name); - shprintf("%s", newline); - } -} - -char * -getoptions() -{ - size_t i; - char m[(int) FNFLAGS + 1]; - register char *cp = m; - - for (i = 0; i < NELEM(goptions); i++) - if (goptions[i].c && Flag(i)) - *cp++ = goptions[i].c; - *cp = 0; - return str_save(m, ATEMP); -} - -/* change a Flag(*) value; takes care of special actions */ -void -change_flag(f, what, newval) - enum sh_flag f; /* flag to change */ - int what; /* what is changing the flag (command line vs set) */ - int newval; -{ - int oldval; - - oldval = Flag(f); - Flag(f) = newval; -#ifdef JOBS - if (f == FMONITOR) { - if (what != OF_CMDLINE && newval != oldval) - j_change(); - } else -#endif /* JOBS */ -#ifdef EDIT - if (0 -# ifdef VI - || f == FVI -# endif /* VI */ -# ifdef EMACS - || f == FEMACS || f == FGMACS -# endif /* EMACS */ - ) - { - if (newval) { -# ifdef VI - Flag(FVI) = 0; -# endif /* VI */ -# ifdef EMACS - Flag(FEMACS) = Flag(FGMACS) = 0; -# endif /* EMACS */ - Flag(f) = newval; - } - } else -#endif /* EDIT */ - /* Turning off -p? */ - if (f == FPRIVILEGED && oldval && !newval) { -#ifdef OS2 - ; -#else /* OS2 */ - seteuid(ksheuid = getuid()); - setuid(ksheuid); - setegid(getgid()); - setgid(getgid()); -#endif /* OS2 */ - } else if (f == FPOSIX && newval) { -#ifdef BRACE_EXPAND - Flag(FBRACEEXPAND) = 0 -#endif /* BRACE_EXPAND */ - ; - } - /* Changing interactive flag? */ - if (f == FTALKING) { - if ((what == OF_CMDLINE || what == OF_SET) && procpid == kshpid) - Flag(FTALKING_I) = newval; - } -} - -/* parse command line & set command arguments. returns the index of - * non-option arguments, -1 if there is an error. - */ -int -parse_args(argv, what, setargsp) - char **argv; - int what; /* OF_CMDLINE or OF_SET */ - int *setargsp; -{ - static char cmd_opts[NELEM(goptions) + 3]; /* o:\0 */ - static char set_opts[NELEM(goptions) + 5]; /* Ao;s\0 */ - char *opts; - char *array = (char *) 0; - Getopt go; - int i, optc, set, sortargs = 0, arrayset = 0; - - /* First call? Build option strings... */ - if (cmd_opts[0] == '\0') { - char *p, *q; - - /* see cmd_opts[] declaration */ - strlcpy(cmd_opts, "o:", sizeof cmd_opts); - p = cmd_opts + strlen(cmd_opts); - /* see set_opts[] declaration */ - strlcpy(set_opts, "A:o;s", sizeof set_opts); - q = set_opts + strlen(set_opts); - for (i = 0; i < (int)NELEM(goptions); i++) { - if (goptions[i].c) { - if (goptions[i].flags & OF_CMDLINE) - *p++ = goptions[i].c; - if (goptions[i].flags & OF_SET) - *q++ = goptions[i].c; - } - } - *p = '\0'; - *q = '\0'; - } - - if (what == OF_CMDLINE) { - char *p; - /* Set FLOGIN before parsing options so user can clear - * flag using +l. - */ - Flag(FLOGIN) = (argv[0][0] == '-' - || ((p = ksh_strrchr_dirsep(argv[0])) - && *++p == '-')); - opts = cmd_opts; - } else - opts = set_opts; - ksh_getopt_reset(&go, GF_ERROR|GF_PLUSOPT); - while ((optc = ksh_getopt(argv, &go, opts)) != EOF) { - set = (go.info & GI_PLUS) ? 0 : 1; - switch (optc) { - case 'A': - arrayset = set ? 1 : -1; - array = go.optarg; - break; - - case 'o': - if (go.optarg == (char *) 0) { - /* lone -o: print options - * - * Note that on the command line, -o requires - * an option (ie, can't get here if what is - * OF_CMDLINE). - */ - printoptions(set); - break; - } - i = option(go.optarg); - if (i >= 0 && set == Flag(i)) - /* Don't check the context if the flag - * isn't changing - makes "set -o interactive" - * work if you're already interactive. Needed - * if the output of "set +o" is to be used. - */ - ; - else if (i >= 0 && (goptions[i].flags & what)) - change_flag((enum sh_flag) i, what, set); - else { - bi_errorf("%s: bad option", go.optarg); - return -1; - } - break; - - case '?': - return -1; - - default: - /* -s: sort positional params (at&t ksh stupidity) */ - if (what == OF_SET && optc == 's') { - sortargs = 1; - break; - } - for (i = 0; i < (int)NELEM(goptions); i++) - if (optc == goptions[i].c - && (what & goptions[i].flags)) - { - change_flag((enum sh_flag) i, what, - set); - break; - } - if (i == NELEM(goptions)) { - internal_errorf(1, "parse_args: `%c'", optc); - return -1; /* not reached */ - } - } - } - if (!(go.info & GI_MINUSMINUS) && argv[go.optind] - && (argv[go.optind][0] == '-' || argv[go.optind][0] == '+') - && argv[go.optind][1] == '\0') - { - /* lone - clears -v and -x flags */ - if (argv[go.optind][0] == '-' && !Flag(FPOSIX)) - Flag(FVERBOSE) = Flag(FXTRACE) = 0; - /* set skips lone - or + option */ - go.optind++; - } - if (setargsp) - /* -- means set $#/$* even if there are no arguments */ - *setargsp = !arrayset && ((go.info & GI_MINUSMINUS) - || argv[go.optind]); - - if (arrayset && (!*array || *skip_varname(array, FALSE))) { - bi_errorf("%s: is not an identifier", array); - return -1; - } - if (sortargs) { - for (i = go.optind; argv[i]; i++) - ; - qsortp((void **) &argv[go.optind], (size_t) (i - go.optind), - xstrcmp); - } - if (arrayset) { - set_array(array, arrayset, argv + go.optind); - for (; argv[go.optind]; go.optind++) - ; - } - - return go.optind; -} - -/* parse a decimal number: returns 0 if string isn't a number, 1 otherwise */ -int -getn(as, ai) - const char *as; - int *ai; -{ - char *p; - long n; - - n = strtol(as, &p, 10); - - if (!*as || *p || INT_MIN >= n || n >= INT_MAX) - return 0; - - *ai = (int)n; - return 1; -} - -/* getn() that prints error */ -int -bi_getn(as, ai) - const char *as; - int *ai; -{ - int rv = getn(as, ai); - - if (!rv) - bi_errorf("%s: bad number", as); - return rv; -} - -/* -------- gmatch.c -------- */ - -/* - * int gmatch(string, pattern) - * char *string, *pattern; - * - * Match a pattern as in sh(1). - * pattern character are prefixed with MAGIC by expand. - */ - -int -gmatch(s, p, isfile) - const char *s, *p; - int isfile; -{ - const char *se, *pe; - - if (s == NULL || p == NULL) - return 0; - se = s + strlen(s); - pe = p + strlen(p); - /* isfile is false iff no syntax check has been done on - * the pattern. If check fails, just to a strcmp(). - */ - if (!isfile && !has_globbing(p, pe)) { - int len = pe - p + 1; - char tbuf[64]; - char *t = len <= (int)sizeof(tbuf) ? tbuf - : (char *) alloc(len, ATEMP); - debunk(t, p, len); - return !strcmp(t, s); - } - return do_gmatch((const unsigned char *) s, (const unsigned char *) se, - (const unsigned char *) p, (const unsigned char *) pe, - isfile); -} - -/* Returns if p is a syntacticly correct globbing pattern, false - * if it contains no pattern characters or if there is a syntax error. - * Syntax errors are: - * - [ with no closing ] - * - imbalanced $(...) expression - * - [...] and *(...) not nested (eg, [a$(b|]c), *(a[b|c]d)) - */ -/*XXX -- if no magic, - if dest given, copy to dst - return ? -- if magic && (no globbing || syntax error) - debunk to dst - return ? -- return ? -*/ -int -has_globbing(xp, xpe) - const char *xp, *xpe; -{ - const unsigned char *p = (const unsigned char *) xp; - const unsigned char *pe = (const unsigned char *) xpe; - int c; - int nest = 0, bnest = 0; - int saw_glob = 0; - int in_bracket = 0; /* inside [...] */ - - for (; p < pe; p++) { - if (!ISMAGIC(*p)) - continue; - if ((c = *++p) == '*' || c == '?') - saw_glob = 1; - else if (c == '[') { - if (!in_bracket) { - saw_glob = 1; - in_bracket = 1; - if (ISMAGIC(p[1]) && p[2] == NOT) - p += 2; - if (ISMAGIC(p[1]) && p[2] == ']') - p += 2; - } - /* XXX Do we need to check ranges here? POSIX Q */ - } else if (c == ']') { - if (in_bracket) { - if (bnest) /* [a*(b]) */ - return 0; - in_bracket = 0; - } - } else if ((c & 0x80) && strchr("*+?@! ", c & 0x7f)) { - saw_glob = 1; - if (in_bracket) - bnest++; - else - nest++; - } else if (c == '|') { - if (in_bracket && !bnest) /* *(a[foo|bar]) */ - return 0; - } else if (c == /*(*/ ')') { - if (in_bracket) { - if (!bnest--) /* *(a[b)c] */ - return 0; - } else if (nest) - nest--; - } - /* else must be a MAGIC-MAGIC, or MAGIC-!, MAGIC--, MAGIC-] - MAGIC-{, MAGIC-,, MAGIC-} */ - } - return saw_glob && !in_bracket && !nest; -} - -/* Function must return either 0 or 1 (assumed by code for 0x80|'!') */ -static int -do_gmatch(s, se, p, pe, isfile) - const unsigned char *s, *p; - const unsigned char *se, *pe; - int isfile; -{ - register int sc, pc; - const unsigned char *prest, *psub, *pnext; - const unsigned char *srest; - - if (s == NULL || p == NULL) - return 0; - while (p < pe) { - pc = *p++; - sc = s < se ? *s : '\0'; - s++; - if (isfile) { - sc = FILECHCONV((unsigned char)sc); - pc = FILECHCONV((unsigned char)pc); - } - if (!ISMAGIC(pc)) { - if (sc != pc) - return 0; - continue; - } - switch (*p++) { - case '[': - if (sc == 0 || (p = cclass(p, sc)) == NULL) - return 0; - break; - - case '?': - if (sc == 0) - return 0; - break; - - case '*': - if (p == pe) - return 1; - s--; - do { - if (do_gmatch(s, se, p, pe, isfile)) - return 1; - } while (s++ < se); - return 0; - - /* - * [*+?@!](pattern|pattern|..) - * - * Not ifdef'd KSH as this is needed for ${..%..}, etc. - */ - case 0x80|'+': /* matches one or more times */ - case 0x80|'*': /* matches zero or more times */ - if (!(prest = pat_scan(p, pe, 0))) - return 0; - s--; - /* take care of zero matches */ - if (p[-1] == (0x80 | '*') - && do_gmatch(s, se, prest, pe, isfile)) - return 1; - for (psub = p; ; psub = pnext) { - pnext = pat_scan(psub, pe, 1); - for (srest = s; srest <= se; srest++) { - if (do_gmatch(s, srest, - psub, pnext - 2, isfile) - && (do_gmatch(srest, se, - prest, pe, isfile) - || (s != srest - && do_gmatch(srest, se, - p - 2, pe, isfile)))) - return 1; - } - if (pnext == prest) - break; - } - return 0; - - case 0x80|'?': /* matches zero or once */ - case 0x80|'@': /* matches one of the patterns */ - case 0x80|' ': /* simile for @ */ - if (!(prest = pat_scan(p, pe, 0))) - return 0; - s--; - /* Take care of zero matches */ - if (p[-1] == (0x80 | '?') - && do_gmatch(s, se, prest, pe, isfile)) - return 1; - for (psub = p; ; psub = pnext) { - pnext = pat_scan(psub, pe, 1); - srest = prest == pe ? se : s; - for (; srest <= se; srest++) { - if (do_gmatch(s, srest, - psub, pnext - 2, isfile) - && do_gmatch(srest, se, - prest, pe, isfile)) - return 1; - } - if (pnext == prest) - break; - } - return 0; - - case 0x80|'!': /* matches none of the patterns */ - if (!(prest = pat_scan(p, pe, 0))) - return 0; - s--; - for (srest = s; srest <= se; srest++) { - int matched = 0; - - for (psub = p; ; psub = pnext) { - pnext = pat_scan(psub, pe, 1); - if (do_gmatch(s, srest, - psub, pnext - 2, isfile)) - { - matched = 1; - break; - } - if (pnext == prest) - break; - } - if (!matched && do_gmatch(srest, se, - prest, pe, isfile)) - return 1; - } - return 0; - - default: - if (sc != p[-1]) - return 0; - break; - } - } - return s == se; -} - -static const unsigned char * -cclass(p, sub) - const unsigned char *p; - register int sub; -{ - register int c, d, not, found = 0; - const unsigned char *orig_p = p; - - if ((not = (ISMAGIC(*p) && *++p == NOT))) - p++; - do { - c = *p++; - if (ISMAGIC(c)) { - c = *p++; - if ((c & 0x80) && !ISMAGIC(c)) { - c &= 0x7f;/* extended pattern matching: *+?@! */ - /* XXX the ( char isn't handled as part of [] */ - if (c == ' ') /* simile for @: plain (..) */ - c = '(' /*)*/; - } - } - if (c == '\0') - /* No closing ] - act as if the opening [ was quoted */ - return sub == '[' ? orig_p : NULL; - if (ISMAGIC(p[0]) && p[1] == '-' - && (!ISMAGIC(p[2]) || p[3] != ']')) - { - p += 2; /* MAGIC- */ - d = *p++; - if (ISMAGIC(d)) { - d = *p++; - if ((d & 0x80) && !ISMAGIC(d)) - d &= 0x7f; - } - /* POSIX says this is an invalid expression */ - if (c > d) - return NULL; - } else - d = c; - if (c == sub || (c <= sub && sub <= d)) - found = 1; - } while (!(ISMAGIC(p[0]) && p[1] == ']')); - - return (found != not) ? p+2 : NULL; -} - -/* Look for next ) or | (if match_sep) in *(foo|bar) pattern */ -const unsigned char * -pat_scan(p, pe, match_sep) - const unsigned char *p; - const unsigned char *pe; - int match_sep; -{ - int nest = 0; - - for (; p < pe; p++) { - if (!ISMAGIC(*p)) - continue; - if ((*++p == /*(*/ ')' && nest-- == 0) - || (*p == '|' && match_sep && nest == 0)) - return ++p; - if ((*p & 0x80) && strchr("*+?@! ", *p & 0x7f)) - nest++; - } - return (const unsigned char *) 0; -} - - -/* -------- qsort.c -------- */ - -/* - * quick sort of array of generic pointers to objects. - */ -static void qsort1 ARGS((void **base, void **lim, int (*f)(void *, void *))); - -void -qsortp(base, n, f) - void **base; /* base address */ - size_t n; /* elements */ - int (*f) ARGS((void *, void *)); /* compare function */ -{ - qsort1(base, base + n, f); -} - -#define swap2(a, b) {\ - register void *t; t = *(a); *(a) = *(b); *(b) = t;\ -} -#define swap3(a, b, c) {\ - register void *t; t = *(a); *(a) = *(c); *(c) = *(b); *(b) = t;\ -} - -static void -qsort1(base, lim, f) - void **base, **lim; - int (*f) ARGS((void *, void *)); -{ - register void **i, **j; - register void **lptr, **hptr; - size_t n; - int c; - - top: - n = (lim - base) / 2; - if (n == 0) - return; - hptr = lptr = base+n; - i = base; - j = lim - 1; - - for (;;) { - if (i < lptr) { - if ((c = (*f)(*i, *lptr)) == 0) { - lptr--; - swap2(i, lptr); - continue; - } - if (c < 0) { - i += 1; - continue; - } - } - - begin: - if (j > hptr) { - if ((c = (*f)(*hptr, *j)) == 0) { - hptr++; - swap2(hptr, j); - goto begin; - } - if (c > 0) { - if (i == lptr) { - hptr++; - swap3(i, hptr, j); - i = lptr += 1; - goto begin; - } - swap2(i, j); - j -= 1; - i += 1; - continue; - } - j -= 1; - goto begin; - } - - if (i == lptr) { - if (lptr-base >= lim-hptr) { - qsort1(hptr+1, lim, f); - lim = lptr; - } else { - qsort1(base, lptr, f); - base = hptr+1; - } - goto top; - } - - lptr -= 1; - swap3(j, lptr, i); - j = hptr -= 1; - } -} - -int -xstrcmp(p1, p2) - void *p1, *p2; -{ - return (strcmp((char *)p1, (char *)p2)); -} - -/* Initialize a Getopt structure */ -void -ksh_getopt_reset(go, flags) - Getopt *go; - int flags; -{ - go->optind = 1; - go->optarg = (char *) 0; - go->p = 0; - go->flags = flags; - go->info = 0; - go->buf[1] = '\0'; -} - - -/* getopt() used for shell built-in commands, the getopts command, and - * command line options. - * A leading ':' in options means don't print errors, instead return '?' - * or ':' and set go->optarg to the offending option character. - * If GF_ERROR is set (and option doesn't start with :), errors result in - * a call to bi_errorf(). - * - * Non-standard features: - * - ';' is like ':' in options, except the argument is optional - * (if it isn't present, optarg is set to 0). - * Used for 'set -o'. - * - ',' is like ':' in options, except the argument always immediately - * follows the option character (optarg is set to the null string if - * the option is missing). - * Used for 'read -u2', 'print -u2' and fc -40. - * - '#' is like ':' in options, expect that the argument is optional - * and must start with a digit. If the argument doesn't start with a - * digit, it is assumed to be missing and normal option processing - * continues (optarg is set to 0 if the option is missing). - * Used for 'typeset -LZ4'. - * - accepts +c as well as -c IF the GF_PLUSOPT flag is present. If an - * option starting with + is accepted, the GI_PLUS flag will be set - * in go->info. - */ -int -ksh_getopt(argv, go, options) - char **argv; - Getopt *go; - const char *options; -{ - char c; - char *o; - - if (go->p == 0 || (c = argv[go->optind - 1][go->p]) == '\0') { - char *arg = argv[go->optind], flag = arg ? *arg : '\0'; - - go->p = 1; - if (flag == '-' && arg[1] == '-' && arg[2] == '\0') { - go->optind++; - go->p = 0; - go->info |= GI_MINUSMINUS; - return EOF; - } - if (arg == (char *) 0 - || ((flag != '-' ) /* neither a - nor a + (if + allowed) */ - && (!(go->flags & GF_PLUSOPT) || flag != '+')) - || (c = arg[1]) == '\0') - { - go->p = 0; - return EOF; - } - go->optind++; - go->info &= ~(GI_MINUS|GI_PLUS); - go->info |= flag == '-' ? GI_MINUS : GI_PLUS; - } - go->p++; - if (c == '?' || c == ':' || c == ';' || c == ',' || c == '#' - || !(o = strchr(options, c))) - { - if (options[0] == ':') { - go->buf[0] = c; - go->optarg = go->buf; - } else { - warningf(TRUE, "%s%s-%c: unknown option", - (go->flags & GF_NONAME) ? "" : argv[0], - (go->flags & GF_NONAME) ? "" : ": ", c); - if (go->flags & GF_ERROR) - bi_errorf("%s", null); - } - return '?'; - } - /* : means argument must be present, may be part of option argument - * or the next argument - * ; same as : but argument may be missing - * , means argument is part of option argument, and may be null. - */ - if (*++o == ':' || *o == ';') { - if (argv[go->optind - 1][go->p]) - go->optarg = argv[go->optind - 1] + go->p; - else if (argv[go->optind]) - go->optarg = argv[go->optind++]; - else if (*o == ';') - go->optarg = (char *) 0; - else { - if (options[0] == ':') { - go->buf[0] = c; - go->optarg = go->buf; - return ':'; - } - warningf(TRUE, "%s%s-`%c' requires argument", - (go->flags & GF_NONAME) ? "" : argv[0], - (go->flags & GF_NONAME) ? "" : ": ", c); - if (go->flags & GF_ERROR) - bi_errorf("%s", null); - return '?'; - } - go->p = 0; - } else if (*o == ',') { - /* argument is attached to option character, even if null */ - go->optarg = argv[go->optind - 1] + go->p; - go->p = 0; - } else if (*o == '#') { - /* argument is optional and may be attached or unattached - * but must start with a digit. optarg is set to 0 if the - * argument is missing. - */ - if (argv[go->optind - 1][go->p]) { - if (digit(argv[go->optind - 1][go->p])) { - go->optarg = argv[go->optind - 1] + go->p; - go->p = 0; - } else - go->optarg = (char *) 0; - } else { - if (argv[go->optind] && digit(argv[go->optind][0])) { - go->optarg = argv[go->optind++]; - go->p = 0; - } else - go->optarg = (char *) 0; - } - } - return c; -} - -/* print variable/alias value using necessary quotes - * (POSIX says they should be suitable for re-entry...) - * No trailing newline is printed. - */ -void -print_value_quoted(s) - const char *s; -{ - const char *p; - int inquote = 0; - - /* Test if any quotes are needed */ - for (p = s; *p; p++) - if (ctype(*p, C_QUOTE)) - break; - if (!*p) { - shprintf("%s", s); - return; - } - for (p = s; *p; p++) { - if (*p == '\'') { - shprintf("%s", "'\\'" + 1 - inquote); - inquote = 0; - } else { - if (!inquote) { - shprintf("'"); - inquote = 1; - } - shf_putc(*p, shl_stdout); - } - } - if (inquote) - shprintf("'"); -} - -/* Print things in columns and rows - func() is called to format the ith - * element - */ -void -print_columns(shf, n, func, arg, max_width, prefcol) - struct shf *shf; - int n; - char *(*func) ARGS((void *, int, char *, int)); - void *arg; - int max_width; - int prefcol; -{ - char *str = (char *) alloc(max_width + 1, ATEMP); - int i; - int r, c; - int rows, cols; - int nspace; - - /* max_width + 1 for the space. Note that no space - * is printed after the last column to avoid problems - * with terminals that have auto-wrap. - */ - cols = x_cols / (max_width + 1); - if (!cols) - cols = 1; - rows = (n + cols - 1) / cols; - if (prefcol && n && cols > rows) { - int tmp = rows; - - rows = cols; - cols = tmp; - if (rows > n) - rows = n; - } - - nspace = (x_cols - max_width * cols) / cols; - if (nspace <= 0) - nspace = 1; - for (r = 0; r < rows; r++) { - for (c = 0; c < cols; c++) { - i = c * rows + r; - if (i < n) { - shf_fprintf(shf, "%-*s", - max_width, - (*func)(arg, i, str, max_width + 1)); - if (c + 1 < cols) - shf_fprintf(shf, "%*s", nspace, null); - } - } - shf_putchar('\n', shf); - } - afree(str, ATEMP); -} - -/* Strip any nul bytes from buf - returns new length (nbytes - # of nuls) */ -int -strip_nuls(buf, nbytes) - char *buf; - int nbytes; -{ - char *dst; - - /* nbytes check because some systems (older freebsd's) have a buggy - * memchr() - */ - if (nbytes && (dst = memchr(buf, '\0', nbytes))) { - char *end = buf + nbytes; - char *p, *q; - - for (p = dst; p < end; p = q) { - /* skip a block of nulls */ - while (++p < end && *p == '\0') - ; - /* find end of non-null block */ - if (!(q = memchr(p, '\0', end - p))) - q = end; - memmove(dst, p, q - p); - dst += q - p; - } - *dst = '\0'; - return dst - buf; - } - return nbytes; -} - -/* Copy at most dsize-1 bytes from src to dst, ensuring dst is null terminated. - * Returns dst. - */ -char * -str_zcpy(dst, src, dsize) - char *dst; - const char *src; - int dsize; -{ - if (dsize > 0) { - int len = strlen(src); - - if (len >= dsize) - len = dsize - 1; - memcpy(dst, src, len); - dst[len] = '\0'; - } - return dst; -} - -/* Like read(2), but if read fails due to non-blocking flag, resets flag - * and restarts read. - */ -int -blocking_read(fd, buf, nbytes) - int fd; - char *buf; - int nbytes; -{ - int ret; - int tried_reset = 0; - - while ((ret = read(fd, buf, nbytes)) < 0) { - if (!tried_reset && (errno == EAGAIN -#ifdef EWOULDBLOCK - || errno == EWOULDBLOCK -#endif /* EWOULDBLOCK */ - )) - { - int oerrno = errno; - if (reset_nonblock(fd) > 0) { - tried_reset = 1; - continue; - } - errno = oerrno; - } - break; - } - return ret; -} - -/* Reset the non-blocking flag on the specified file descriptor. - * Returns -1 if there was an error, 0 if non-blocking wasn't set, - * 1 if it was. - */ -int -reset_nonblock(fd) - int fd; -{ - int flags; - int blocking_flags; - - if ((flags = fcntl(fd, F_GETFL, 0)) < 0) - return -1; - /* With luck, the C compiler will reduce this to a constant */ - blocking_flags = 0; -#ifdef O_NONBLOCK - blocking_flags |= O_NONBLOCK; -#endif /* O_NONBLOCK */ -#ifdef O_NDELAY - blocking_flags |= O_NDELAY; -#else /* O_NDELAY */ -# ifndef O_NONBLOCK - blocking_flags |= FNDELAY; /* hope this exists... */ -# endif /* O_NONBLOCK */ -#endif /* O_NDELAY */ - if (!(flags & blocking_flags)) - return 0; - flags &= ~blocking_flags; - if (fcntl(fd, F_SETFL, flags) < 0) - return -1; - return 1; -} - - -#ifdef HAVE_SYS_PARAM_H -# include -#endif /* HAVE_SYS_PARAM_H */ -#ifndef MAXPATHLEN -# define MAXPATHLEN PATH -#endif /* MAXPATHLEN */ - -#ifdef HPUX_GETWD_BUG -# include "ksh_dir.h" - -/* - * Work around bug in hpux 10.x C library - getwd/getcwd dump core - * if current directory is not readable. Done in macro 'cause code - * is needed in GETWD and GETCWD cases. - */ -# define HPUX_GETWD_BUG_CODE \ - { \ - DIR *d = ksh_opendir("."); \ - if (!d) \ - return (char *) 0; \ - closedir(d); \ - } -#else /* HPUX_GETWD_BUG */ -# define HPUX_GETWD_BUG_CODE -#endif /* HPUX_GETWD_BUG */ - -/* Like getcwd(), except bsize is ignored if buf is 0 (MAXPATHLEN is used) */ -char * -ksh_get_wd(buf, bsize) - char *buf; - int bsize; -{ -#ifdef HAVE_GETCWD - char *b; - char *ret; - - /* Before memory allocated */ - HPUX_GETWD_BUG_CODE - - /* Assume getcwd() available */ - if (!buf) { - bsize = MAXPATHLEN; - b = alloc(MAXPATHLEN + 1, ATEMP); - } else - b = buf; - - ret = getcwd(b, bsize); - - if (!buf) { - if (ret) - ret = aresize(b, strlen(b) + 1, ATEMP); - else - afree(b, ATEMP); - } - - return ret; -#else /* HAVE_GETCWD */ - extern char *getwd ARGS((char *)); - char *b; - int len; - - /* Before memory allocated */ - HPUX_GETWD_BUG_CODE - - if (buf && bsize > MAXPATHLEN) - b = buf; - else - b = alloc(MAXPATHLEN + 1, ATEMP); - if (!getcwd(b, MAXPATHLEN)) { - errno = EACCES; - if (b != buf) - afree(b, ATEMP); - return (char *) 0; - } - len = strlen(b) + 1; - if (!buf) - b = aresize(b, len, ATEMP); - else if (buf != b) { - if (len > bsize) { - errno = ERANGE; - return (char *) 0; - } - memcpy(buf, b, len); - afree(b, ATEMP); - b = buf; - } - - return b; -#endif /* HAVE_GETCWD */ -} diff --git a/bin/ksh/path.c b/bin/ksh/path.c deleted file mode 100644 index 31e59b4f9..000000000 --- a/bin/ksh/path.c +++ /dev/null @@ -1,318 +0,0 @@ -/* $NetBSD: path.c,v 1.8 2009/04/25 05:11:37 lukem Exp $ */ -#include - -#ifndef lint -__RCSID("$NetBSD: path.c,v 1.8 2009/04/25 05:11:37 lukem Exp $"); -#endif - - -#include "sh.h" -#include "ksh_stat.h" - -/* - * Contains a routine to search a : separated list of - * paths (a la CDPATH) and make appropriate file names. - * Also contains a routine to simplify .'s and ..'s out of - * a path name. - * - * Larry Bouzane (larry@cs.mun.ca) - */ - -#ifdef S_ISLNK -static char *do_phys_path ARGS((XString *, char *, const char *)); -#endif /* S_ISLNK */ - -/* - * Makes a filename into result using the following algorithm. - * - make result NULL - * - if file starts with '/', append file to result & set cdpathp to NULL - * - if file starts with ./ or ../ append cwd and file to result - * and set cdpathp to NULL - * - if the first element of cdpathp doesnt start with a '/' xx or '.' xx - * then cwd is appended to result. - * - the first element of cdpathp is appended to result - * - file is appended to result - * - cdpathp is set to the start of the next element in cdpathp (or NULL - * if there are no more elements. - * The return value indicates whether a non-null element from cdpathp - * was appended to result. - */ -int -make_path(cwd, file, cdpathp, xsp, phys_pathp) - const char *cwd; - const char *file; - char **cdpathp; /* & of : separated list */ - XString *xsp; - int *phys_pathp; -{ - int rval = 0; - int use_cdpath = 1; - char *plist; - int len; - int plen = 0; - char *xp = Xstring(*xsp, xp); - - if (!file) - file = null; - - if (!ISRELPATH(file)) { - *phys_pathp = 0; - use_cdpath = 0; - } else { - if (file[0] == '.') { - char c = file[1]; - - if (c == '.') - c = file[2]; - if (ISDIRSEP(c) || c == '\0') - use_cdpath = 0; - } - - plist = *cdpathp; - if (!plist) - use_cdpath = 0; - else if (use_cdpath) { - char *pend; - - for (pend = plist; *pend && *pend != PATHSEP; pend++) - ; - plen = pend - plist; - *cdpathp = *pend ? ++pend : (char *) 0; - } - - if ((use_cdpath == 0 || !plen || ISRELPATH(plist)) - && (cwd && *cwd)) - { - len = strlen(cwd); - XcheckN(*xsp, xp, len); - memcpy(xp, cwd, len); - xp += len; - if (!ISDIRSEP(cwd[len - 1])) - Xput(*xsp, xp, DIRSEP); - } - *phys_pathp = Xlength(*xsp, xp); - if (use_cdpath && plen) { - XcheckN(*xsp, xp, plen); - memcpy(xp, plist, plen); - xp += plen; - if (!ISDIRSEP(plist[plen - 1])) - Xput(*xsp, xp, DIRSEP); - rval = 1; - } - } - - len = strlen(file) + 1; - XcheckN(*xsp, xp, len); - memcpy(xp, file, len); - - if (!use_cdpath) - *cdpathp = (char *) 0; - - return rval; -} - -/* - * Simplify pathnames containing "." and ".." entries. - * ie, simplify_path("/a/b/c/./../d/..") returns "/a/b" - */ -void -simplify_path(pathx) - char *pathx; -{ - char *cur; - char *t; - int isrooted; - char *very_start = pathx; - char *start; - - if (!*pathx) - return; - - if ((isrooted = ISROOTEDPATH(pathx))) - very_start++; -#if defined (OS2) || defined (__CYGWIN__) - if (pathx[0] && pathx[1] == ':') /* skip a: */ - very_start += 2; -#endif /* OS2 || __CYGWIN__ */ - - /* Before After - * /foo/ /foo - * /foo/../../bar /bar - * /foo/./blah/.. /foo - * . . - * .. .. - * ./foo foo - * foo/../../../bar ../../bar - * OS2 and CYGWIN: - * a:/foo/../.. a:/ - * a:. a: - * a:.. a:.. - * a:foo/../../blah a:../blah - */ - -#ifdef __CYGWIN__ - /* preserve leading double-slash on pathnames (for UNC paths) */ - if (pathx[0] && ISDIRSEP(pathx[0]) && pathx[1] && ISDIRSEP(pathx[1])) - very_start++; -#endif /* __CYGWIN__ */ - - for (cur = t = start = very_start; ; ) { - /* treat multiple '/'s as one '/' */ - while (ISDIRSEP(*t)) - t++; - - if (*t == '\0') { - if (cur == pathx) - /* convert empty path to dot */ - *cur++ = '.'; - *cur = '\0'; - break; - } - - if (t[0] == '.') { - if (!t[1] || ISDIRSEP(t[1])) { - t += 1; - continue; - } else if (t[1] == '.' && (!t[2] || ISDIRSEP(t[2]))) { - if (!isrooted && cur == start) { - if (cur != very_start) - *cur++ = DIRSEP; - *cur++ = '.'; - *cur++ = '.'; - start = cur; - } else if (cur != start) - while (--cur > start && !ISDIRSEP(*cur)) - ; - t += 2; - continue; - } - } - - if (cur != very_start) - *cur++ = DIRSEP; - - /* find/copy next component of pathname */ - while (*t && !ISDIRSEP(*t)) - *cur++ = *t++; - } -} - - -void -set_current_wd(pathx) - char *pathx; -{ - int len; - char *p = pathx; - - if (!p && !(p = ksh_get_wd((char *) 0, 0))) - p = null; - - len = strlen(p) + 1; - - if (len > current_wd_size) - current_wd = aresize(current_wd, current_wd_size = len, APERM); - memcpy(current_wd, p, len); - if (p != pathx && p != null) - afree(p, ATEMP); -} - -#ifdef S_ISLNK -char * -get_phys_path(pathx) - const char *pathx; -{ - XString xs; - char *xp; - - Xinit(xs, xp, strlen(pathx) + 1, ATEMP); - - xp = do_phys_path(&xs, xp, pathx); - - if (!xp) - return (char *) 0; - - if (Xlength(xs, xp) == 0) - Xput(xs, xp, DIRSEP); - Xput(xs, xp, '\0'); - - return Xclose(xs, xp); -} - -static char * -do_phys_path(xsp, xp, pathx) - XString *xsp; - char *xp; - const char *pathx; -{ - const char *p, *q; - int len, llen; - int savepos; - char lbuf[PATH]; - - Xcheck(*xsp, xp); - for (p = pathx; p; p = q) { - while (ISDIRSEP(*p)) - p++; - if (!*p) - break; - len = (q = ksh_strchr_dirsep(p)) ? q - p : (int)strlen(p); - if (len == 1 && p[0] == '.') - continue; - if (len == 2 && p[0] == '.' && p[1] == '.') { - while (xp > Xstring(*xsp, xp)) { - xp--; - if (ISDIRSEP(*xp)) - break; - } - continue; - } - - savepos = Xsavepos(*xsp, xp); - Xput(*xsp, xp, DIRSEP); - XcheckN(*xsp, xp, len + 1); - memcpy(xp, p, len); - xp += len; - *xp = '\0'; - - llen = readlink(Xstring(*xsp, xp), lbuf, sizeof(lbuf) - 1); - if (llen < 0) { - /* EINVAL means it wasn't a symlink... */ - if (errno != EINVAL) - return (char *) 0; - continue; - } - lbuf[llen] = '\0'; - - /* If absolute path, start from scratch.. */ - xp = ISABSPATH(lbuf) ? Xstring(*xsp, xp) - : Xrestpos(*xsp, xp, savepos); - if (!(xp = do_phys_path(xsp, xp, lbuf))) - return (char *) 0; - } - return xp; -} -#endif /* S_ISLNK */ - -#ifdef TEST - -main(argc, argv) -{ - int rv; - char *cp, cdpath[256], pwd[256], file[256], result[256]; - - printf("enter CDPATH: "); gets(cdpath); - printf("enter PWD: "); gets(pwd); - while (1) { - if (printf("Enter file: "), gets(file) == 0) - return 0; - cp = cdpath; - do { - rv = make_path(pwd, file, &cp, result, sizeof(result)); - printf("make_path returns (%d), \"%s\" ", rv, result); - simplify_path(result); - printf("(simpifies to \"%s\")\n", result); - } while (cp); - } -} -#endif /* TEST */ diff --git a/bin/ksh/proto.h b/bin/ksh/proto.h deleted file mode 100644 index 3129b7c5a..000000000 --- a/bin/ksh/proto.h +++ /dev/null @@ -1,298 +0,0 @@ -/* $NetBSD: proto.h,v 1.7 2005/06/26 19:09:00 christos Exp $ */ - -/* - * prototypes for PD-KSH - * originally generated using "cproto.c 3.5 92/04/11 19:28:01 cthuang " - * $Id: proto.h,v 1.7 2005/06/26 19:09:00 christos Exp $ - */ - -/* alloc.c */ -Area * ainit ARGS((Area *)); -void afreeall ARGS((Area *)); -void * alloc ARGS((size_t, Area *)); -void * aresize ARGS((void *, size_t, Area *)); -void afree ARGS((void *, Area *)); -/* c_ksh.c */ -int c_hash ARGS((char **)); -int c_cd ARGS((char **)); -int c_pwd ARGS((char **)); -int c_print ARGS((char **)); -int c_whence ARGS((char **)); -int c_command ARGS((char **)); -int c_typeset ARGS((char **)); -int c_alias ARGS((char **)); -int c_unalias ARGS((char **)); -int c_let ARGS((char **)); -int c_jobs ARGS((char **)); -int c_fgbg ARGS((char **)); -int c_kill ARGS((char **)); -void getopts_reset ARGS((int)); -int c_getopts ARGS((char **)); -int c_bind ARGS((char **)); -/* c_sh.c */ -int c_label ARGS((char **)); -int c_shift ARGS((char **)); -int c_umask ARGS((char **)); -int c_dot ARGS((char **)); -int c_wait ARGS((char **)); -int c_read ARGS((char **)); -int c_eval ARGS((char **)); -int c_trap ARGS((char **)); -int c_brkcont ARGS((char **)); -int c_exitreturn ARGS((char **)); -int c_set ARGS((char **)); -int c_unset ARGS((char **)); -int c_ulimit ARGS((char **)); -int c_times ARGS((char **)); -int timex ARGS((struct op *, int)); -void timex_hook ARGS((struct op *, char ** volatile *)); -int c_exec ARGS((char **)); -int c_builtin ARGS((char **)); -/* c_test.c */ -int c_test ARGS((char **)); -/* edit.c: most prototypes in edit.h */ -void x_init ARGS((void)); -int x_read ARGS((char *, size_t)); -void set_editmode ARGS((const char *)); -/* emacs.c: most prototypes in edit.h */ -int x_bind ARGS((const char *, const char *, int, int)); -/* eval.c */ -char * substitute ARGS((const char *, int)); -char ** eval ARGS((char **, int)); -char * evalstr ARGS((char *, int)); -char * evalonestr ARGS((char *, int)); -char *debunk ARGS((char *, const char *, size_t)); -void expand ARGS((char *, XPtrV *, int)); -int glob_str ARGS((char *, XPtrV *, int)); -/* exec.c */ -int fd_clexec ARGS((int)); -int execute ARGS((struct op * volatile, volatile int)); -int shcomexec ARGS((char **)); -struct tbl * findfunc ARGS((const char *, unsigned int, int)); -int define ARGS((const char *, struct op *)); -void builtin ARGS((const char *, int (*)(char **))); -struct tbl * findcom ARGS((const char *, int)); -void flushcom ARGS((int all)); -char * search ARGS((const char *, const char *, int, int *)); -int search_access ARGS((const char *, int, int *)); -int pr_menu ARGS((char *const *)); -int pr_list ARGS((char *const *)); -/* expr.c */ -int evaluate ARGS((const char *, long *, int)); -int v_evaluate ARGS((struct tbl *, const char *, volatile int)); -/* history.c */ -void init_histvec ARGS((void)); -void hist_init ARGS((Source *)); -void hist_finish ARGS((void)); -void histsave ARGS((int, const char *, int)); -#ifdef HISTORY -int c_fc ARGS((char **)); -void sethistsize ARGS((int)); -void sethistfile ARGS((const char *)); -# ifdef EASY_HISTORY -void histappend ARGS((const char *, int)); -# endif -char ** histpos ARGS((void)); -int histN ARGS((void)); -int histnum ARGS((int)); -int findhist ARGS((int, int, const char *, int)); -#endif /* HISTORY */ -/* io.c */ -void errorf ARGS((const char *, ...)) - GCC_FUNC_ATTR2(noreturn, format(printf, 1, 2)); -void warningf ARGS((int, const char *, ...)) - GCC_FUNC_ATTR(format(printf, 2, 3)); -void bi_errorf ARGS((const char *, ...)) - GCC_FUNC_ATTR(format(printf, 1, 2)); -void internal_errorf ARGS((int, const char *, ...)) - GCC_FUNC_ATTR(format(printf, 2, 3)); -void error_prefix ARGS((int)); -void shellf ARGS((const char *, ...)) - GCC_FUNC_ATTR(format(printf, 1, 2)); -void shprintf ARGS((const char *, ...)) - GCC_FUNC_ATTR(format(printf, 1, 2)); -#ifdef KSH_DEBUG -void kshdebug_init_ ARGS((void)); -void kshdebug_printf_ ARGS((const char *, ...)) - GCC_FUNC_ATTR(format(printf, 1, 2)); -void kshdebug_dump_ ARGS((const char *, const void *, int)); -#endif /* KSH_DEBUG */ -int can_seek ARGS((int)); -void initio ARGS((void)); -int ksh_dup2 ARGS((int, int, int)); -int savefd ARGS((int, int)); -void restfd ARGS((int, int)); -void openpipe ARGS((int *)); -void closepipe ARGS((int *)); -int check_fd ARGS((char *, int, const char **)); -#ifdef KSH -void coproc_init ARGS((void)); -void coproc_read_close ARGS((int)); -void coproc_readw_close ARGS((int)); -void coproc_write_close ARGS((int)); -int coproc_getfd ARGS((int, const char **)); -void coproc_cleanup ARGS((int)); -#endif /* KSH */ -struct temp *maketemp ARGS((Area *, Temp_type, struct temp **)); -/* jobs.c */ -void j_init ARGS((int)); -void j_exit ARGS((void)); -void j_change ARGS((void)); -int exchild ARGS((struct op *, int, int)); -void startlast ARGS((void)); -int waitlast ARGS((void)); -int waitfor ARGS((const char *, int *)); -int j_kill ARGS((const char *, int)); -int j_resume ARGS((const char *, int)); -int j_jobs ARGS((const char *, int, int)); -void j_notify ARGS((void)); -pid_t j_async ARGS((void)); -int j_stopped_running ARGS((void)); -/* lex.c */ -int yylex ARGS((int)); -void yyerror ARGS((const char *, ...)) - GCC_FUNC_ATTR2(noreturn, format(printf, 1, 2)); -Source * pushs ARGS((int, Area *)); -void set_prompt ARGS((int, Source *)); -void pprompt ARGS((const char *, int)); -/* mail.c */ -#ifdef KSH -void mcheck ARGS((void)); -void mcset ARGS((long)); -void mbset ARGS((char *)); -void mpset ARGS((char *)); -#endif /* KSH */ -/* main.c */ -int include ARGS((const char *, int, char **, int)); -int command ARGS((const char *)); -int shell ARGS((Source *volatile, int volatile)); -void unwind ARGS((int)) GCC_FUNC_ATTR(noreturn); -void newenv ARGS((int)); -void quitenv ARGS((void)); -void cleanup_parents_env ARGS((void)); -void cleanup_proc_env ARGS((void)); -void aerror ARGS((Area *, const char *)) - GCC_FUNC_ATTR(noreturn); -/* misc.c */ -void setctypes ARGS((const char *, int)); -void initctypes ARGS((void)); -char * ulton ARGS((unsigned long, int)); -char * str_save ARGS((const char *, Area *)); -char * str_nsave ARGS((const char *, int, Area *)); -int option ARGS((const char *)); -char * getoptions ARGS((void)); -void change_flag ARGS((enum sh_flag, int, int)); -int parse_args ARGS((char **v, int what, int *)); -int getn ARGS((const char *, int *)); -int bi_getn ARGS((const char *, int *)); -int gmatch ARGS((const char *, const char *, int)); -int has_globbing ARGS((const char *, const char *)); -const unsigned char *pat_scan ARGS((const unsigned char *, - const unsigned char *, int)); -void qsortp ARGS((void **, size_t, int (*)(void *, void *))); -int xstrcmp ARGS((void *, void *)); -void ksh_getopt_reset ARGS((Getopt *, int)); -int ksh_getopt ARGS((char **, Getopt *, const char *)); -void print_value_quoted ARGS((const char *)); -void print_columns ARGS((struct shf *, int, - char *(*)(void *, int, char *, int), - void *, int, int)); -int strip_nuls ARGS((char *, int)); -char *str_zcpy ARGS((char *, const char *, int)); -int blocking_read ARGS((int, char *, int)); -int reset_nonblock ARGS((int)); -char *ksh_get_wd ARGS((char *, int)); -/* path.c */ -int make_path ARGS((const char *, const char *, - char **, XString *, int *)); -void simplify_path ARGS((char *)); -char *get_phys_path ARGS((const char *)); -void set_current_wd ARGS((char *)); -/* syn.c */ -void initkeywords ARGS((void)); -struct op * compile ARGS((Source *)); -/* table.c */ -unsigned int hash ARGS((const char *)); -void tinit ARGS((struct table *, Area *, int)); -struct tbl * tsearch ARGS((struct table *, const char *, unsigned int)); -struct tbl * tenter ARGS((struct table *, const char *, unsigned int)); -void tdelete ARGS((struct tbl *)); -void twalk ARGS((struct tstate *, struct table *)); -struct tbl * tnext ARGS((struct tstate *)); -struct tbl ** tsort ARGS((struct table *)); -/* trace.c */ -/* trap.c */ -void inittraps ARGS((void)); -#ifdef KSH -void alarm_init ARGS((void)); -#endif /* KSH */ -Trap * gettrap ARGS((const char *, int)); -RETSIGTYPE trapsig ARGS((int)); -void intrcheck ARGS((void)); -int fatal_trap_check ARGS((void)); -int trap_pending ARGS((void)); -void runtraps ARGS((int)); -void runtrap ARGS((Trap *)); -void cleartraps ARGS((void)); -void restoresigs ARGS((void)); -void settrap ARGS((Trap *, char *)); -int block_pipe ARGS((void)); -void restore_pipe ARGS((int)); -int setsig ARGS((Trap *, handler_t, int)); -void setexecsig ARGS((Trap *, int)); -/* tree.c */ -int fptreef ARGS((struct shf *, int, const char *, ...)); -char * snptreef ARGS((char *, int, const char *, ...)); -struct op * tcopy ARGS((struct op *, Area *)); -char * wdcopy ARGS((const char *, Area *)); -char * wdscan ARGS((const char *, int)); -char * wdstrip ARGS((const char *)); -void tfree ARGS((struct op *, Area *)); -/* var.c */ -void newblock ARGS((void)); -void popblock ARGS((void)); -void initvar ARGS((void)); -struct tbl * global ARGS((const char *)); -struct tbl * local ARGS((const char *, bool_t)); -char * str_val ARGS((struct tbl *)); -long intval ARGS((struct tbl *)); -int setstr ARGS((struct tbl *, const char *, int)); -struct tbl *setint_v ARGS((struct tbl *, struct tbl *)); -void setint ARGS((struct tbl *, long)); -int getint ARGS((struct tbl *, long *)); -struct tbl * typeset ARGS((const char *, Tflag, Tflag, int, int)); -void unset ARGS((struct tbl *, int)); -char * skip_varname ARGS((const char *, int)); -char *skip_wdvarname ARGS((const char *, int)); -int is_wdvarname ARGS((const char *, int)); -int is_wdvarassign ARGS((const char *)); -char ** makenv ARGS((void)); -void change_random ARGS((void)); -int array_ref_len ARGS((const char *)); -char * arrayname ARGS((const char *)); -void set_array ARGS((const char *, int, char **)); -/* version.c */ -/* vi.c: see edit.h */ - - -/* Hack to avoid billions of compile warnings on SunOS 4.1.x */ -#if defined(MUN) && defined(sun) && !defined(__svr4__) -extern void bcopy ARGS((const void *, void *, size_t)); -extern intclose ARGS((FILE *)); -extern intprintf ARGS((FILE *, const char *, ...)); -extern intread ARGS((void *, int, int, FILE *)); -extern int ioctl ARGS((int, int, void *)); -extern int killpg ARGS((int, int)); -extern int nice ARGS((int)); -extern int readlink ARGS((const char *, char *, int)); -extern int setpgrp ARGS((int, int)); -extern int strcasecmp ARGS((const char *, const char *)); -extern int tolower ARGS((int)); -extern int toupper ARGS((int)); -/* Include files aren't included yet */ -extern int getrlimit ARGS(( /* int, struct rlimit * */ )); -extern int getrusage ARGS(( /* int, struct rusage * */ )); -extern int gettimeofday ARGS(( /* struct timeval *, struct timezone * */ )); -extern int setrlimit ARGS(( /* int, struct rlimit * */ )); -extern int lstat ARGS(( /* const char *, struct stat * */ )); -#endif diff --git a/bin/ksh/sh.h b/bin/ksh/sh.h deleted file mode 100644 index 83c3f70c0..000000000 --- a/bin/ksh/sh.h +++ /dev/null @@ -1,735 +0,0 @@ -/* $NetBSD: sh.h,v 1.7 2005/06/26 19:09:00 christos Exp $ */ - -/* - * Public Domain Bourne/Korn shell - */ - -/* $Id: sh.h,v 1.7 2005/06/26 19:09:00 christos Exp $ */ - -#include "config.h" /* system and option configuration info */ - -#ifdef HAVE_PROTOTYPES -# define ARGS(args) args /* prototype declaration */ -#else -# define ARGS(args) () /* K&R declaration */ -#endif - -/* Start of common headers */ - -#include -#include -#include -#ifdef HAVE_STDDEF_H -# include -#endif - -#ifdef HAVE_STDLIB_H -# include -#else -/* just a useful subset of what stdlib.h would have */ -extern char * getenv ARGS((const char *)); -extern void * malloc ARGS((size_t)); -extern void * realloc ARGS((void *, size_t)); -extern int free ARGS((void *)); -extern int exit ARGS((int)); -extern int rand ARGS((void)); -extern void srand ARGS((unsigned int)); -extern int atoi ARGS((const char *)); -#endif /* HAVE_STDLIB_H */ - -#ifdef HAVE_UNISTD_H -# include -#else -/* just a useful subset of what unistd.h would have */ -extern int access ARGS((const char *, int)); -extern int open ARGS((const char *, int, ...)); -extern int creat ARGS((const char *, mode_t)); -extern int read ARGS((int, char *, unsigned)); -extern int write ARGS((int, const char *, unsigned)); -extern off_t lseek ARGS((int, off_t, int)); -extern int close ARGS((int)); -extern int pipe ARGS((int [])); -extern int dup2 ARGS((int, int)); -extern int unlink ARGS((const char *)); -extern int fork ARGS((void)); -extern int execve ARGS((const char *, char * const[], char * const[])); -extern int chdir ARGS((const char *)); -extern int kill ARGS((pid_t, int)); -extern char *getcwd(); /* no ARGS here - differs on different machines */ -extern int geteuid ARGS((void)); -extern int readlink ARGS((const char *, char *, int)); -extern int getegid ARGS((void)); -extern int getpid ARGS((void)); -extern int getppid ARGS((void)); -extern unsigned int sleep ARGS((unsigned int)); -extern int isatty ARGS((int)); -# ifdef POSIX_PGRP -extern int getpgrp ARGS((void)); -extern int setpgid ARGS((pid_t, pid_t)); -# endif /* POSIX_PGRP */ -# ifdef BSD_PGRP -extern int getpgrp ARGS((pid_t)); -extern int setpgrp ARGS((pid_t, pid_t)); -# endif /* BSD_PGRP */ -# ifdef SYSV_PGRP -extern int getpgrp ARGS((void)); -extern int setpgrp ARGS((void)); -# endif /* SYSV_PGRP */ -#endif /* HAVE_UNISTD_H */ - -#ifdef HAVE_STRING_H -# include -#else -# include -# define strchr index -# define strrchr rindex -#endif /* HAVE_STRING_H */ -#ifndef HAVE_STRSTR -char *strstr ARGS((const char *s, const char *p)); -#endif /* HAVE_STRSTR */ -#ifndef HAVE_STRCASECMP -int strcasecmp ARGS((const char *s1, const char *s2)); -int strncasecmp ARGS((const char *s1, const char *s2, int n)); -#endif /* HAVE_STRCASECMP */ - -#ifdef HAVE_MEMORY_H -# include -#endif -#ifndef HAVE_MEMSET -# define memcpy(d, s, n) bcopy(s, d, n) -# define memcmp(s1, s2, n) bcmp(s1, s2, n) -void *memset ARGS((void *d, int c, size_t n)); -#endif /* HAVE_MEMSET */ -#ifndef HAVE_MEMMOVE -# ifdef HAVE_BCOPY -# define memmove(d, s, n) bcopy(s, d, n) -# else -void *memmove ARGS((void *d, const void *s, size_t n)); -# endif -#endif /* HAVE_MEMMOVE */ - -#ifdef HAVE_PROTOTYPES -# include -# define SH_VA_START(va, argn) va_start(va, argn) -#else -# include -# define SH_VA_START(va, argn) va_start(va) -#endif /* HAVE_PROTOTYPES */ - -#include - -#ifdef HAVE_FCNTL_H -# include -#else -# include -#endif /* HAVE_FCNTL_H */ -#ifndef O_ACCMODE -# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) -#endif /* !O_ACCMODE */ - -#ifndef F_OK /* access() arguments */ -# define F_OK 0 -# define X_OK 1 -# define W_OK 2 -# define R_OK 4 -#endif /* !F_OK */ - -#ifndef SEEK_SET -# ifdef L_SET -# define SEEK_SET L_SET -# define SEEK_CUR L_INCR -# define SEEK_END L_XTND -# else /* L_SET */ -# define SEEK_SET 0 -# define SEEK_CUR 1 -# define SEEK_END 2 -# endif /* L_SET */ -#endif /* !SEEK_SET */ - -/* Some machines (eg, FreeBSD 1.1.5) define CLK_TCK in limits.h - * (ksh_limval.h assumes limits has been included, if available) - */ -#ifdef HAVE_LIMITS_H -# include -#endif /* HAVE_LIMITS_H */ - -#include -#ifdef NSIG -# define SIGNALS NSIG -#else -# ifdef _MINIX -# define SIGNALS (_NSIG+1) /* _NSIG is # of signals used, excluding 0. */ -# else -# ifdef _SIGMAX /* QNX */ -# define SIGNALS _SIGMAX -# else /* _SIGMAX */ -# define SIGNALS 32 -# endif /* _SIGMAX */ -# endif /* _MINIX */ -#endif /* NSIG */ -#ifndef SIGCHLD -# define SIGCHLD SIGCLD -#endif -/* struct sigaction.sa_flags is set to KSH_SA_FLAGS. Used to ensure - * system calls are interrupted - */ -#ifdef SA_INTERRUPT -# define KSH_SA_FLAGS SA_INTERRUPT -#else /* SA_INTERRUPT */ -# define KSH_SA_FLAGS 0 -#endif /* SA_INTERRUPT */ - -typedef RETSIGTYPE (*handler_t) ARGS((int)); /* signal handler */ - -#ifdef USE_FAKE_SIGACT -# include "sigact.h" /* use sjg's fake sigaction() */ -#endif - -#ifdef HAVE_PATHS_H -# include -#endif /* HAVE_PATHS_H */ -#ifdef _PATH_DEFPATH -# define DEFAULT__PATH _PATH_DEFPATH -#else /* _PATH_DEFPATH */ -# define DEFAULT__PATH DEFAULT_PATH -#endif /* _PATH_DEFPATH */ - -#ifndef offsetof -# define offsetof(type,id) ((size_t)&((type*)NULL)->id) -#endif - -#ifndef HAVE_KILLPG -# define killpg(p, s) kill(-(p), (s)) -#endif /* !HAVE_KILLPG */ - -/* Special cases for execve(2) */ -#ifdef OS2 -extern int ksh_execve(char *cmd, char **args, char **env, int flags); -#else /* OS2 */ -# if defined(OS_ISC) && defined(_POSIX_SOURCE) -/* Kludge for ISC 3.2 (and other versions?) so programs will run correctly. */ -# define ksh_execve(p, av, ev, flags) \ - do { \ - __setostype(0); \ - execve(p, av, ev); \ - __setostype(1); \ - } while (0) -# else /* OS_ISC && _POSIX */ -# define ksh_execve(p, av, ev, flags) execve(p, av, ev) -# endif /* OS_ISC && _POSIX */ -#endif /* OS2 */ - -/* this is a hang-over from older versions of the os2 port */ -#define ksh_dupbase(fd, base) fcntl(fd, F_DUPFD, base) - -#ifdef HAVE_SIGSETJMP -# define ksh_sigsetjmp(env,sm) sigsetjmp((env), (sm)) -# define ksh_siglongjmp(env,v) siglongjmp((env), (v)) -# define ksh_jmp_buf sigjmp_buf -#else /* HAVE_SIGSETJMP */ -# ifdef HAVE__SETJMP -# define ksh_sigsetjmp(env,sm) _setjmp(env) -# define ksh_siglongjmp(env,v) _longjmp((env), (v)) -# else /* HAVE__SETJMP */ -# define ksh_sigsetjmp(env,sm) setjmp(env) -# define ksh_siglongjmp(env,v) longjmp((env), (v)) -# endif /* HAVE__SETJMP */ -# define ksh_jmp_buf jmp_buf -#endif /* HAVE_SIGSETJMP */ - -#ifndef HAVE_DUP2 -extern int dup2 ARGS((int, int)); -#endif /* !HAVE_DUP2 */ - -/* Find a integer type that is at least 32 bits (or die) - SIZEOF_* defined - * by autoconf (assumes an 8 bit byte, but I'm not concerned). - * NOTE: INT32 may end up being more than 32 bits. - */ -#if SIZEOF_INT >= 4 -# define INT32 int -#else /* SIZEOF_INT */ -# if SIZEOF_LONG >= 4 -# define INT32 long -# else /* SIZEOF_LONG */ - #error cannot find 32 bit type... -# endif /* SIZEOF_LONG */ -#endif /* SIZEOF_INT */ - -/* end of common headers */ - -/* Stop gcc and lint from complaining about possibly uninitialized variables */ -#if defined(__GNUC__) || defined(lint) -# define UNINITIALIZED(var) var = 0 -#else -# define UNINITIALIZED(var) var -#endif /* GNUC || lint */ - -/* some useful #defines */ -#ifdef EXTERN -# define I__(i) = i -#else -# define I__(i) -# define EXTERN extern -# define EXTERN_DEFINED -#endif - -#ifdef OS2 -# define inDOS() (!(_emx_env & 0x200)) -#endif - -#ifndef EXECSHELL -/* shell to exec scripts (see also $SHELL initialization in main.c) */ -# ifdef OS2 -# define EXECSHELL (inDOS() ? "c:\\command.com" : "c:\\os2\\cmd.exe") -# define EXECSHELL_STR (inDOS() ? "COMSPEC" : "OS2_SHELL") -# else /* OS2 */ -# define EXECSHELL "/bin/sh" -# define EXECSHELL_STR "EXECSHELL" -# endif /* OS2 */ -#endif - -/* ISABSPATH() means path is fully and completely specified, - * ISROOTEDPATH() means a .. as the first component is a no-op, - * ISRELPATH() means $PWD can be tacked on to get an absolute path. - * - * OS Path ISABSPATH ISROOTEDPATH ISRELPATH - * unix /foo yes yes no - * unix foo no no yes - * unix ../foo no no yes - * os2+cyg a:/foo yes yes no - * os2+cyg a:foo no no no - * os2+cyg /foo no yes no - * os2+cyg foo no no yes - * os2+cyg ../foo no no yes - * cyg //foo yes yes no - */ -#ifdef OS2 -# define PATHSEP ';' -# define DIRSEP '/' /* even though \ is native */ -# define DIRSEPSTR "\\" -# define ISDIRSEP(c) ((c) == '\\' || (c) == '/') -# define ISABSPATH(s) (((s)[0] && (s)[1] == ':' && ISDIRSEP((s)[2]))) -# define ISROOTEDPATH(s) (ISDIRSEP((s)[0]) || ISABSPATH(s)) -# define ISRELPATH(s) (!(s)[0] || ((s)[1] != ':' && !ISDIRSEP((s)[0]))) -# define FILECHCONV(c) (isascii(c) && isupper(c) ? tolower(c) : c) -# define FILECMP(s1, s2) stricmp(s1, s2) -# define FILENCMP(s1, s2, n) strnicmp(s1, s2, n) -extern char *ksh_strchr_dirsep(const char *path); -extern char *ksh_strrchr_dirsep(const char *path); -# define chdir _chdir2 -# define getcwd _getcwd2 -#else -# define PATHSEP ':' -# define DIRSEP '/' -# define DIRSEPSTR "/" -# define ISDIRSEP(c) ((c) == '/') -#ifdef __CYGWIN__ -# define ISABSPATH(s) \ - (((s)[0] && (s)[1] == ':' && ISDIRSEP((s)[2])) || ISDIRSEP((s)[0])) -# define ISRELPATH(s) (!(s)[0] || ((s)[1] != ':' && !ISDIRSEP((s)[0]))) -#else /* __CYGWIN__ */ -# define ISABSPATH(s) ISDIRSEP((s)[0]) -# define ISRELPATH(s) (!ISABSPATH(s)) -#endif /* __CYGWIN__ */ -# define ISROOTEDPATH(s) ISABSPATH(s) -# define FILECHCONV(c) c -# define FILECMP(s1, s2) strcmp(s1, s2) -# define FILENCMP(s1, s2, n) strncmp(s1, s2, n) -# define ksh_strchr_dirsep(p) strchr(p, DIRSEP) -# define ksh_strrchr_dirsep(p) strrchr(p, DIRSEP) -#endif - -typedef int bool_t; -#define FALSE 0 -#define TRUE 1 - -#define NELEM(a) (sizeof(a) / sizeof((a)[0])) -#define sizeofN(type, n) (sizeof(type) * (n)) -#define BIT(i) (1<<(i)) /* define bit in flag */ - -/* Table flag type - needs > 16 and < 32 bits */ -typedef INT32 Tflag; - -#define NUFILE 32 /* Number of user-accessible files */ -#define FDBASE 10 /* First file usable by Shell */ - -/* you're not going to run setuid shell scripts, are you? */ -#define eaccess(path, mode) access(path, mode) - -/* Make MAGIC a char that might be printed to make bugs more obvious, but - * not a char that is used often. Also, can't use the high bit as it causes - * portability problems (calling strchr(x, 0x80|'x') is error prone). - */ -#define MAGIC (7) /* prefix for *?[!{,} during expand */ -#define ISMAGIC(c) ((unsigned char)(c) == MAGIC) -#define NOT '!' /* might use ^ (ie, [!...] vs [^..]) */ - -#define LINE 1024 /* input line size */ -#define PATH 1024 /* pathname size (todo: PATH_MAX/pathconf()) */ -#define ARRAYMAX 1023 /* max array index */ - -EXTERN const char *kshname; /* $0 */ -EXTERN pid_t kshpid; /* $$, shell pid */ -EXTERN pid_t procpid; /* pid of executing process */ -EXTERN uid_t ksheuid; /* effective uid of shell */ -EXTERN int exstat; /* exit status */ -EXTERN int subst_exstat; /* exit status of last $(..)/`..` */ -EXTERN const char *safe_prompt; /* safe prompt if PS1 substitution fails */ - -/* - * Area-based allocation built on malloc/free - */ -typedef struct Area { - struct link *freelist; /* free list */ -} Area; - -EXTERN Area aperm; /* permanent object space */ -#define APERM &aperm -#define ATEMP &e->area - -#ifdef MEM_DEBUG -# include "chmem.h" /* a debugging front end for malloc et. al. */ -#endif /* MEM_DEBUG */ - -#ifdef KSH_DEBUG -# define kshdebug_init() kshdebug_init_() -# define kshdebug_printf(a) kshdebug_printf_ a -# define kshdebug_dump(a) kshdebug_dump_ a -#else /* KSH_DEBUG */ -# define kshdebug_init() -# define kshdebug_printf(a) -# define kshdebug_dump(a) -#endif /* KSH_DEBUG */ - -/* - * parsing & execution environment - */ -EXTERN struct env { - short type; /* environment type - see below */ - short flags; /* EF_* */ - Area area; /* temporary allocation area */ - struct block *loc; /* local variables and functions */ - short *savefd; /* original redirected fd's */ - struct env *oenv; /* link to previous environment */ - ksh_jmp_buf jbuf; /* long jump back to env creator */ - struct temp *temps; /* temp files */ -} *e; - -/* struct env.type values */ -#define E_NONE 0 /* dummy environment */ -#define E_PARSE 1 /* parsing command # */ -#define E_FUNC 2 /* executing function # */ -#define E_INCL 3 /* including a file via . # */ -#define E_EXEC 4 /* executing command tree */ -#define E_LOOP 5 /* executing for/while # */ -#define E_ERRH 6 /* general error handler # */ -/* # indicates env has valid jbuf (see unwind()) */ - -/* struct env.flag values */ -#define EF_FUNC_PARSE BIT(0) /* function being parsed */ -#define EF_BRKCONT_PASS BIT(1) /* set if E_LOOP must pass break/continue on */ -#define EF_FAKE_SIGDIE BIT(2) /* hack to get info from unwind to quitenv */ - -/* Do breaks/continues stop at env type e? */ -#define STOP_BRKCONT(t) ((t) == E_NONE || (t) == E_PARSE \ - || (t) == E_FUNC || (t) == E_INCL) -/* Do returns stop at env type e? */ -#define STOP_RETURN(t) ((t) == E_FUNC || (t) == E_INCL) - -/* values for ksh_siglongjmp(e->jbuf, 0) */ -#define LRETURN 1 /* return statement */ -#define LEXIT 2 /* exit statement */ -#define LERROR 3 /* errorf() called */ -#define LLEAVE 4 /* untrappable exit/error */ -#define LINTR 5 /* ^C noticed */ -#define LBREAK 6 /* break statement */ -#define LCONTIN 7 /* continue statement */ -#define LSHELL 8 /* return to interactive shell() */ -#define LAEXPR 9 /* error in arithmetic expression */ - -/* option processing */ -#define OF_CMDLINE 0x01 /* command line */ -#define OF_SET 0x02 /* set builtin */ -#define OF_SPECIAL 0x04 /* a special variable changing */ -#define OF_INTERNAL 0x08 /* set internally by shell */ -#define OF_ANY (OF_CMDLINE | OF_SET | OF_SPECIAL | OF_INTERNAL) - -struct option { - const char *name; /* long name of option */ - char c; /* character flag (if any) */ - short flags; /* OF_* */ -}; -extern const struct option goptions[]; - -/* - * flags (the order of these enums MUST match the order in misc.c(options[])) - */ -enum sh_flag { - FEXPORT = 0, /* -a: export all */ -#ifdef BRACE_EXPAND - FBRACEEXPAND, /* enable {} globbing */ -#endif - FBGNICE, /* bgnice */ - FCOMMAND, /* -c: (invocation) execute specified command */ -#ifdef EMACS - FEMACS, /* emacs command editing */ - FEMACSUSEMETA, /* use 8th bit as meta */ -#endif - FERREXIT, /* -e: quit on error */ -#ifdef EMACS - FGMACS, /* gmacs command editing */ -#endif - FIGNOREEOF, /* eof does not exit */ - FTALKING, /* -i: interactive */ - FKEYWORD, /* -k: name=value anywhere */ - FLOGIN, /* -l: a login shell */ - FMARKDIRS, /* mark dirs with / in file name completion */ - FMONITOR, /* -m: job control monitoring */ - FNOCLOBBER, /* -C: don't overwrite existing files */ - FNOEXEC, /* -n: don't execute any commands */ - FNOGLOB, /* -f: don't do file globbing */ - FNOHUP, /* -H: don't kill running jobs when login shell exits */ - FNOLOG, /* don't save functions in history (ignored) */ -#ifdef JOBS - FNOTIFY, /* -b: asynchronous job completion notification */ -#endif - FNOUNSET, /* -u: using an unset var is an error */ - FPHYSICAL, /* -o physical: don't do logical cd's/pwd's */ - FPOSIX, /* -o posix: be posixly correct */ - FPRIVILEGED, /* -p: use suid_profile */ - FRESTRICTED, /* -r: restricted shell */ - FSTDIN, /* -s: (invocation) parse stdin */ - FTRACKALL, /* -h: create tracked aliases for all commands */ - FVERBOSE, /* -v: echo input */ -#ifdef VI - FVI, /* vi command editing */ - FVIRAW, /* always read in raw mode (ignored) */ - FVISHOW8, /* display chars with 8th bit set as is (versus M-) */ - FVITABCOMPLETE, /* enable tab as file name completion char */ - FVIESCCOMPLETE, /* enable ESC as file name completion in command mode */ -#endif - FXTRACE, /* -x: execution trace */ - FTALKING_I, /* (internal): initial shell was interactive */ - FNFLAGS /* (place holder: how many flags are there) */ -}; - -#define Flag(f) (shell_flags[(int) (f)]) - -EXTERN char shell_flags [FNFLAGS]; - -EXTERN char null [] I__(""); /* null value for variable */ -EXTERN char space [] I__(" "); -EXTERN char newline [] I__("\n"); -EXTERN char slash [] I__("/"); - -enum temp_type { - TT_HEREDOC_EXP, /* expanded heredoc */ - TT_HIST_EDIT /* temp file used for history editing (fc -e) */ -}; -typedef enum temp_type Temp_type; -/* temp/heredoc files. The file is removed when the struct is freed. */ -struct temp { - struct temp *next; - struct shf *shf; - int pid; /* pid of process parsed here-doc */ - Temp_type type; - char *name; -}; - -/* - * stdio and our IO routines - */ - -#define shl_spare (&shf_iob[0]) /* for c_read()/c_print() */ -#define shl_stdout (&shf_iob[1]) -#define shl_out (&shf_iob[2]) -EXTERN int shl_stdout_ok; - -/* - * trap handlers - */ -typedef struct trap { - int signal; /* signal number */ - const char *name; /* short name */ - const char *mess; /* descriptive name */ - char *trap; /* trap command */ - int volatile set; /* trap pending */ - int flags; /* TF_* */ - handler_t cursig; /* current handler (valid if TF_ORIG_* set) */ - handler_t shtrap; /* shell signal handler */ -} Trap; - -/* values for Trap.flags */ -#define TF_SHELL_USES BIT(0) /* shell uses signal, user can't change */ -#define TF_USER_SET BIT(1) /* user has (tried to) set trap */ -#define TF_ORIG_IGN BIT(2) /* original action was SIG_IGN */ -#define TF_ORIG_DFL BIT(3) /* original action was SIG_DFL */ -#define TF_EXEC_IGN BIT(4) /* restore SIG_IGN just before exec */ -#define TF_EXEC_DFL BIT(5) /* restore SIG_DFL just before exec */ -#define TF_DFL_INTR BIT(6) /* when received, default action is LINTR */ -#define TF_TTY_INTR BIT(7) /* tty generated signal (see j_waitj) */ -#define TF_CHANGED BIT(8) /* used by runtrap() to detect trap changes */ -#define TF_FATAL BIT(9) /* causes termination if not trapped */ - -/* values for setsig()/setexecsig() flags argument */ -#define SS_RESTORE_MASK 0x3 /* how to restore a signal before an exec() */ -#define SS_RESTORE_CURR 0 /* leave current handler in place */ -#define SS_RESTORE_ORIG 1 /* restore original handler */ -#define SS_RESTORE_DFL 2 /* restore to SIG_DFL */ -#define SS_RESTORE_IGN 3 /* restore to SIG_IGN */ -#define SS_FORCE BIT(3) /* set signal even if original signal ignored */ -#define SS_USER BIT(4) /* user is doing the set (ie, trap command) */ -#define SS_SHTRAP BIT(5) /* trap for internal use (CHLD,ALRM,WINCH) */ - -#define SIGEXIT_ 0 /* for trap EXIT */ -#define SIGERR_ SIGNALS /* for trap ERR */ - -EXTERN int volatile trap; /* traps pending? */ -EXTERN int volatile intrsig; /* pending trap interrupts executing command */ -EXTERN int volatile fatal_trap;/* received a fatal signal */ -#ifndef FROM_TRAP_C -/* Kludge to avoid bogus re-declaration of sigtraps[] error on AIX 3.2.5 */ -extern Trap sigtraps[SIGNALS+1]; -#endif /* !FROM_TRAP_C */ - -#ifdef KSH -/* - * TMOUT support - */ -/* values for ksh_tmout_state */ -enum tmout_enum { - TMOUT_EXECUTING = 0, /* executing commands */ - TMOUT_READING, /* waiting for input */ - TMOUT_LEAVING /* have timed out */ - }; -EXTERN unsigned int ksh_tmout; -EXTERN enum tmout_enum ksh_tmout_state I__(TMOUT_EXECUTING); -#endif /* KSH */ - -/* For "You have stopped jobs" message */ -EXTERN int really_exit; - -/* - * fast character classes - */ -#define C_ALPHA BIT(0) /* a-z_A-Z */ -#define C_DIGIT BIT(1) /* 0-9 */ -#define C_LEX1 BIT(2) /* \0 \t\n|&;<>() */ -#define C_VAR1 BIT(3) /* *@#!$-? */ -#define C_IFSWS BIT(4) /* \t \n (IFS white space) */ -#define C_SUBOP1 BIT(5) /* "=-+?" */ -#define C_SUBOP2 BIT(6) /* "#%" */ -#define C_IFS BIT(7) /* $IFS */ -#define C_QUOTE BIT(8) /* \n\t"#$&'()*;<>?[\`| (needing quoting) */ - -extern short ctypes []; - -#define ctype(c, t) !!(ctypes[(unsigned char)(c)]&(t)) -#define letter(c) ctype(c, C_ALPHA) -#define digit(c) ctype(c, C_DIGIT) -#define letnum(c) ctype(c, C_ALPHA|C_DIGIT) - -EXTERN int ifs0 I__(' '); /* for "$*" */ - -/* Argument parsing for built-in commands and getopts command */ - -/* Values for Getopt.flags */ -#define GF_ERROR BIT(0) /* call errorf() if there is an error */ -#define GF_PLUSOPT BIT(1) /* allow +c as an option */ -#define GF_NONAME BIT(2) /* don't print argv[0] in errors */ - -/* Values for Getopt.info */ -#define GI_MINUS BIT(0) /* an option started with -... */ -#define GI_PLUS BIT(1) /* an option started with +... */ -#define GI_MINUSMINUS BIT(2) /* arguments were ended with -- */ - -typedef struct { - int optind; - int uoptind;/* what user sees in $OPTIND */ - char *optarg; - int flags; /* see GF_* */ - int info; /* see GI_* */ - unsigned int p; /* 0 or index into argv[optind - 1] */ - char buf[2]; /* for bad option OPTARG value */ -} Getopt; - -EXTERN Getopt builtin_opt; /* for shell builtin commands */ -EXTERN Getopt user_opt; /* parsing state for getopts builtin command */ - -#ifdef KSH -/* This for co-processes */ - -typedef INT32 Coproc_id; /* something that won't (realisticly) wrap */ -struct coproc { - int read; /* pipe from co-process's stdout */ - int readw; /* other side of read (saved temporarily) */ - int write; /* pipe to co-process's stdin */ - Coproc_id id; /* id of current output pipe */ - int njobs; /* number of live jobs using output pipe */ - void *job; /* 0 or job of co-process using input pipe */ -}; -EXTERN struct coproc coproc; -#endif /* KSH */ - -/* Used in jobs.c and by coprocess stuff in exec.c */ -#ifdef JOB_SIGS -EXTERN sigset_t sm_default, sm_sigchld; -#endif /* JOB_SIGS */ - -extern char ksh_version[]; - -/* name of called builtin function (used by error functions) */ -EXTERN char *builtin_argv0; -EXTERN Tflag builtin_flag; /* flags of called builtin (SPEC_BI, etc.) */ - -/* current working directory, and size of memory allocated for same */ -EXTERN char *current_wd; -EXTERN int current_wd_size; - -#ifdef EDIT -/* Minimum required space to work with on a line - if the prompt leaves less - * space than this on a line, the prompt is truncated. - */ -# define MIN_EDIT_SPACE 7 -/* Minimum allowed value for x_cols: 2 for prompt, 3 for " < " at end of line - */ -# define MIN_COLS (2 + MIN_EDIT_SPACE + 3) -EXTERN int x_cols I__(80); /* tty columns */ -#else -# define x_cols 80 /* for pr_menu(exec.c) */ -#endif - -/* These to avoid bracket matching problems */ -#define OPAREN '(' -#define CPAREN ')' -#define OBRACK '[' -#define CBRACK ']' -#define OBRACE '{' -#define CBRACE '}' - -/* Determine the location of the system (common) profile */ -#ifndef KSH_SYSTEM_PROFILE -# ifdef __NeXT -# define KSH_SYSTEM_PROFILE "/etc/profile.std" -# else /* __NeXT */ -# define KSH_SYSTEM_PROFILE "/etc/profile" -# endif /* __NeXT */ -#endif /* KSH_SYSTEM_PROFILE */ - -/* Used by v_evaluate() and setstr() to control action when error occurs */ -#define KSH_UNWIND_ERROR 0 /* unwind the stack (longjmp) */ -#define KSH_RETURN_ERROR 1 /* return 1/0 for success/failure */ - -#include "shf.h" -#include "table.h" -#include "tree.h" -#include "expand.h" -#include "lex.h" -#include "proto.h" - -/* be sure not to interfere with anyone else's idea about EXTERN */ -#ifdef EXTERN_DEFINED -# undef EXTERN_DEFINED -# undef EXTERN -#endif -#undef I__ diff --git a/bin/ksh/shf.c b/bin/ksh/shf.c deleted file mode 100644 index 9913b5a68..000000000 --- a/bin/ksh/shf.c +++ /dev/null @@ -1,1302 +0,0 @@ -/* $NetBSD: shf.c,v 1.7 2005/06/26 19:09:00 christos Exp $ */ - -/* - * Shell file I/O routines - */ -#include - -#ifndef lint -__RCSID("$NetBSD: shf.c,v 1.7 2005/06/26 19:09:00 christos Exp $"); -#endif - - -#include "sh.h" -#include "ksh_stat.h" -#include "ksh_limval.h" - - -/* flags to shf_emptybuf() */ -#define EB_READSW 0x01 /* about to switch to reading */ -#define EB_GROW 0x02 /* grow buffer if necessary (STRING+DYNAMIC) */ - -/* - * Replacement stdio routines. Stdio is too flakey on too many machines - * to be useful when you have multiple processes using the same underlying - * file descriptors. - */ - -static int shf_fillbuf ARGS((struct shf *shf)); -static int shf_emptybuf ARGS((struct shf *shf, int flags)); - -/* Open a file. First three args are for open(), last arg is flags for - * this package. Returns NULL if file could not be opened, or if a dup - * fails. - */ -struct shf * -shf_open(name, oflags, mode, sflags) - const char *name; - int oflags; - int mode; - int sflags; -{ - struct shf *shf; - int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE; - int fd; - - /* Done before open so if alloca fails, fd won't be lost. */ - shf = (struct shf *) alloc(sizeof(struct shf) + bsize, ATEMP); - shf->areap = ATEMP; - shf->buf = (unsigned char *) &shf[1]; - shf->bsize = bsize; - shf->flags = SHF_ALLOCS; - /* Rest filled in by reopen. */ - - fd = open(name, oflags, mode); - if (fd < 0) { - afree(shf, shf->areap); - return NULL; - } - if ((sflags & SHF_MAPHI) && fd < FDBASE) { - int nfd; - - nfd = ksh_dupbase(fd, FDBASE); - close(fd); - if (nfd < 0) { - afree(shf, shf->areap); - return NULL; - } - fd = nfd; - } - sflags &= ~SHF_ACCMODE; - sflags |= (oflags & O_ACCMODE) == O_RDONLY ? SHF_RD - : ((oflags & O_ACCMODE) == O_WRONLY ? SHF_WR - : SHF_RDWR); - - return shf_reopen(fd, sflags, shf); -} - -/* Set up the shf structure for a file descriptor. Doesn't fail. */ -struct shf * -shf_fdopen(fd, sflags, shf) - int fd; - int sflags; - struct shf *shf; -{ - int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE; - - /* use fcntl() to figure out correct read/write flags */ - if (sflags & SHF_GETFL) { - int flags = fcntl(fd, F_GETFL, 0); - - if (flags < 0) - /* will get an error on first read/write */ - sflags |= SHF_RDWR; - else - switch (flags & O_ACCMODE) { - case O_RDONLY: sflags |= SHF_RD; break; - case O_WRONLY: sflags |= SHF_WR; break; - case O_RDWR: sflags |= SHF_RDWR; break; - } - } - - if (!(sflags & (SHF_RD | SHF_WR))) - internal_errorf(1, "shf_fdopen: missing read/write"); - - if (shf) { - if (bsize) { - shf->buf = (unsigned char *) alloc(bsize, ATEMP); - sflags |= SHF_ALLOCB; - } else - shf->buf = (unsigned char *) 0; - } else { - shf = (struct shf *) alloc(sizeof(struct shf) + bsize, ATEMP); - shf->buf = (unsigned char *) &shf[1]; - sflags |= SHF_ALLOCS; - } - shf->areap = ATEMP; - shf->fd = fd; - shf->rp = shf->wp = shf->buf; - shf->rnleft = 0; - shf->rbsize = bsize; - shf->wnleft = 0; /* force call to shf_emptybuf() */ - shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize; - shf->flags = sflags; - shf->errno_ = 0; - shf->bsize = bsize; - if (sflags & SHF_CLEXEC) - fd_clexec(fd); - return shf; -} - -/* Set up an existing shf (and buffer) to use the given fd */ -struct shf * -shf_reopen(fd, sflags, shf) - int fd; - int sflags; - struct shf *shf; -{ - int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE; - - /* use fcntl() to figure out correct read/write flags */ - if (sflags & SHF_GETFL) { - int flags = fcntl(fd, F_GETFL, 0); - - if (flags < 0) - /* will get an error on first read/write */ - sflags |= SHF_RDWR; - else - switch (flags & O_ACCMODE) { - case O_RDONLY: sflags |= SHF_RD; break; - case O_WRONLY: sflags |= SHF_WR; break; - case O_RDWR: sflags |= SHF_RDWR; break; - } - } - - if (!(sflags & (SHF_RD | SHF_WR))) - internal_errorf(1, "shf_reopen: missing read/write"); - if (!shf || !shf->buf || shf->bsize < bsize) - internal_errorf(1, "shf_reopen: bad shf/buf/bsize"); - - /* assumes shf->buf and shf->bsize already set up */ - shf->fd = fd; - shf->rp = shf->wp = shf->buf; - shf->rnleft = 0; - shf->rbsize = bsize; - shf->wnleft = 0; /* force call to shf_emptybuf() */ - shf->wbsize = sflags & SHF_UNBUF ? 0 : bsize; - shf->flags = (shf->flags & (SHF_ALLOCS | SHF_ALLOCB)) | sflags; - shf->errno_ = 0; - if (sflags & SHF_CLEXEC) - fd_clexec(fd); - return shf; -} - -/* Open a string for reading or writing. If reading, bsize is the number - * of bytes that can be read. If writing, bsize is the maximum number of - * bytes that can be written. If shf is not null, it is filled in and - * returned, if it is null, shf is allocated. If writing and buf is null - * and SHF_DYNAMIC is set, the buffer is allocated (if bsize > 0, it is - * used for the initial size). Doesn't fail. - * When writing, a byte is reserved for a trailing null - see shf_sclose(). - */ -struct shf * -shf_sopen(buf, bsize, sflags, shf) - char *buf; - int bsize; - int sflags; - struct shf *shf; -{ - /* can't have a read+write string */ - if (!(sflags & (SHF_RD | SHF_WR)) - || (sflags & (SHF_RD | SHF_WR)) == (SHF_RD | SHF_WR)) - internal_errorf(1, "shf_sopen: flags 0x%x", sflags); - - if (!shf) { - shf = (struct shf *) alloc(sizeof(struct shf), ATEMP); - sflags |= SHF_ALLOCS; - } - shf->areap = ATEMP; - if (!buf && (sflags & SHF_WR) && (sflags & SHF_DYNAMIC)) { - if (bsize <= 0) - bsize = 64; - sflags |= SHF_ALLOCB; - buf = alloc(bsize, shf->areap); - } - shf->fd = -1; - shf->buf = shf->rp = shf->wp = (unsigned char *) buf; - shf->rnleft = bsize; - shf->rbsize = bsize; - shf->wnleft = bsize - 1; /* space for a '\0' */ - shf->wbsize = bsize; - shf->flags = sflags | SHF_STRING; - shf->errno_ = 0; - shf->bsize = bsize; - - return shf; -} - -/* Flush and close file descriptor, free the shf structure */ -int -shf_close(shf) - struct shf *shf; -{ - int ret = 0; - - if (shf->fd >= 0) { - ret = shf_flush(shf); - if (close(shf->fd) < 0) - ret = EOF; - } - if (shf->flags & SHF_ALLOCS) - afree(shf, shf->areap); - else if (shf->flags & SHF_ALLOCB) - afree(shf->buf, shf->areap); - - return ret; -} - -/* Flush and close file descriptor, don't free file structure */ -int -shf_fdclose(shf) - struct shf *shf; -{ - int ret = 0; - - if (shf->fd >= 0) { - ret = shf_flush(shf); - if (close(shf->fd) < 0) - ret = EOF; - shf->rnleft = 0; - shf->rp = shf->buf; - shf->wnleft = 0; - shf->fd = -1; - } - - return ret; -} - -/* Close a string - if it was opened for writing, it is null terminated; - * returns a pointer to the string and frees shf if it was allocated - * (does not free string if it was allocated). - */ -char * -shf_sclose(shf) - struct shf *shf; -{ - unsigned char *s = shf->buf; - - /* null terminate */ - if (shf->flags & SHF_WR) { - shf->wnleft++; - shf_putc('\0', shf); - } - if (shf->flags & SHF_ALLOCS) - afree(shf, shf->areap); - return (char *) s; -} - -/* Flush and free file structure, don't close file descriptor */ -int -shf_finish(shf) - struct shf *shf; -{ - int ret = 0; - - if (shf->fd >= 0) - ret = shf_flush(shf); - if (shf->flags & SHF_ALLOCS) - afree(shf, shf->areap); - else if (shf->flags & SHF_ALLOCB) - afree(shf->buf, shf->areap); - - return ret; -} - -/* Un-read what has been read but not examined, or write what has been - * buffered. Returns 0 for success, EOF for (write) error. - */ -int -shf_flush(shf) - struct shf *shf; -{ - if (shf->flags & SHF_STRING) - return (shf->flags & SHF_WR) ? EOF : 0; - - if (shf->fd < 0) - internal_errorf(1, "shf_flush: no fd"); - - if (shf->flags & SHF_ERROR) { - errno = shf->errno_; - return EOF; - } - - if (shf->flags & SHF_READING) { - shf->flags &= ~(SHF_EOF | SHF_READING); - if (shf->rnleft > 0) { - lseek(shf->fd, (off_t) -shf->rnleft, 1); - shf->rnleft = 0; - shf->rp = shf->buf; - } - return 0; - } else if (shf->flags & SHF_WRITING) - return shf_emptybuf(shf, 0); - - return 0; -} - -/* Write out any buffered data. If currently reading, flushes the read - * buffer. Returns 0 for success, EOF for (write) error. - */ -static int -shf_emptybuf(shf, flags) - struct shf *shf; - int flags; -{ - int ret = 0; - - if (!(shf->flags & SHF_STRING) && shf->fd < 0) - internal_errorf(1, "shf_emptybuf: no fd"); - - if (shf->flags & SHF_ERROR) { - errno = shf->errno_; - return EOF; - } - - if (shf->flags & SHF_READING) { - if (flags & EB_READSW) /* doesn't happen */ - return 0; - ret = shf_flush(shf); - shf->flags &= ~SHF_READING; - } - if (shf->flags & SHF_STRING) { - unsigned char *nbuf; - - /* Note that we assume SHF_ALLOCS is not set if SHF_ALLOCB - * is set... (changing the shf pointer could cause problems) - */ - if (!(flags & EB_GROW) || !(shf->flags & SHF_DYNAMIC) - || !(shf->flags & SHF_ALLOCB)) - return EOF; - /* allocate more space for buffer */ - nbuf = (unsigned char *) aresize(shf->buf, shf->wbsize * 2, - shf->areap); - shf->rp = nbuf + (shf->rp - shf->buf); - shf->wp = nbuf + (shf->wp - shf->buf); - shf->rbsize += shf->wbsize; - shf->wnleft += shf->wbsize; - shf->wbsize *= 2; - shf->buf = nbuf; - } else { - if (shf->flags & SHF_WRITING) { - int ntowrite = shf->wp - shf->buf; - unsigned char *buf = shf->buf; - int n; - - while (ntowrite > 0) { - n = write(shf->fd, buf, ntowrite); - if (n < 0) { - if (errno == EINTR - && !(shf->flags & SHF_INTERRUPT)) - continue; - shf->flags |= SHF_ERROR; - shf->errno_ = errno; - shf->wnleft = 0; - if (buf != shf->buf) { - /* allow a second flush - * to work */ - memmove(shf->buf, buf, - ntowrite); - shf->wp = shf->buf + ntowrite; - } - return EOF; - } - buf += n; - ntowrite -= n; - } - if (flags & EB_READSW) { - shf->wp = shf->buf; - shf->wnleft = 0; - shf->flags &= ~SHF_WRITING; - return 0; - } - } - shf->wp = shf->buf; - shf->wnleft = shf->wbsize; - } - shf->flags |= SHF_WRITING; - - return ret; -} - -/* Fill up a read buffer. Returns EOF for a read error, 0 otherwise. */ -static int -shf_fillbuf(shf) - struct shf *shf; -{ - if (shf->flags & SHF_STRING) - return 0; - - if (shf->fd < 0) - internal_errorf(1, "shf_fillbuf: no fd"); - - if (shf->flags & (SHF_EOF | SHF_ERROR)) { - if (shf->flags & SHF_ERROR) - errno = shf->errno_; - return EOF; - } - - if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF) - return EOF; - - shf->flags |= SHF_READING; - - shf->rp = shf->buf; - while (1) { - shf->rnleft = blocking_read(shf->fd, (char *) shf->buf, - shf->rbsize); - if (shf->rnleft < 0 && errno == EINTR - && !(shf->flags & SHF_INTERRUPT)) - continue; - break; - } - if (shf->rnleft <= 0) { - if (shf->rnleft < 0) { - shf->flags |= SHF_ERROR; - shf->errno_ = errno; - shf->rnleft = 0; - shf->rp = shf->buf; - return EOF; - } - shf->flags |= SHF_EOF; - } - return 0; -} - -/* Seek to a new position in the file. If writing, flushes the buffer - * first. If reading, optimizes small relative seeks that stay inside the - * buffer. Returns 0 for success, EOF otherwise. - */ -int -shf_seek(shf, where, from) - struct shf *shf; - off_t where; - int from; -{ - if (shf->fd < 0) { - errno = EINVAL; - return EOF; - } - - if (shf->flags & SHF_ERROR) { - errno = shf->errno_; - return EOF; - } - - if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF) - return EOF; - - if (shf->flags & SHF_READING) { - if (from == SEEK_CUR && - (where < 0 ? - -where >= shf->rbsize - shf->rnleft : - where < shf->rnleft)) { - shf->rnleft -= where; - shf->rp += where; - return 0; - } - shf->rnleft = 0; - shf->rp = shf->buf; - } - - shf->flags &= ~(SHF_EOF | SHF_READING | SHF_WRITING); - - if (lseek(shf->fd, where, from) < 0) { - shf->errno_ = errno; - shf->flags |= SHF_ERROR; - return EOF; - } - - return 0; -} - - -/* Read a buffer from shf. Returns the number of bytes read into buf, - * if no bytes were read, returns 0 if end of file was seen, EOF if - * a read error occurred. - */ -int -shf_read(buf, bsize, shf) - char *buf; - int bsize; - struct shf *shf; -{ - int orig_bsize = bsize; - int ncopy; - - if (!(shf->flags & SHF_RD)) - internal_errorf(1, "shf_read: flags %x", shf->flags); - - if (bsize <= 0) - internal_errorf(1, "shf_read: bsize %d", bsize); - - while (bsize > 0) { - if (shf->rnleft == 0 - && (shf_fillbuf(shf) == EOF || shf->rnleft == 0)) - break; - ncopy = shf->rnleft; - if (ncopy > bsize) - ncopy = bsize; - memcpy(buf, shf->rp, ncopy); - buf += ncopy; - bsize -= ncopy; - shf->rp += ncopy; - shf->rnleft -= ncopy; - } - /* Note: fread(3S) returns 0 for errors - this doesn't */ - return orig_bsize == bsize ? (shf_error(shf) ? EOF : 0) - : orig_bsize - bsize; -} - -/* Read up to a newline or EOF. The newline is put in buf; buf is always - * null terminated. Returns NULL on read error or if nothing was read before - * end of file, returns a pointer to the null byte in buf otherwise. - */ -char * -shf_getse(buf, bsize, shf) - char *buf; - int bsize; - struct shf *shf; -{ - unsigned char *end; - int ncopy; - char *orig_buf = buf; - - if (!(shf->flags & SHF_RD)) - internal_errorf(1, "shf_getse: flags %x", shf->flags); - - if (bsize <= 0) - return (char *) 0; - - --bsize; /* save room for null */ - do { - if (shf->rnleft == 0) { - if (shf_fillbuf(shf) == EOF) - return NULL; - if (shf->rnleft == 0) { - *buf = '\0'; - return buf == orig_buf ? NULL : buf; - } - } - end = (unsigned char *) memchr((char *) shf->rp, '\n', - shf->rnleft); - ncopy = end ? end - shf->rp + 1 : shf->rnleft; - if (ncopy > bsize) - ncopy = bsize; - memcpy(buf, (char *) shf->rp, ncopy); - shf->rp += ncopy; - shf->rnleft -= ncopy; - buf += ncopy; - bsize -= ncopy; -#ifdef OS2 - if (end && buf > orig_buf + 1 && buf[-2] == '\r') { - buf--; - bsize++; - buf[-1] = '\n'; - } -#endif - - } while (!end && bsize); - *buf = '\0'; - return buf; -} - -/* Returns the char read. Returns EOF for error and end of file. */ -int -shf_getchar(shf) - struct shf *shf; -{ - if (!(shf->flags & SHF_RD)) - internal_errorf(1, "shf_getchar: flags %x", shf->flags); - - if (shf->rnleft == 0 && (shf_fillbuf(shf) == EOF || shf->rnleft == 0)) - return EOF; - --shf->rnleft; - return *shf->rp++; -} - -/* Put a character back in the input stream. Returns the character if - * successful, EOF if there is no room. - */ -int -shf_ungetc(c, shf) - int c; - struct shf *shf; -{ - if (!(shf->flags & SHF_RD)) - internal_errorf(1, "shf_ungetc: flags %x", shf->flags); - - if ((shf->flags & SHF_ERROR) || c == EOF - || (shf->rp == shf->buf && shf->rnleft)) - return EOF; - - if ((shf->flags & SHF_WRITING) && shf_emptybuf(shf, EB_READSW) == EOF) - return EOF; - - if (shf->rp == shf->buf) - shf->rp = shf->buf + shf->rbsize; - if (shf->flags & SHF_STRING) { - /* Can unget what was read, but not something different - we - * don't want to modify a string. - */ - if (shf->rp[-1] != c) - return EOF; - shf->flags &= ~SHF_EOF; - shf->rp--; - shf->rnleft++; - return c; - } - shf->flags &= ~SHF_EOF; - *--(shf->rp) = c; - shf->rnleft++; - return c; -} - -/* Write a character. Returns the character if successful, EOF if - * the char could not be written. - */ -int -shf_putchar(c, shf) - int c; - struct shf *shf; -{ - if (!(shf->flags & SHF_WR)) - internal_errorf(1, "shf_putchar: flags %x", shf->flags); - - if (c == EOF) - return EOF; - - if (shf->flags & SHF_UNBUF) { - char cc = c; - int n; - - if (shf->fd < 0) - internal_errorf(1, "shf_putchar: no fd"); - if (shf->flags & SHF_ERROR) { - errno = shf->errno_; - return EOF; - } - while ((n = write(shf->fd, &cc, 1)) != 1) - if (n < 0) { - if (errno == EINTR - && !(shf->flags & SHF_INTERRUPT)) - continue; - shf->flags |= SHF_ERROR; - shf->errno_ = errno; - return EOF; - } - } else { - /* Flush deals with strings and sticky errors */ - if (shf->wnleft == 0 && shf_emptybuf(shf, EB_GROW) == EOF) - return EOF; - shf->wnleft--; - *shf->wp++ = c; - } - - return c; -} - -/* Write a string. Returns the length of the string if successful, EOF if - * the string could not be written. - */ -int -shf_puts(s, shf) - const char *s; - struct shf *shf; -{ - if (!s) - return EOF; - - return shf_write(s, strlen(s), shf); -} - -/* Write a buffer. Returns nbytes if successful, EOF if there is an error. */ -int -shf_write(buf, nbytes, shf) - const char *buf; - int nbytes; - struct shf *shf; -{ - int orig_nbytes = nbytes; - int n; - int ncopy; - - if (!(shf->flags & SHF_WR)) - internal_errorf(1, "shf_write: flags %x", shf->flags); - - if (nbytes < 0) - internal_errorf(1, "shf_write: nbytes %d", nbytes); - - /* Don't buffer if buffer is empty and we're writting a large amount. */ - if ((ncopy = shf->wnleft) - && (shf->wp != shf->buf || nbytes < shf->wnleft)) - { - if (ncopy > nbytes) - ncopy = nbytes; - memcpy(shf->wp, buf, ncopy); - nbytes -= ncopy; - buf += ncopy; - shf->wp += ncopy; - shf->wnleft -= ncopy; - } - if (nbytes > 0) { - /* Flush deals with strings and sticky errors */ - if (shf_emptybuf(shf, EB_GROW) == EOF) - return EOF; - if (nbytes > shf->wbsize) { - ncopy = nbytes; - if (shf->wbsize) - ncopy -= nbytes % shf->wbsize; - nbytes -= ncopy; - while (ncopy > 0) { - n = write(shf->fd, buf, ncopy); - if (n < 0) { - if (errno == EINTR - && !(shf->flags & SHF_INTERRUPT)) - continue; - shf->flags |= SHF_ERROR; - shf->errno_ = errno; - shf->wnleft = 0; - /* Note: fwrite(3S) returns 0 for - * errors - this doesn't */ - return EOF; - } - buf += n; - ncopy -= n; - } - } - if (nbytes > 0) { - memcpy(shf->wp, buf, nbytes); - shf->wp += nbytes; - shf->wnleft -= nbytes; - } - } - - return orig_nbytes; -} - -int -#ifdef HAVE_PROTOTYPES -shf_fprintf(struct shf *shf, const char *fmt, ...) -#else -shf_fprintf(shf, fmt, va_alist) - struct shf *shf; - const char *fmt; - va_dcl -#endif -{ - va_list args; - int n; - - SH_VA_START(args, fmt); - n = shf_vfprintf(shf, fmt, args); - va_end(args); - - return n; -} - -int -#ifdef HAVE_PROTOTYPES -shf_snprintf(char *buf, int bsize, const char *fmt, ...) -#else -shf_snprintf(buf, bsize, fmt, va_alist) - char *buf; - int bsize; - const char *fmt; - va_dcl -#endif -{ - struct shf shf; - va_list args; - int n; - - if (!buf || bsize <= 0) - internal_errorf(1, "shf_snprintf: buf %lx, bsize %d", - (long) buf, bsize); - - shf_sopen(buf, bsize, SHF_WR, &shf); - SH_VA_START(args, fmt); - n = shf_vfprintf(&shf, fmt, args); - va_end(args); - shf_sclose(&shf); /* null terminates */ - return n; -} - -char * -#ifdef HAVE_PROTOTYPES -shf_smprintf(const char *fmt, ...) -#else -shf_smprintf(fmt, va_alist) - char *fmt; - va_dcl -#endif -{ - struct shf shf; - va_list args; - - shf_sopen((char *) 0, 0, SHF_WR|SHF_DYNAMIC, &shf); - SH_VA_START(args, fmt); - shf_vfprintf(&shf, fmt, args); - va_end(args); - return shf_sclose(&shf); /* null terminates */ -} - -#undef FP /* if you want floating point stuff */ - -#define BUF_SIZE 128 -#define FPBUF_SIZE (DMAXEXP+16)/* this must be > - * MAX(DMAXEXP, log10(pow(2, DSIGNIF))) - * + ceil(log10(DMAXEXP)) + 8 (I think). - * Since this is hard to express as a - * constant, just use a large buffer. - */ - -/* - * What kinda of machine we on? Hopefully the C compiler will optimize - * this out... - * - * For shorts, we want sign extend for %d but not for %[oxu] - on 16 bit - * machines it don't matter. Assumes C compiler has converted shorts to - * ints before pushing them. - */ -#define POP_INT(f, s, a) (((f) & FL_LONG) ? \ - va_arg((a), unsigned long) \ - : \ - (sizeof(int) < sizeof(long) ? \ - ((s) ? \ - (long) va_arg((a), int) \ - : \ - va_arg((a), unsigned)) \ - : \ - va_arg((a), unsigned))) - -#define ABIGNUM 32000 /* big numer that will fit in a short */ -#define LOG2_10 3.321928094887362347870319429 /* log base 2 of 10 */ - -#define FL_HASH 0x001 /* `#' seen */ -#define FL_PLUS 0x002 /* `+' seen */ -#define FL_RIGHT 0x004 /* `-' seen */ -#define FL_BLANK 0x008 /* ` ' seen */ -#define FL_SHORT 0x010 /* `h' seen */ -#define FL_LONG 0x020 /* `l' seen */ -#define FL_ZERO 0x040 /* `0' seen */ -#define FL_DOT 0x080 /* '.' seen */ -#define FL_UPPER 0x100 /* format character was uppercase */ -#define FL_NUMBER 0x200 /* a number was formated %[douxefg] */ - - -#ifdef FP -#include - -static double -my_ceil(d) - double d; -{ - double i; - - return d - modf(d, &i) + (d < 0 ? -1 : 1); -} -#endif /* FP */ - -int -shf_vfprintf(shf, fmt, args) - struct shf *shf; - const char *fmt; - va_list args; -{ - char c, *s; - int UNINITIALIZED(tmp); - int field, precision; - int len; - int flags; - unsigned long lnum; - /* %#o produces the longest output */ - char numbuf[(BITS(long) + 2) / 3 + 1]; - /* this stuff for dealing with the buffer */ - int nwritten = 0; - static char nulls[] = "(null %s)"; -#ifdef FP - /* should be in - * extern double frexp(); - */ - extern char *ecvt(); - - double fpnum; - int expo, decpt; - char style; - char fpbuf[FPBUF_SIZE]; -#endif /* FP */ - - if (!fmt) - return 0; - - while ((c = *fmt++)) { - if (c != '%') { - shf_putc(c, shf); - nwritten++; - continue; - } - /* - * This will accept flags/fields in any order - not - * just the order specified in printf(3), but this is - * the way _doprnt() seems to work (on bsd and sysV). - * The only restriction is that the format character must - * come last :-). - */ - flags = field = precision = 0; - for ( ; (c = *fmt++) ; ) { - switch (c) { - case '#': - flags |= FL_HASH; - continue; - - case '+': - flags |= FL_PLUS; - continue; - - case '-': - flags |= FL_RIGHT; - continue; - - case ' ': - flags |= FL_BLANK; - continue; - - case '0': - if (!(flags & FL_DOT)) - flags |= FL_ZERO; - continue; - - case '.': - flags |= FL_DOT; - precision = 0; - continue; - - case '*': - tmp = va_arg(args, int); - if (flags & FL_DOT) - precision = tmp; - else if ((field = tmp) < 0) { - field = -field; - flags |= FL_RIGHT; - } - continue; - - case 'l': - flags |= FL_LONG; - continue; - - case 'h': - flags |= FL_SHORT; - continue; - } - if (digit(c)) { - tmp = c - '0'; - while (c = *fmt++, digit(c)) - tmp = tmp * 10 + c - '0'; - --fmt; - if (tmp < 0) /* overflow? */ - tmp = 0; - if (flags & FL_DOT) - precision = tmp; - else - field = tmp; - continue; - } - break; - } - - if (precision < 0) - precision = 0; - - if (!c) /* nasty format */ - break; - - if (c >= 'A' && c <= 'Z') { - flags |= FL_UPPER; - c = c - 'A' + 'a'; - } - - switch (c) { - case 'p': /* pointer */ - flags &= ~(FL_LONG | FL_SHORT); - if (sizeof(char *) > sizeof(int)) - flags |= FL_LONG; /* hope it fits.. */ - /* aaahhh... */ - case 'd': - case 'i': - case 'o': - case 'u': - case 'x': - flags |= FL_NUMBER; - s = &numbuf[sizeof(numbuf)]; - lnum = POP_INT(flags, c == 'd', args); - switch (c) { - case 'd': - case 'i': - if (0 > (long) lnum) - lnum = - (long) lnum, tmp = 1; - else - tmp = 0; - /* aaahhhh..... */ - - case 'u': - do { - *--s = lnum % 10 + '0'; - lnum /= 10; - } while (lnum); - - if (c != 'u') { - if (tmp) - *--s = '-'; - else if (flags & FL_PLUS) - *--s = '+'; - else if (flags & FL_BLANK) - *--s = ' '; - } - break; - - case 'o': - do { - *--s = (lnum & 0x7) + '0'; - lnum >>= 3; - } while (lnum); - - if ((flags & FL_HASH) && *s != '0') - *--s = '0'; - break; - - case 'p': - case 'x': - { - const char *digits = (flags & FL_UPPER) ? - "0123456789ABCDEF" - : "0123456789abcdef"; - do { - *--s = digits[lnum & 0xf]; - lnum >>= 4; - } while (lnum); - - if (flags & FL_HASH) { - *--s = (flags & FL_UPPER) ? 'X' : 'x'; - *--s = '0'; - } - } - } - len = &numbuf[sizeof(numbuf)] - s; - if (flags & FL_DOT) { - if (precision > len) { - field = precision; - flags |= FL_ZERO; - } else - precision = len; /* no loss */ - } - break; - -#ifdef FP - case 'e': - case 'g': - case 'f': - { - char *p; - - /* - * This could probably be done better, - * but it seems to work. Note that gcvt() - * is not used, as you cannot tell it to - * not strip the zeros. - */ - flags |= FL_NUMBER; - if (!(flags & FL_DOT)) - precision = 6; /* default */ - /* - * Assumes doubles are pushed on - * the stack. If this is not so, then - * FL_LONG/FL_SHORT should be checked. - */ - fpnum = va_arg(args, double); - s = fpbuf; - style = c; - /* - * This is the same as - * expo = ceil(log10(fpnum)) - * but doesn't need -lm. This is an - * approximation as expo is rounded up. - */ - (void) frexp(fpnum, &expo); - expo = my_ceil(expo / LOG2_10); - - if (expo < 0) - expo = 0; - - p = ecvt(fpnum, precision + 1 + expo, - &decpt, &tmp); - if (c == 'g') { - if (decpt < -4 || decpt > precision) - style = 'e'; - else - style = 'f'; - if (decpt > 0 && (precision -= decpt) < 0) - precision = 0; - } - if (tmp) - *s++ = '-'; - else if (flags & FL_PLUS) - *s++ = '+'; - else if (flags & FL_BLANK) - *s++ = ' '; - - if (style == 'e') - *s++ = *p++; - else { - if (decpt > 0) { - /* Overflow check - should - * never have this problem. - */ - if (decpt > - &fpbuf[sizeof(fpbuf)] - - s - 8) - decpt = - &fpbuf[sizeof(fpbuf)] - - s - 8; - (void) memcpy(s, p, decpt); - s += decpt; - p += decpt; - } else - *s++ = '0'; - } - - /* print the fraction? */ - if (precision > 0) { - *s++ = '.'; - /* Overflow check - should - * never have this problem. - */ - if (precision > &fpbuf[sizeof(fpbuf)] - - s - 7) - precision = - &fpbuf[sizeof(fpbuf)] - - s - 7; - for (tmp = decpt; tmp++ < 0 && - precision > 0 ; precision--) - *s++ = '0'; - tmp = strlen(p); - if (precision > tmp) - precision = tmp; - /* Overflow check - should - * never have this problem. - */ - if (precision > &fpbuf[sizeof(fpbuf)] - - s - 7) - precision = - &fpbuf[sizeof(fpbuf)] - - s - 7; - (void) memcpy(s, p, precision); - s += precision; - /* - * `g' format strips trailing - * zeros after the decimal. - */ - if (c == 'g' && !(flags & FL_HASH)) { - while (*--s == '0') - ; - if (*s != '.') - s++; - } - } else if (flags & FL_HASH) - *s++ = '.'; - - if (style == 'e') { - *s++ = (flags & FL_UPPER) ? 'E' : 'e'; - if (--decpt >= 0) - *s++ = '+'; - else { - *s++ = '-'; - decpt = -decpt; - } - p = &numbuf[sizeof(numbuf)]; - for (tmp = 0; tmp < 2 || decpt ; tmp++) { - *--p = '0' + decpt % 10; - decpt /= 10; - } - tmp = &numbuf[sizeof(numbuf)] - p; - (void) memcpy(s, p, tmp); - s += tmp; - } - - len = s - fpbuf; - s = fpbuf; - precision = len; - break; - } -#endif /* FP */ - - case 's': - if (!(s = va_arg(args, char *))) - s = nulls; - len = strlen(s); - break; - - case 'c': - flags &= ~FL_DOT; - numbuf[0] = va_arg(args, int); - s = numbuf; - len = 1; - break; - - case '%': - default: - numbuf[0] = c; - s = numbuf; - len = 1; - break; - } - - /* - * At this point s should point to a string that is - * to be formatted, and len should be the length of the - * string. - */ - if (!(flags & FL_DOT) || len < precision) - precision = len; - if (field > precision) { - field -= precision; - if (!(flags & FL_RIGHT)) { - field = -field; - /* skip past sign or 0x when padding with 0 */ - if ((flags & FL_ZERO) && (flags & FL_NUMBER)) { - if (*s == '+' || *s == '-' || *s ==' ') - { - shf_putc(*s, shf); - s++; - precision--; - nwritten++; - } else if (*s == '0') { - shf_putc(*s, shf); - s++; - nwritten++; - if (--precision > 0 && - (*s | 0x20) == 'x') - { - shf_putc(*s, shf); - s++; - precision--; - nwritten++; - } - } - c = '0'; - } else - c = flags & FL_ZERO ? '0' : ' '; - if (field < 0) { - nwritten += -field; - for ( ; field < 0 ; field++) - shf_putc(c, shf); - } - } else - c = ' '; - } else - field = 0; - - if (precision > 0) { - nwritten += precision; - for ( ; precision-- > 0 ; s++) - shf_putc(*s, shf); - } - if (field > 0) { - nwritten += field; - for ( ; field > 0 ; --field) - shf_putc(c, shf); - } - } - - return shf_error(shf) ? EOF : nwritten; -} diff --git a/bin/ksh/shf.h b/bin/ksh/shf.h deleted file mode 100644 index bc8af96c4..000000000 --- a/bin/ksh/shf.h +++ /dev/null @@ -1,87 +0,0 @@ -/* $NetBSD: shf.h,v 1.3 1999/10/20 15:10:00 hubertf Exp $ */ - -#ifndef SHF_H -# define SHF_H - -/* - * Shell file I/O routines - */ -/* $Id: shf.h,v 1.3 1999/10/20 15:10:00 hubertf Exp $ */ - -#define SHF_BSIZE 512 - -#define shf_fileno(shf) ((shf)->fd) -#define shf_setfileno(shf,nfd) ((shf)->fd = (nfd)) -#define shf_getc(shf) ((shf)->rnleft > 0 ? (shf)->rnleft--, *(shf)->rp++ : \ - shf_getchar(shf)) -#define shf_putc(c, shf) ((shf)->wnleft == 0 ? shf_putchar((c), (shf)) \ - : ((shf)->wnleft--, *(shf)->wp++ = (c))) -#define shf_eof(shf) ((shf)->flags & SHF_EOF) -#define shf_error(shf) ((shf)->flags & SHF_ERROR) -#define shf_errno(shf) ((shf)->errno_) -#define shf_clearerr(shf) ((shf)->flags &= ~(SHF_EOF | SHF_ERROR)) - -/* Flags passed to shf_*open() */ -#define SHF_RD 0x0001 -#define SHF_WR 0x0002 -#define SHF_RDWR (SHF_RD|SHF_WR) -#define SHF_ACCMODE 0x0003 /* mask */ -#define SHF_GETFL 0x0004 /* use fcntl() to figure RD/WR flags */ -#define SHF_UNBUF 0x0008 /* unbuffered I/O */ -#define SHF_CLEXEC 0x0010 /* set close on exec flag */ -#define SHF_MAPHI 0x0020 /* make fd > FDBASE (and close orig) - * (shf_open() only) */ -#define SHF_DYNAMIC 0x0040 /* string: increase buffer as needed */ -#define SHF_INTERRUPT 0x0080 /* EINTR in read/write causes error */ -/* Flags used internally */ -#define SHF_STRING 0x0100 /* a string, not a file */ -#define SHF_ALLOCS 0x0200 /* shf and shf->buf were alloc()ed */ -#define SHF_ALLOCB 0x0400 /* shf->buf was alloc()ed */ -#define SHF_ERROR 0x0800 /* read()/write() error */ -#define SHF_EOF 0x1000 /* read eof (sticky) */ -#define SHF_READING 0x2000 /* currently reading: rnleft,rp valid */ -#define SHF_WRITING 0x4000 /* currently writing: wnleft,wp valid */ - - -struct shf { - int flags; /* see SHF_* */ - unsigned char *rp; /* read: current position in buffer */ - int rbsize; /* size of buffer (1 if SHF_UNBUF) */ - int rnleft; /* read: how much data left in buffer */ - unsigned char *wp; /* write: current position in buffer */ - int wbsize; /* size of buffer (0 if SHF_UNBUF) */ - int wnleft; /* write: how much space left in buffer */ - unsigned char *buf; /* buffer */ - int fd; /* file descriptor */ - int errno_; /* saved value of errno after error */ - int bsize; /* actual size of buf */ - Area *areap; /* area shf/buf were allocated in */ -}; - -extern struct shf shf_iob[]; - -struct shf *shf_open ARGS((const char *name, int oflags, int mode, - int sflags)); -struct shf *shf_fdopen ARGS((int fd, int sflags, struct shf *shf)); -struct shf *shf_reopen ARGS((int fd, int sflags, struct shf *shf)); -struct shf *shf_sopen ARGS((char *buf, int bsize, int sflags, - struct shf *shf)); -int shf_close ARGS((struct shf *shf)); -int shf_fdclose ARGS((struct shf *shf)); -char *shf_sclose ARGS((struct shf *shf)); -int shf_finish ARGS((struct shf *shf)); -int shf_flush ARGS((struct shf *shf)); -int shf_seek ARGS((struct shf *shf, off_t where, int from)); -int shf_read ARGS((char *buf, int bsize, struct shf *shf)); -char *shf_getse ARGS((char *buf, int bsize, struct shf *shf)); -int shf_getchar ARGS((struct shf *shf)); -int shf_ungetc ARGS((int c, struct shf *shf)); -int shf_putchar ARGS((int c, struct shf *shf)); -int shf_puts ARGS((const char *s, struct shf *shf)); -int shf_write ARGS((const char *buf, int nbytes, struct shf *shf)); -int shf_fprintf ARGS((struct shf *shf, const char *fmt, ...)); -int shf_snprintf ARGS((char *buf, int bsize, const char *fmt, ...)); -char *shf_smprintf ARGS((const char *fmt, ...)); -int shf_vfprintf ARGS((struct shf *, const char *fmt, va_list args)); - -#endif /* SHF_H */ diff --git a/bin/ksh/sigact.c b/bin/ksh/sigact.c deleted file mode 100644 index 80ff9a8e2..000000000 --- a/bin/ksh/sigact.c +++ /dev/null @@ -1,486 +0,0 @@ -/* $NetBSD: sigact.c,v 1.4 2003/06/23 11:39:03 agc Exp $ */ - -/* NAME: - * sigact.c - fake sigaction(2) - * - * SYNOPSIS: - * #include "sigact.h" - * - * int sigaction(int sig, struct sigaction *act, - * struct sigaction *oact); - * int sigaddset(sigset_t *mask, int sig); - * int sigdelset(sigset_t *mask, int sig); - * int sigemptyset(sigset_t *mask); - * int sigfillset(sigset_t *mask); - * int sigismember(sigset_t *mask, int sig); - * int sigpending(sigset_t *set); - * int sigprocmask(int how, sigset_t *set, sigset_t *oset); - * int sigsuspend(sigset_t *mask); - * - * RETSIGTYPE (*Signal(int sig, RETSIGTYPE (*disp)(int)))(int); - * - * DESCRIPTION: - * This is a fake sigaction implementation. It uses - * sigsetmask(2) et al or sigset(2) and friends if - * available, otherwise it just uses signal(2). If it - * thinks sigaction(2) really exists it compiles to "almost" - * nothing. - * - * In any case it provides a Signal() function that is - * implemented in terms of sigaction(). - * If not using signal(2) as part of the underlying - * implementation (USE_SIGNAL or USE_SIGMASK), and - * NO_SIGNAL is not defined, it also provides a signal() - * function that calls Signal(). - * - * The need for all this mucking about is the problems - * caused by mixing various signal handling mechanisms in - * the one process. This module allows for a consistent - * POSIX compliant interface to whatever is actually - * available. - * - * sigaction() allows the caller to examine and/or set the - * action to be associated with a given signal. "act" and - * "oact" are pointers to 'sigaction structs': - *.nf - * - * struct sigaction - * { - * RETSIGTYPE (*sa_handler)(); - * sigset_t sa_mask; - * int sa_flags; - * }; - *.fi - * - * RETSIGTYPE is normally 'void' in the POSIX implementation - * and for most current systems. On some older UNIX - * systems, signal handlers do not return 'void', so - * this implementation keeps 'sa_handler' inline with the - * hosts normal signal handling conventions. - * 'sa_mask' controls which signals will be blocked while - * the selected signal handler is active. It is not used - * in this implementation. - * 'sa_flags' controls various semantics such as whether - * system calls should be automagically restarted - * (SA_RESTART) etc. It is not used in this - * implementation. - * Either "act" or "oact" may be NULL in which case the - * appropriate operation is skipped. - * - * sigaddset() adds "sig" to the sigset_t pointed to by "mask". - * - * sigdelset() removes "sig" from the sigset_t pointed to - * by "mask". - * - * sigemptyset() makes the sigset_t pointed to by "mask" empty. - * - * sigfillset() makes the sigset_t pointed to by "mask" - * full ie. match all signals. - * - * sigismember() returns true if "sig" is found in "*mask". - * - * sigpending() is supposed to return "set" loaded with the - * set of signals that are blocked and pending for the - * calling process. It does nothing in this impementation. - * - * sigprocmask() is used to examine and/or change the - * signal mask for the calling process. Either "set" or - * "oset" may be NULL in which case the appropriate - * operation is skipped. "how" may be one of SIG_BLOCK, - * SIG_UNBLOCK or SIG_SETMASK. If this package is built - * with USE_SIGNAL, then this routine achieves nothing. - * - * sigsuspend() sets the signal mask to "*mask" and waits - * for a signal to be delivered after which the previous - * mask is restored. - * - * - * RETURN VALUE: - * 0==success, -1==failure - * - * BUGS: - * Since we fake most of this, don't expect fancy usage to - * work. - * - * AUTHOR: - * Simon J. Gerraty - */ -/* COPYRIGHT: - * @(#)Copyright (c) 1992 Simon J. Gerraty - * - * This is free software. It comes with NO WARRANTY. - * Permission to use, modify and distribute this source code - * is granted subject to the following conditions. - * 1/ that that the above copyright notice and this notice - * are preserved in all copies and that due credit be given - * to the author. - * 2/ that any changes to this code are clearly commented - * as such so that the author does get blamed for bugs - * other than his own. - * - * Please send copies of changes and bug-fixes to: - * sjg@zen.void.oz.au - * - */ -/* Changes to sigact.c for pdksh, Michael Rendell : - * - sigsuspend(): pass *mask to bsd4.2 sigpause instead of mask. - * - changed SIG_HDLR to RETSIGTYPE for use with GNU autoconf - * - added and used RETSIGVAL - * - include sh.h instead of signal.h (to get *_SIGNALS macros) - * - changed if !SA_NOCLDSTOP ... to USE_FAKE_SIGACT to avoid confusion - * - set the USE_* defines using the *_SIGNALS defines from autoconf - * - sigaction(): if using BSD signals, use sigvec() (used to use - * signal()) and set the SV_INTERRUPT flag (POSIX says syscalls - * are interrupted and pdksh needs this behaviour). - * - define IS_KSH before including anything; ifdef out routines - * not used in ksh if IS_KSH is defined (same in sigact.h). - * - use ARGS() instead of __P() - * - sigaction(),sigsuspend(),Signal(),signal(): use handler_t typedef - * instead of explicit type. - */ -#include - -#ifndef lint -__RCSID("$NetBSD: sigact.c,v 1.4 2003/06/23 11:39:03 agc Exp $"); -#endif - - -/* - #include -*/ -#define IS_KSH -#include "sh.h" - -/* - #ifndef __P - # define __P(p) p - #endif -*/ - - -/* - * some systems have a faulty sigaction() implementation! - * Allow us to bypass it. - * Or they may have installed sigact.h as signal.h which is why - * we have SA_NOCLDSTOP defined. - */ -#ifdef USE_FAKE_SIGACT /* let autoconf decide.. */ -/* #if !defined(SA_NOCLDSTOP) || defined(_SIGACT_H) || defined(USE_SIGNAL) || defined(USE_SIGSET) || defined(USE_SIGMASK) */ - -/* Let autoconf decide which to use */ -#ifdef BSD42_SIGNALS -# define USE_SIGMASK -#else -# ifdef BSD41_SIGNALS -# define USE_SIGSET -# else -# define USE_SIGNAL -# endif -#endif /* BSD42_SIGNALS */ - -/* - * if we haven't been told, - * try and guess what we should implement with. - */ -#if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL) -# if defined(sigmask) || defined(BSD) || defined(_BSD) && !defined(BSD41) -# define USE_SIGMASK -# else -# ifndef NO_SIGSET -# define USE_SIGSET -# else -# define USE_SIGNAL -# endif -# endif -#endif -/* - * if we still don't know, we're in trouble - */ -#if !defined(USE_SIGSET) && !defined(USE_SIGMASK) && !defined(USE_SIGNAL) -error must know what to implement with -#endif - -#include "sigact.h" - -/* - * in case signal() has been mapped to our Signal(). - */ -#undef signal - - -int -sigaction(sig, act, oact) - int sig; - struct sigaction *act, *oact; -{ - handler_t oldh; - - if (act) - { -#ifdef USE_SIGSET - oldh = sigset(sig, act->sa_handler); -#else -# ifdef USE_SIGMASK - struct sigvec nsv,osv; - - nsv.sv_handler = act->sa_handler; - nsv.sv_mask = 0; /* punt */ - nsv.sv_flags = SV_INTERRUPT; /* punt */ - sigvec(sig, &nsv, &osv); - oldh = osv.sv_handler; -# else /* USE_SIGMASK */ - oldh = signal(sig, act->sa_handler); -# endif /* USE_SIGMASK */ -#endif - } - else - { - if (oact) - { -#ifdef USE_SIGSET - oldh = sigset(sig, SIG_IGN); -#else - oldh = signal(sig, SIG_IGN); -#endif - if (oldh != SIG_IGN && oldh != SIG_ERR) - { -#ifdef USE_SIGSET - (void) sigset(sig, oldh); -#else - (void) signal(sig, oldh); -#endif - } - } - } - if (oact) - { - oact->sa_handler = oldh; - } - return 0; /* hey we're faking it */ -} - - -int -sigaddset(mask, sig) - sigset_t *mask; - int sig; -{ - *mask |= sigmask(sig); - return 0; -} - - -#ifndef IS_KSH -int -sigdelset(mask, sig) - sigset_t *mask; - int sig; -{ - *mask &= ~(sigmask(sig)); - return 0; -} -#endif /* IS_KSH */ - - -int -sigemptyset(mask) - sigset_t *mask; -{ - *mask = 0; - return 0; -} - - -#ifndef IS_KSH -int -sigfillset(mask) - sigset_t *mask; -{ - *mask = ~0; - return 0; -} -#endif /* IS_KSH */ - - -#ifndef IS_KSH -int -sigismember(mask, sig) - sigset_t *mask; - int sig; -{ - return ((*mask) & sigmask(sig)); -} -#endif /* IS_KSH */ - - -#ifndef IS_KSH -int -sigpending(set) - sigset_t *set; -{ - return 0; /* faking it! */ -} -#endif /* IS_KSH */ - - -int -sigprocmask(how, set, oset) - int how; - sigset_t *set, *oset; -{ -#ifdef USE_SIGSET - register int i; -#endif - static sigset_t sm; - static int once = 0; - - if (!once) - { - /* - * initally we clear sm, - * there after, it represents the last - * thing we did. - */ - once++; -#ifdef USE_SIGMASK - sm = sigblock(0); -#else - sm = 0; -#endif - } - - if (oset) - *oset = sm; - if (set) - { - switch (how) - { - case SIG_BLOCK: - sm |= *set; - break; - case SIG_UNBLOCK: - sm &= ~(*set); - break; - case SIG_SETMASK: - sm = *set; - break; - } -#ifdef USE_SIGMASK - (void) sigsetmask(sm); -#else -# ifdef USE_SIGSET - for (i = 1; i < NSIG; i++) - { - if (how == SIG_UNBLOCK) - { - if (*set & sigmask(i)) - sigrelse(i); - } - else - if (sm & sigmask(i)) - { - sighold(i); - } - } -# endif -#endif - } - return 0; -} - - -int -sigsuspend(mask) - sigset_t *mask; -{ -#ifdef USE_SIGMASK - sigpause(*mask); -#else - register int i; - -# ifdef USE_SIGSET - - for (i = 1; i < NSIG; i++) - { - if (*mask & sigmask(i)) - { - /* not the same sigpause() as above! */ - sigpause(i); - break; - } - } -# else /* signal(2) only */ - handler_t oldh; - - /* - * make sure that signals in mask will not - * be ignored. - */ - for (i = 1; i < NSIG; i++) - { - if (*mask & sigmask(i)) - { - if ((oldh = signal(i, SIG_DFL)) != SIG_ERR && - oldh != SIG_IGN && - oldh != SIG_DFL) - (void) signal(i, oldh); /* restore handler */ - } - } - pause(); /* wait for a signal */ -# endif -#endif - return 0; -} - -#endif /* USE_FAKE_SIGACT (was ! SA_NOCLDSTOP) */ - -#if !defined(RETSIGTYPE) -# define RETSIGTYPE void -# define RETSIGVAL -#endif -#if !defined(SIG_ERR) -# define SIG_ERR (RETSIGTYPE (*)())-1 -#endif - -/* - * an implementation of signal() using sigaction(). - */ - -#ifndef IS_KSH -handler_t Signal(sig, handler) - int sig; - handler_t handler; -{ - struct sigaction act, oact; - - act.sa_handler = handler; - sigemptyset(&act.sa_mask); - act.sa_flags = 0; - if (sigaction(sig, &act, &oact) < 0) - return (SIG_ERR); - return (oact.sa_handler); -} -#endif /* IS_KSH */ - -#ifndef IS_KSH -#if !defined(USE_SIGNAL) && !defined(USE_SIGMASK) && !defined(NO_SIGNAL) -/* - * ensure we avoid signal mayhem - */ - -handler_t signal(sig, handler) - int sig; - handler_t handler; -{ - return (Signal(sig, handler)); -} -#endif -#endif /* IS_KSH */ - -/* This lot (for GNU-Emacs) goes at the end of the file. */ -/* - * Local Variables: - * version-control:t - * comment-column:40 - * End: - */ diff --git a/bin/ksh/sigact.h b/bin/ksh/sigact.h deleted file mode 100644 index e1dce463d..000000000 --- a/bin/ksh/sigact.h +++ /dev/null @@ -1,125 +0,0 @@ -/* $NetBSD: sigact.h,v 1.3 2002/05/25 23:29:17 wiz Exp $ */ - -/* NAME: - * sigact.h - sigaction et al - * - * SYNOPSIS: - * #include "sigact.h" - * - * DESCRIPTION: - * This header is the interface to a fake sigaction(2) - * implementation. It provides a POSIX compliant interface - * to whatever signal handling mechanisms are available. - * It also provides a Signal() function that is implemented - * in terms of sigaction(). - * If not using signal(2) as part of the underlying - * implementation (USE_SIGNAL or USE_SIGMASK), and - * NO_SIGNAL is not defined, it also provides a signal() - * function that calls Signal(). - * - * SEE ALSO: - * sigact.c - */ -/* - * RCSid: - * $NetBSD: sigact.h,v 1.3 2002/05/25 23:29:17 wiz Exp $ - */ -/* Changes to sigact.h for pdksh, Michael Rendell : - * - changed SIG_HDLR to RETSIGTYPE for use with GNU autoconf - * - added RETSIGVAL - * - ifdef'd out ARGS(), volatile and const initializations - * - ifdef'd out sigset_t definition - let autoconf handle it - * - ifdef out routines not used in ksh if IS_KSH is defined - * (same in sigact.c). - */ -#ifndef _SIGACT_H -#define _SIGACT_H - -/* - * most modern systems use void for signal handlers but - * not all. - */ -#ifndef RETSIGTYPE -# define RETSIGTYPE void -# define RETSIGVAL -#endif - -#if 0 /* ARGS(), volatile and const are already set up in config*.h -mhr */ -#undef ARGS -#define ARGS(p) p -#endif - -#ifndef IS_KSH -handler_t Signal ARGS((int sig, handler_t disp)); -#endif /* IS_KSH */ - -/* - * if you want to install this header as signal.h, - * modify this to pick up the original signal.h - */ -#ifndef SIGKILL -# include -#endif - -#ifndef SIG_ERR -# define SIG_ERR ((handler_t) -1) -#endif -#ifndef BADSIG -# define BADSIG SIG_ERR -#endif - -#ifndef SA_NOCLDSTOP -/* we assume we need the fake sigaction */ -/* sa_flags */ -#define SA_NOCLDSTOP 1 /* don't send SIGCHLD on child stop */ -#define SA_RESTART 2 /* re-start I/O */ - -/* sigprocmask flags */ -#define SIG_BLOCK 1 -#define SIG_UNBLOCK 2 -#define SIG_SETMASK 4 - -#if 0 /* autoconf will define sigset_t if it isn't available */ -/* - * this is a bit untidy - */ -#if !defined(__sys_stdtypes_h) -typedef unsigned int sigset_t; -#endif -#endif /* 0 */ - -/* - * POSIX sa_handler should return void, but since we are - * implementing in terms of something else, it may - * be appropriate to use the normal RETSIGTYPE return type - */ -struct sigaction -{ - handler_t sa_handler; - sigset_t sa_mask; - int sa_flags; -}; - - -int sigaction ARGS(( int sig, struct sigaction *act, struct sigaction *oact )); -int sigaddset ARGS(( sigset_t *mask, int sig )); -#ifndef IS_KSH -int sigdelset ARGS(( sigset_t *mask, int sig )); -#endif /* IS_KSH */ -int sigemptyset ARGS(( sigset_t *mask )); -#ifndef IS_KSH -int sigfillset ARGS(( sigset_t *mask )); -int sigismember ARGS(( sigset_t *mask, int sig )); -int sigpending ARGS(( sigset_t *set )); -#endif /* IS_KSH */ -int sigprocmask ARGS(( int how, sigset_t *set, sigset_t *oset )); -int sigsuspend ARGS(( sigset_t *mask )); - -#ifndef sigmask -# define sigmask(s) (1<<((s)-1)) /* convert SIGnum to mask */ -#endif -#if !defined(NSIG) && defined(_NSIG) -# define NSIG _NSIG -#endif -#endif /* ! SA_NOCLDSTOP */ -#endif /* _SIGACT_H */ diff --git a/bin/ksh/siglist.in b/bin/ksh/siglist.in deleted file mode 100644 index 8aa29a618..000000000 --- a/bin/ksh/siglist.in +++ /dev/null @@ -1,56 +0,0 @@ -# $NetBSD: siglist.in,v 1.2 1997/01/12 19:12:17 tls Exp $ -# -# List of signals used to initialize ksh's signal table (see trap.c -# and siglist.sh). -# -# Note that if a system has multiple defines for the same signal -# (eg, SIGABRT vs SIGIOT, SIGCHLD vs SIGCLD), only the first one -# will be seen, so the order in this list is important. -# - HUP Hangup - INT Interrupt - QUIT Quit - ILL Illegal instruction - TRAP Trace trap -# before IOT (ABRT is posix and ABRT is sometimes the same as IOT) - ABRT Abort - IOT IOT instruction - EMT EMT trap - FPE Floating point exception - KILL Killed -# before BUS (linux doesn't really have a BUS, but defines it to UNUSED) - UNUSED Unused - BUS Bus error - SEGV Memory fault - SYS Bad system call - PIPE Broken pipe - ALRM Alarm clock - TERM Terminated - STKFLT Stack fault - IO I/O possible - XCPU CPU time limit exceeded - XFSZ File size limit exceeded - VTALRM Virtual timer expired - PROF Profiling timer expired - WINCH Window size change - LOST File lock lost - USR1 User defined signal 1 - USR2 User defined signal 2 - PWR Power-fail/Restart - POLL Pollable event occurred - STOP Stopped (signal) - TSTP Stopped - CONT Continued -# before CLD (CHLD is posix and CHLD is sometimes the same as CLD) - CHLD Child exited - CLD Child exited - TTIN Stopped (tty input) - TTOU Stopped (tty output) - INFO Information request - URG Urgent I/O condition -# Solaris (svr4?) signals - WAITING No runnable LWPs - LWP Inter-LWP signal - FREEZE Checkpoint freeze - THAW Checkpoint thaw - CANCEL Thread cancellation diff --git a/bin/ksh/siglist.sh b/bin/ksh/siglist.sh deleted file mode 100755 index e5d708405..000000000 --- a/bin/ksh/siglist.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/sh -# $NetBSD: siglist.sh,v 1.9 2011/01/23 17:11:55 hauke Exp $ -# -# Script to generate a sorted, complete list of signals, suitable -# for inclusion in trap.c as array initializer. -# - -set -e - -: ${AWK:=awk} -: ${SED:=sed} - -in=tmpi$$.c -out=tmpo$$.c -ecode=1 -trapsigs='0 1 2 13 15' -trap 'rm -f $in $out; trap 0; exit $ecode' $trapsigs - -CPP="${1-cc -E}" - -# The trap here to make up for a bug in bash (1.14.3(1)) that calls the trap -(trap $trapsigs; - echo '#include "sh.h"'; - echo ' { QwErTy SIGNALS , "DUMMY" , "hook for number of signals" },'; - ${SED} -e '/^[ ]*#/d' -e 's/^[ ]*\([^ ][^ ]*\)[ ][ ]*\(.*[^ ]\)[ ]*$/#ifdef SIG\1\ - { QwErTy .signal = SIG\1 , .name = "\1", .mess = "\2" },\ -#endif/') > $in -$CPP $in > $out -${SED} -n 's/{ QwErTy/{/p' < $out | ${AWK} '{print NR, $0}' | sort -k 5n -k 1n | - ${SED} 's/^[0-9]* //' | - ${AWK} 'BEGIN { last=0; nsigs=0; } - { - if ($4 ~ /^[0-9][0-9]*$/ && $5 == ",") { - n = $4; - if (n > 0 && n != last) { - while (++last < n) { - printf "\t{ .signal = %d , .name = NULL, .mess = `Signal %d` } ,\n", last, last; - } - print; - } - } - }' | - tr '`' '"' | grep -v '"DUMMY"' -ecode=0 diff --git a/bin/ksh/syn.c b/bin/ksh/syn.c deleted file mode 100644 index 01cc8ed16..000000000 --- a/bin/ksh/syn.c +++ /dev/null @@ -1,958 +0,0 @@ -/* $NetBSD: syn.c,v 1.9 2006/10/16 00:07:32 christos Exp $ */ - -/* - * shell parser (C version) - */ -#include - -#ifndef lint -__RCSID("$NetBSD: syn.c,v 1.9 2006/10/16 00:07:32 christos Exp $"); -#endif - - -#include "sh.h" -#include "c_test.h" -#include - -struct nesting_state { - int start_token; /* token than began nesting (eg, FOR) */ - int start_line; /* line nesting began on */ -}; - -static void yyparse ARGS((void)); -static struct op *pipeline ARGS((int cf)); -static struct op *andor ARGS((void)); -static struct op *c_list ARGS((int multi)); -static struct ioword *synio ARGS((int cf)); -static void musthave ARGS((int c, int cf)); -static struct op *nested ARGS((int type, int smark, int emark)); -static struct op *get_command ARGS((int cf)); -static struct op *dogroup ARGS((void)); -static struct op *thenpart ARGS((void)); -static struct op *elsepart ARGS((void)); -static struct op *caselist ARGS((void)); -static struct op *casepart ARGS((int endtok)); -static struct op *function_body ARGS((char *name, int ksh_func)); -static char ** wordlist ARGS((void)); -static struct op *block ARGS((int type, struct op *t1, struct op *t2, - char **wp)); -static struct op *newtp ARGS((int type)); -static void syntaxerr ARGS((const char *what)) - GCC_FUNC_ATTR(noreturn); -static void nesting_push ARGS((struct nesting_state *save, int tok)); -static void nesting_pop ARGS((struct nesting_state *saved)); -static int assign_command ARGS((char *s)); -static int inalias ARGS((struct source *s)); -#ifdef KSH -static int dbtestp_isa ARGS((Test_env *te, Test_meta meta)); -static const char *dbtestp_getopnd ARGS((Test_env *te, Test_op op, - int do_eval)); -static int dbtestp_eval ARGS((Test_env *te, Test_op op, const char *opnd1, - const char *opnd2, int do_eval)); -static void dbtestp_error ARGS((Test_env *te, int offset, const char *msg)); -#endif /* KSH */ - -static struct op *outtree; /* yyparse output */ - -static struct nesting_state nesting; /* \n changed to ; */ - -static int reject; /* token(cf) gets symbol again */ -static int symbol; /* yylex value */ - -#define REJECT (reject = 1) -#define ACCEPT (reject = 0) -#define token(cf) \ - ((reject) ? (ACCEPT, symbol) : (symbol = yylex(cf))) -#define tpeek(cf) \ - ((reject) ? (symbol) : (REJECT, symbol = yylex(cf))) - -static void -yyparse() -{ - int c; - - ACCEPT; - - outtree = c_list(source->type == SSTRING); - c = tpeek(0); - if (c == 0 && !outtree) - outtree = newtp(TEOF); - else if (c != '\n' && c != 0) - syntaxerr((char *) 0); -} - -static struct op * -pipeline(cf) - int cf; -{ - register struct op *t, *p, *tl = NULL; - - t = get_command(cf); - if (t != NULL) { - while (token(0) == '|') { - if ((p = get_command(CONTIN)) == NULL) - syntaxerr((char *) 0); - if (tl == NULL) - t = tl = block(TPIPE, t, p, NOWORDS); - else - tl = tl->right = block(TPIPE, tl->right, p, NOWORDS); - } - REJECT; - } - return (t); -} - -static struct op * -andor() -{ - register struct op *t, *p; - register int c; - - t = pipeline(0); - if (t != NULL) { - while ((c = token(0)) == LOGAND || c == LOGOR) { - if ((p = pipeline(CONTIN)) == NULL) - syntaxerr((char *) 0); - t = block(c == LOGAND? TAND: TOR, t, p, NOWORDS); - } - REJECT; - } - return (t); -} - -static struct op * -c_list(multi) - int multi; -{ - register struct op *t = NULL, *p, *tl = NULL; - register int c; - int have_sep; - - while (1) { - p = andor(); - /* Token has always been read/rejected at this point, so - * we don't worry about what flags to pass token() - */ - c = token(0); - have_sep = 1; - if (c == '\n' && (multi || inalias(source))) { - if (!p) /* ignore blank lines */ - continue; - } else if (!p) - break; - else if (c == '&' || c == COPROC) - p = block(c == '&' ? TASYNC : TCOPROC, - p, NOBLOCK, NOWORDS); - else if (c != ';') - have_sep = 0; - if (!t) - t = p; - else if (!tl) - t = tl = block(TLIST, t, p, NOWORDS); - else - tl = tl->right = block(TLIST, tl->right, p, NOWORDS); - if (!have_sep) - break; - } - REJECT; - return t; -} - -static struct ioword * -synio(cf) - int cf; -{ - register struct ioword *iop; - int ishere; - - if (tpeek(cf) != REDIR) - return NULL; - ACCEPT; - iop = yylval.iop; - ishere = (iop->flag&IOTYPE) == IOHERE; - musthave(LWORD, ishere ? HEREDELIM : 0); - if (ishere) { - iop->delim = yylval.cp; - if (*ident != 0) /* unquoted */ - iop->flag |= IOEVAL; - if (herep >= &heres[HERES]) - yyerror("too many <<'s\n"); - *herep++ = iop; - } else - iop->name = yylval.cp; - return iop; -} - -static void -musthave(c, cf) - int c, cf; -{ - if ((token(cf)) != c) - syntaxerr((char *) 0); -} - -static struct op * -nested(type, smark, emark) - int type, smark, emark; -{ - register struct op *t; - struct nesting_state old_nesting; - - nesting_push(&old_nesting, smark); - t = c_list(TRUE); - musthave(emark, KEYWORD|ALIAS); - nesting_pop(&old_nesting); - return (block(type, t, NOBLOCK, NOWORDS)); -} - -static struct op * -get_command(cf) - int cf; -{ - register struct op *t; - register int c, iopn = 0, syniocf; - struct ioword *iop, **iops; - XPtrV args, vars; - struct nesting_state old_nesting; - - iops = (struct ioword **) alloc(sizeofN(struct ioword *, NUFILE+1), - ATEMP); - XPinit(args, 16); - XPinit(vars, 16); - - syniocf = KEYWORD|ALIAS; - switch (c = token(cf|KEYWORD|ALIAS|VARASN)) { - default: - REJECT; - afree((void*) iops, ATEMP); - XPfree(args); - XPfree(vars); - return NULL; /* empty line */ - - case LWORD: - case REDIR: - REJECT; - syniocf &= ~(KEYWORD|ALIAS); - t = newtp(TCOM); - t->lineno = source->line; - while (1) { - cf = (t->u.evalflags ? ARRAYVAR : 0) - | (XPsize(args) == 0 ? ALIAS|VARASN : CMDWORD); - switch (tpeek(cf)) { - case REDIR: - if (iopn >= NUFILE) - yyerror("too many redirections\n"); - iops[iopn++] = synio(cf); - break; - - case LWORD: - ACCEPT; - /* the iopn == 0 and XPsize(vars) == 0 are - * dubious but at&t ksh acts this way - */ - if (iopn == 0 && XPsize(vars) == 0 - && XPsize(args) == 0 - && assign_command(ident)) - t->u.evalflags = DOVACHECK; - if ((XPsize(args) == 0 || Flag(FKEYWORD)) - && is_wdvarassign(yylval.cp)) - XPput(vars, yylval.cp); - else - XPput(args, yylval.cp); - break; - - case '(': - /* Check for "> foo (echo hi)", which at&t ksh - * allows (not POSIX, but not disallowed) - */ - afree(t, ATEMP); - if (XPsize(args) == 0 && XPsize(vars) == 0) { - ACCEPT; - goto Subshell; - } - /* Must be a function */ - if (iopn != 0 || XPsize(args) != 1 - || XPsize(vars) != 0) - syntaxerr((char *) 0); - ACCEPT; - /*(*/ - musthave(')', 0); - t = function_body(XPptrv(args)[0], FALSE); - goto Leave; - - default: - goto Leave; - } - } - Leave: - break; - - Subshell: - case '(': - t = nested(TPAREN, '(', ')'); - break; - - case '{': /*}*/ - t = nested(TBRACE, '{', '}'); - break; - -#ifdef KSH - case MDPAREN: - { - static const char let_cmd[] = { CHAR, 'l', CHAR, 'e', - CHAR, 't', EOS }; - /* Leave KEYWORD in syniocf (allow if (( 1 )) then ...) */ - t = newtp(TCOM); - t->lineno = source->line; - ACCEPT; - XPput(args, wdcopy(let_cmd, ATEMP)); - musthave(LWORD,LETEXPR); - XPput(args, yylval.cp); - break; - } -#endif /* KSH */ - -#ifdef KSH - case DBRACKET: /* [[ .. ]] */ - /* Leave KEYWORD in syniocf (allow if [[ -n 1 ]] then ...) */ - t = newtp(TDBRACKET); - ACCEPT; - { - Test_env te; - - te.flags = TEF_DBRACKET; - te.pos.av = &args; - te.isa = dbtestp_isa; - te.getopnd = dbtestp_getopnd; - te.eval = dbtestp_eval; - te.error = dbtestp_error; - - test_parse(&te); - } - break; -#endif /* KSH */ - - case FOR: - case SELECT: - t = newtp((c == FOR) ? TFOR : TSELECT); - musthave(LWORD, ARRAYVAR); - if (!is_wdvarname(yylval.cp, TRUE)) - yyerror("%s: bad identifier\n", - c == FOR ? "for" : "select"); - t->str = str_save(ident, ATEMP); - nesting_push(&old_nesting, c); - t->vars = wordlist(); - t->left = dogroup(); - nesting_pop(&old_nesting); - break; - - case WHILE: - case UNTIL: - nesting_push(&old_nesting, c); - t = newtp((c == WHILE) ? TWHILE : TUNTIL); - t->left = c_list(TRUE); - t->right = dogroup(); - nesting_pop(&old_nesting); - break; - - case CASE: - t = newtp(TCASE); - musthave(LWORD, 0); - t->str = yylval.cp; - nesting_push(&old_nesting, c); - t->left = caselist(); - nesting_pop(&old_nesting); - break; - - case IF: - nesting_push(&old_nesting, c); - t = newtp(TIF); - t->left = c_list(TRUE); - t->right = thenpart(); - musthave(FI, KEYWORD|ALIAS); - nesting_pop(&old_nesting); - break; - - case BANG: - syniocf &= ~(KEYWORD|ALIAS); - t = pipeline(0); - if (t == (struct op *) 0) - syntaxerr((char *) 0); - t = block(TBANG, NOBLOCK, t, NOWORDS); - break; - - case TIME: - syniocf &= ~(KEYWORD|ALIAS); - t = pipeline(0); - t = block(TTIME, t, NOBLOCK, NOWORDS); - break; - - case FUNCTION: - musthave(LWORD, 0); - t = function_body(yylval.cp, TRUE); - break; - } - - while ((iop = synio(syniocf)) != NULL) { - if (iopn >= NUFILE) - yyerror("too many redirections\n"); - iops[iopn++] = iop; - } - - if (iopn == 0) { - afree((void*) iops, ATEMP); - t->ioact = NULL; - } else { - iops[iopn++] = NULL; - iops = (struct ioword **) aresize((void*) iops, - sizeofN(struct ioword *, iopn), ATEMP); - t->ioact = iops; - } - - if (t->type == TCOM || t->type == TDBRACKET) { - XPput(args, NULL); - t->args = (char **) XPclose(args); - XPput(vars, NULL); - t->vars = (char **) XPclose(vars); - } else { - XPfree(args); - XPfree(vars); - } - - return t; -} - -static struct op * -dogroup() -{ - register int c; - register struct op *list; - - c = token(CONTIN|KEYWORD|ALIAS); - /* A {...} can be used instead of do...done for for/select loops - * but not for while/until loops - we don't need to check if it - * is a while loop because it would have been parsed as part of - * the conditional command list... - */ - if (c == DO) - c = DONE; - else if (c == '{') - c = '}'; - else - syntaxerr((char *) 0); - list = c_list(TRUE); - musthave(c, KEYWORD|ALIAS); - return list; -} - -static struct op * -thenpart() -{ - register struct op *t; - - musthave(THEN, KEYWORD|ALIAS); - t = newtp(0); - t->left = c_list(TRUE); - if (t->left == NULL) - syntaxerr((char *) 0); - t->right = elsepart(); - return (t); -} - -static struct op * -elsepart() -{ - register struct op *t; - - switch (token(KEYWORD|ALIAS|VARASN)) { - case ELSE: - if ((t = c_list(TRUE)) == NULL) - syntaxerr((char *) 0); - return (t); - - case ELIF: - t = newtp(TELIF); - t->left = c_list(TRUE); - t->right = thenpart(); - return (t); - - default: - REJECT; - } - return NULL; -} - -static struct op * -caselist() -{ - register struct op *t, *tl; - int c; - - c = token(CONTIN|KEYWORD|ALIAS); - /* A {...} can be used instead of in...esac for case statements */ - if (c == IN) - c = ESAC; - else if (c == '{') - c = '}'; - else - syntaxerr((char *) 0); - t = tl = NULL; - while ((tpeek(CONTIN|KEYWORD|ESACONLY)) != c) { /* no ALIAS here */ - struct op *tc = casepart(c); - if (tl == NULL) - t = tl = tc, tl->right = NULL; - else - tl->right = tc, tl = tc; - } - musthave(c, KEYWORD|ALIAS); - return (t); -} - -static struct op * -casepart(endtok) - int endtok; -{ - register struct op *t; - register int c; - XPtrV ptns; - - XPinit(ptns, 16); - t = newtp(TPAT); - c = token(CONTIN|KEYWORD); /* no ALIAS here */ - if (c != '(') - REJECT; - do { - musthave(LWORD, 0); - XPput(ptns, yylval.cp); - } while ((c = token(0)) == '|'); - REJECT; - XPput(ptns, NULL); - t->vars = (char **) XPclose(ptns); - musthave(')', 0); - - t->left = c_list(TRUE); - /* Note: Posix requires the ;; */ - if ((tpeek(CONTIN|KEYWORD|ALIAS)) != endtok) - musthave(BREAK, CONTIN|KEYWORD|ALIAS); - return (t); -} - -static struct op * -function_body(name, ksh_func) - char *name; - int ksh_func; /* function foo { ... } vs foo() { .. } */ -{ - char *sname, *p; - struct op *t; - int old_func_parse; - - sname = wdstrip(name); - /* Check for valid characters in name. posix and ksh93 say only - * allow [a-zA-Z_0-9] but this allows more as old pdksh's have - * allowed more (the following were never allowed: - * nul space nl tab $ ' " \ ` ( ) & | ; = < > - * C_QUOTE covers all but = and adds # [ ? *) - */ - for (p = sname; *p; p++) - if (ctype(*p, C_QUOTE) || *p == '=') - yyerror("%s: invalid function name\n", sname); - - t = newtp(TFUNCT); - t->str = sname; - t->u.ksh_func = ksh_func; - t->lineno = source->line; - - /* Note that POSIX allows only compound statements after foo(), sh and - * at&t ksh allow any command, go with the later since it shouldn't - * break anything. However, for function foo, at&t ksh only accepts - * an open-brace. - */ - if (ksh_func) { - musthave('{', CONTIN|KEYWORD|ALIAS); /* } */ - REJECT; - } - - old_func_parse = e->flags & EF_FUNC_PARSE; - e->flags |= EF_FUNC_PARSE; - if ((t->left = get_command(CONTIN)) == (struct op *) 0) { - /* - * Probably something like foo() followed by eof or ;. - * This is accepted by sh and ksh88. - * To make "typeset -f foo" work reliably (so its output can - * be used as input), we pretend there is a colon here. - */ - t->left = newtp(TCOM); - t->left->args = (char **) alloc(sizeof(char *) * 2, ATEMP); - t->left->args[0] = alloc(sizeof(char) * 3, ATEMP); - t->left->args[0][0] = CHAR; - t->left->args[0][1] = ':'; - t->left->args[0][2] = EOS; - t->left->args[1] = (char *) 0; - t->left->vars = (char **) alloc(sizeof(char *), ATEMP); - t->left->vars[0] = (char *) 0; - t->left->lineno = 1; - } - if (!old_func_parse) - e->flags &= ~EF_FUNC_PARSE; - - return t; -} - -static char ** -wordlist() -{ - register int c; - XPtrV args; - - XPinit(args, 16); - /* Posix does not do alias expansion here... */ - if ((c = token(CONTIN|KEYWORD|ALIAS)) != IN) { - if (c != ';') /* non-POSIX, but at&t ksh accepts a ; here */ - REJECT; - return NULL; - } - while ((c = token(0)) == LWORD) - XPput(args, yylval.cp); - if (c != '\n' && c != ';') - syntaxerr((char *) 0); - if (XPsize(args) == 0) { - XPfree(args); - return NULL; - } else { - XPput(args, NULL); - return (char **) XPclose(args); - } -} - -/* - * supporting functions - */ - -static struct op * -block(type, t1, t2, wp) - int type; - struct op *t1, *t2; - char **wp; -{ - register struct op *t; - - t = newtp(type); - t->left = t1; - t->right = t2; - t->vars = wp; - return (t); -} - -const struct tokeninfo { - const char *name; - short val; - short reserved; -} tokentab[] = { - /* Reserved words */ - { "if", IF, TRUE }, - { "then", THEN, TRUE }, - { "else", ELSE, TRUE }, - { "elif", ELIF, TRUE }, - { "fi", FI, TRUE }, - { "case", CASE, TRUE }, - { "esac", ESAC, TRUE }, - { "for", FOR, TRUE }, -#ifdef KSH - { "select", SELECT, TRUE }, -#endif /* KSH */ - { "while", WHILE, TRUE }, - { "until", UNTIL, TRUE }, - { "do", DO, TRUE }, - { "done", DONE, TRUE }, - { "in", IN, TRUE }, - { "function", FUNCTION, TRUE }, - { "time", TIME, TRUE }, - { "{", '{', TRUE }, - { "}", '}', TRUE }, - { "!", BANG, TRUE }, -#ifdef KSH - { "[[", DBRACKET, TRUE }, -#endif /* KSH */ - /* Lexical tokens (0[EOF], LWORD and REDIR handled specially) */ - { "&&", LOGAND, FALSE }, - { "||", LOGOR, FALSE }, - { ";;", BREAK, FALSE }, -#ifdef KSH - { "((", MDPAREN, FALSE }, - { "|&", COPROC, FALSE }, -#endif /* KSH */ - /* and some special cases... */ - { "newline", '\n', FALSE }, - { .name = NULL } -}; - -void -initkeywords() -{ - register struct tokeninfo const *tt; - register struct tbl *p; - - tinit(&keywords, APERM, 32); /* must be 2^n (currently 20 keywords) */ - for (tt = tokentab; tt->name; tt++) { - if (tt->reserved) { - p = tenter(&keywords, tt->name, hash(tt->name)); - p->flag |= DEFINED|ISSET; - p->type = CKEYWD; - p->val.i = tt->val; - } - } -} - -static void -syntaxerr(what) - const char *what; -{ - char redir[6]; /* 2<<- is the longest redirection, I think */ - const char *s; - struct tokeninfo const *tt; - int c; - - if (!what) - what = "unexpected"; - REJECT; - c = token(0); - Again: - switch (c) { - case 0: - if (nesting.start_token) { - c = nesting.start_token; - source->errline = nesting.start_line; - what = "unmatched"; - goto Again; - } - /* don't quote the EOF */ - yyerror("syntax error: unexpected EOF\n"); - /*NOTREACHED*/ - - case LWORD: - s = snptreef((char *) 0, 32, "%S", yylval.cp); - break; - - case REDIR: - s = snptreef(redir, sizeof(redir), "%R", yylval.iop); - break; - - default: - for (tt = tokentab; tt->name; tt++) - if (tt->val == c) - break; - if (tt->name) - s = tt->name; - else { - if (c > 0 && c < 256) { - redir[0] = c; - redir[1] = '\0'; - } else - shf_snprintf(redir, sizeof(redir), - "?%d", c); - s = redir; - } - } - yyerror("syntax error: `%s' %s\n", s, what); -} - -static void -nesting_push(save, tok) - struct nesting_state *save; - int tok; -{ - *save = nesting; - nesting.start_token = tok; - nesting.start_line = source->line; -} - -static void -nesting_pop(saved) - struct nesting_state *saved; -{ - nesting = *saved; -} - -static struct op * -newtp(type) - int type; -{ - register struct op *t; - - t = (struct op *) alloc(sizeof(*t), ATEMP); - t->type = type; - t->u.evalflags = 0; - t->args = t->vars = NULL; - t->ioact = NULL; - t->left = t->right = NULL; - t->str = NULL; - return (t); -} - -struct op * -compile(s) - Source *s; -{ - nesting.start_token = 0; - nesting.start_line = 0; - herep = heres; - source = s; - yyparse(); - return outtree; -} - -/* This kludge exists to take care of sh/at&t ksh oddity in which - * the arguments of alias/export/readonly/typeset have no field - * splitting, file globbing, or (normal) tilde expansion done. - * at&t ksh seems to do something similar to this since - * $ touch a=a; typeset a=[ab]; echo "$a" - * a=[ab] - * $ x=typeset; $x a=[ab]; echo "$a" - * a=a - * $ - */ -static int -assign_command(s) - char *s; -{ - char c = *s; - - if (Flag(FPOSIX) || !*s) - return 0; - return (c == 'a' && strcmp(s, "alias") == 0) - || (c == 'e' && strcmp(s, "export") == 0) - || (c == 'r' && strcmp(s, "readonly") == 0) - || (c == 't' && strcmp(s, "typeset") == 0); -} - -/* Check if we are in the middle of reading an alias */ -static int -inalias(s) - struct source *s; -{ - for (; s && s->type == SALIAS; s = s->next) - if (!(s->flags & SF_ALIASEND)) - return 1; - return 0; -} - - -#ifdef KSH -/* Order important - indexed by Test_meta values - * Note that ||, &&, ( and ) can't appear in as unquoted strings - * in normal shell input, so these can be interpreted unambiguously - * in the evaluation pass. - */ -static const char dbtest_or[] = { CHAR, '|', CHAR, '|', EOS }; -static const char dbtest_and[] = { CHAR, '&', CHAR, '&', EOS }; -static const char dbtest_not[] = { CHAR, '!', EOS }; -static const char dbtest_oparen[] = { CHAR, '(', EOS }; -static const char dbtest_cparen[] = { CHAR, ')', EOS }; -const char *const dbtest_tokens[] = { - dbtest_or, dbtest_and, dbtest_not, - dbtest_oparen, dbtest_cparen - }; -const char db_close[] = { CHAR, ']', CHAR, ']', EOS }; -const char db_lthan[] = { CHAR, '<', EOS }; -const char db_gthan[] = { CHAR, '>', EOS }; - -/* Test if the current token is a whatever. Accepts the current token if - * it is. Returns 0 if it is not, non-zero if it is (in the case of - * TM_UNOP and TM_BINOP, the returned value is a Test_op). - */ -static int -dbtestp_isa(te, meta) - Test_env *te; - Test_meta meta; -{ - int c = tpeek(ARRAYVAR | (meta == TM_BINOP ? 0 : CONTIN)); - int uqword = 0; - char *save = (char *) 0; - int ret = 0; - - /* unquoted word? */ - uqword = c == LWORD && *ident; - - if (meta == TM_OR) - ret = c == LOGOR; - else if (meta == TM_AND) - ret = c == LOGAND; - else if (meta == TM_NOT) - ret = uqword && strcmp(yylval.cp, dbtest_tokens[(int) TM_NOT]) == 0; - else if (meta == TM_OPAREN) - ret = c == '(' /*)*/; - else if (meta == TM_CPAREN) - ret = c == /*(*/ ')'; - else if (meta == TM_UNOP || meta == TM_BINOP) { - if (meta == TM_BINOP && c == REDIR - && (yylval.iop->flag == IOREAD - || yylval.iop->flag == IOWRITE)) - { - ret = 1; - save = wdcopy(yylval.iop->flag == IOREAD ? - db_lthan : db_gthan, ATEMP); - } else if (uqword && (ret = (int) test_isop(te, meta, ident))) - save = yylval.cp; - } else /* meta == TM_END */ - ret = uqword && strcmp(yylval.cp, db_close) == 0; - if (ret) { - ACCEPT; - if (meta != TM_END) { - if (!save) { - assert(/* meta >= 0 && */ - meta < sizeof(dbtest_tokens) / - sizeof(dbtest_tokens[0])); - save = wdcopy(dbtest_tokens[(int) meta], ATEMP); - } - XPput(*te->pos.av, save); - } - } - return ret; -} - -static const char * -dbtestp_getopnd(te, op, do_eval) - Test_env *te; - Test_op op; - int do_eval; -{ - int c = tpeek(ARRAYVAR); - - if (c != LWORD) - return (const char *) 0; - - ACCEPT; - XPput(*te->pos.av, yylval.cp); - - return null; -} - -static int -dbtestp_eval(te, op, opnd1, opnd2, do_eval) - Test_env *te; - Test_op op; - const char *opnd1; - const char *opnd2; - int do_eval; -{ - return 1; -} - -static void -dbtestp_error(te, offset, msg) - Test_env *te; - int offset; - const char *msg; -{ - te->flags |= TEF_ERROR; - - if (offset < 0) { - REJECT; - /* Kludgy to say the least... */ - symbol = LWORD; - yylval.cp = *(XPptrv(*te->pos.av) + XPsize(*te->pos.av) - + offset); - } - syntaxerr(msg); -} -#endif /* KSH */ diff --git a/bin/ksh/table.c b/bin/ksh/table.c deleted file mode 100644 index 025b56d27..000000000 --- a/bin/ksh/table.c +++ /dev/null @@ -1,247 +0,0 @@ -/* $NetBSD: table.c,v 1.4 2003/06/23 11:39:04 agc Exp $ */ - -/* - * dynamic hashed associative table for commands and variables - */ -#include - -#ifndef lint -__RCSID("$NetBSD: table.c,v 1.4 2003/06/23 11:39:04 agc Exp $"); -#endif - - -#include "sh.h" - -#define INIT_TBLS 8 /* initial table size (power of 2) */ - -static void texpand ARGS((struct table *tp, int nsize)); -static int tnamecmp ARGS((void *p1, void *p2)); - - -unsigned int -hash(n) - register const char * n; -{ - register unsigned int h = 0; - - while (*n != '\0') - h = 2*h + *n++; - return h * 32821; /* scatter bits */ -} - -void -tinit(tp, ap, tsize) - register struct table *tp; - register Area *ap; - int tsize; -{ - tp->areap = ap; - tp->tbls = NULL; - tp->size = tp->nfree = 0; - if (tsize) - texpand(tp, tsize); -} - -static void -texpand(tp, nsize) - register struct table *tp; - int nsize; -{ - register int i; - register struct tbl *tblp, **p; - register struct tbl **ntblp, **otblp = tp->tbls; - int osize = tp->size; - - ntblp = (struct tbl**) alloc(sizeofN(struct tbl *, nsize), tp->areap); - for (i = 0; i < nsize; i++) - ntblp[i] = NULL; - tp->size = nsize; - tp->nfree = 8*nsize/10; /* table can get 80% full */ - tp->tbls = ntblp; - if (otblp == NULL) - return; - for (i = 0; i < osize; i++) { - if ((tblp = otblp[i]) != NULL) { - if ((tblp->flag&DEFINED)) { - for (p = &ntblp[hash(tblp->name) - & (tp->size-1)]; - *p != NULL; p--) - if (p == ntblp) /* wrap */ - p += tp->size; - *p = tblp; - tp->nfree--; - } else if (!(tblp->flag & FINUSE)) { - afree((void*)tblp, tp->areap); - } - } - } - afree((void*)otblp, tp->areap); -} - -struct tbl * -tsearch(tp, n, h) - register struct table *tp; /* table */ - register const char *n; /* name to enter */ - unsigned int h; /* hash(n) */ -{ - register struct tbl **pp, *p; - - if (tp->size == 0) - return NULL; - - /* search for name in hashed table */ - for (pp = &tp->tbls[h & (tp->size-1)]; (p = *pp) != NULL; pp--) { - if (*p->name == *n && strcmp(p->name, n) == 0 - && (p->flag&DEFINED)) - return p; - if (pp == tp->tbls) /* wrap */ - pp += tp->size; - } - - return NULL; -} - -struct tbl * -tenter(tp, n, h) - register struct table *tp; /* table */ - register const char *n; /* name to enter */ - unsigned int h; /* hash(n) */ -{ - register struct tbl **pp, *p; - register int len; - - if (tp->size == 0) - texpand(tp, INIT_TBLS); - Search: - /* search for name in hashed table */ - for (pp = &tp->tbls[h & (tp->size-1)]; (p = *pp) != NULL; pp--) { - if (*p->name == *n && strcmp(p->name, n) == 0) - return p; /* found */ - if (pp == tp->tbls) /* wrap */ - pp += tp->size; - } - - if (tp->nfree <= 0) { /* too full */ - texpand(tp, 2*tp->size); - goto Search; - } - - /* create new tbl entry */ - len = strlen(n) + 1; - p = (struct tbl *) alloc(offsetof(struct tbl, name[0]) + len, - tp->areap); - p->flag = 0; - p->type = 0; - p->areap = tp->areap; - p->u2.field = 0; - p->u.array = (struct tbl *)0; - memcpy(p->name, n, len); - - /* enter in tp->tbls */ - tp->nfree--; - *pp = p; - return p; -} - -void -tdelete(p) - register struct tbl *p; -{ - p->flag = 0; -} - -void -twalk(ts, tp) - struct tstate *ts; - struct table *tp; -{ - ts->left = tp->size; - ts->next = tp->tbls; -} - -struct tbl * -tnext(ts) - struct tstate *ts; -{ - while (--ts->left >= 0) { - struct tbl *p = *ts->next++; - if (p != NULL && (p->flag&DEFINED)) - return p; - } - return NULL; -} - -static int -tnamecmp(p1, p2) - void *p1, *p2; -{ - return strcmp(((struct tbl *)p1)->name, ((struct tbl *)p2)->name); -} - -struct tbl ** -tsort(tp) - register struct table *tp; -{ - register int i; - register struct tbl **p, **sp, **dp; - - p = (struct tbl **)alloc(sizeofN(struct tbl *, tp->size+1), ATEMP); - sp = tp->tbls; /* source */ - dp = p; /* dest */ - for (i = 0; i < tp->size; i++) - if ((*dp = *sp++) != NULL && (((*dp)->flag&DEFINED) || - ((*dp)->flag&ARRAY))) - dp++; - i = dp - p; - qsortp((void**)p, (size_t)i, tnamecmp); - p[i] = NULL; - return p; -} - -#ifdef PERF_DEBUG /* performance debugging */ - -void tprintinfo ARGS((struct table *tp)); - -void -tprintinfo(tp) - struct table *tp; -{ - struct tbl *te; - char *n; - unsigned int h; - int ncmp; - int totncmp = 0, maxncmp = 0; - int nentries = 0; - struct tstate ts; - - shellf("table size %d, nfree %d\n", tp->size, tp->nfree); - shellf(" Ncmp name\n"); - twalk(&ts, tp); - while ((te = tnext(&ts))) { - register struct tbl **pp, *p; - - h = hash(n = te->name); - ncmp = 0; - - /* taken from tsearch() and added counter */ - for (pp = &tp->tbls[h & (tp->size-1)]; (p = *pp); pp--) { - ncmp++; - if (*p->name == *n && strcmp(p->name, n) == 0 - && (p->flag&DEFINED)) - break; /* return p; */ - if (pp == tp->tbls) /* wrap */ - pp += tp->size; - } - shellf(" %4d %s\n", ncmp, n); - totncmp += ncmp; - nentries++; - if (ncmp > maxncmp) - maxncmp = ncmp; - } - if (nentries) - shellf(" %d entries, worst ncmp %d, avg ncmp %d.%02d\n", - nentries, maxncmp, - totncmp / nentries, - (totncmp % nentries) * 100 / nentries); -} -#endif /* PERF_DEBUG */ diff --git a/bin/ksh/table.h b/bin/ksh/table.h deleted file mode 100644 index 9dc42c851..000000000 --- a/bin/ksh/table.h +++ /dev/null @@ -1,181 +0,0 @@ -/* $NetBSD: table.h,v 1.3 1999/10/20 15:10:00 hubertf Exp $ */ - -/* - * generic hashed associative table for commands and variables. - */ - -struct table { - Area *areap; /* area to allocate entries */ - short size, nfree; /* hash size (always 2^^n), free entries */ - struct tbl **tbls; /* hashed table items */ -}; - -struct tbl { /* table item */ - Tflag flag; /* flags */ - int type; /* command type (see below), base (if INTEGER), - * or offset from val.s of value (if EXPORT) */ - Area *areap; /* area to allocate from */ - union { - char *s; /* string */ - long i; /* integer */ - int (*f) ARGS((char **)); /* int function */ - struct op *t; /* "function" tree */ - } val; /* value */ - int index; /* index for an array */ - union { - int field; /* field with for -L/-R/-Z */ - int errno_; /* CEXEC/CTALIAS */ - } u2; - union { - struct tbl *array; /* array values */ - char *fpath; /* temporary path to undef function */ - } u; - char name[4]; /* name -- variable length */ -}; - -/* common flag bits */ -#define ALLOC BIT(0) /* val.s has been allocated */ -#define DEFINED BIT(1) /* is defined in block */ -#define ISSET BIT(2) /* has value, vp->val.[si] */ -#define EXPORT BIT(3) /* exported variable/function */ -#define TRACE BIT(4) /* var: user flagged, func: execution tracing */ -/* (start non-common flags at 8) */ -/* flag bits used for variables */ -#define SPECIAL BIT(8) /* PATH, IFS, SECONDS, etc */ -#define INTEGER BIT(9) /* val.i contains integer value */ -#define RDONLY BIT(10) /* read-only variable */ -#define LOCAL BIT(11) /* for local typeset() */ -#define ARRAY BIT(13) /* array */ -#define LJUST BIT(14) /* left justify */ -#define RJUST BIT(15) /* right justify */ -#define ZEROFIL BIT(16) /* 0 filled if RJUSTIFY, strip 0s if LJUSTIFY */ -#define LCASEV BIT(17) /* convert to lower case */ -#define UCASEV_AL BIT(18)/* convert to upper case / autoload function */ -#define INT_U BIT(19) /* unsigned integer */ -#define INT_L BIT(20) /* long integer (no-op) */ -#define IMPORT BIT(21) /* flag to typeset(): no arrays, must have = */ -#define LOCAL_COPY BIT(22) /* with LOCAL - copy attrs from existing var */ -#define EXPRINEVAL BIT(23) /* contents currently being evaluated */ -#define EXPRLVALUE BIT(24) /* useable as lvalue (temp flag) */ -/* flag bits used for taliases/builtins/aliases/keywords/functions */ -#define KEEPASN BIT(8) /* keep command assignments (eg, var=x cmd) */ -#define FINUSE BIT(9) /* function being executed */ -#define FDELETE BIT(10) /* function deleted while it was executing */ -#define FKSH BIT(11) /* function defined with function x (vs x()) */ -#define SPEC_BI BIT(12) /* a POSIX special builtin */ -#define REG_BI BIT(13) /* a POSIX regular builtin */ -/* Attributes that can be set by the user (used to decide if an unset param - * should be repoted by set/typeset). Does not include ARRAY or LOCAL. - */ -#define USERATTRIB (EXPORT|INTEGER|RDONLY|LJUST|RJUST|ZEROFIL\ - |LCASEV|UCASEV_AL|INT_U|INT_L) - -/* command types */ -#define CNONE 0 /* undefined */ -#define CSHELL 1 /* built-in */ -#define CFUNC 2 /* function */ -#define CEXEC 4 /* executable command */ -#define CALIAS 5 /* alias */ -#define CKEYWD 6 /* keyword */ -#define CTALIAS 7 /* tracked alias */ - -/* Flags for findcom()/comexec() */ -#define FC_SPECBI BIT(0) /* special builtin */ -#define FC_FUNC BIT(1) /* function builtin */ -#define FC_REGBI BIT(2) /* regular builtin */ -#define FC_UNREGBI BIT(3) /* un-regular builtin (!special,!regular) */ -#define FC_BI (FC_SPECBI|FC_REGBI|FC_UNREGBI) -#define FC_PATH BIT(4) /* do path search */ -#define FC_DEFPATH BIT(5) /* use default path in path search */ - - -#define AF_ARGV_ALLOC 0x1 /* argv[] array allocated */ -#define AF_ARGS_ALLOCED 0x2 /* argument strings allocated */ -#define AI_ARGV(a, i) ((i) == 0 ? (a).argv[0] : (a).argv[(i) - (a).skip]) -#define AI_ARGC(a) ((a).argc_ - (a).skip) - -/* Argument info. Used for $#, $* for shell, functions, includes, etc. */ -struct arg_info { - int flags; /* AF_* */ - char **argv; - int argc_; - int skip; /* first arg is argv[0], second is argv[1 + skip] */ -}; - -/* - * activation record for function blocks - */ -struct block { - Area area; /* area to allocate things */ - /*struct arg_info argi;*/ - char **argv; - int argc; - int flags; /* see BF_* */ - struct table vars; /* local variables */ - struct table funs; /* local functions */ - Getopt getopts_state; -#if 1 - char * error; /* error handler */ - char * exit; /* exit handler */ -#else - Trap error, exit; -#endif - struct block *next; /* enclosing block */ -}; - -/* Values for struct block.flags */ -#define BF_DOGETOPTS BIT(0) /* save/restore getopts state */ - -/* - * Used by twalk() and tnext() routines. - */ -struct tstate { - int left; - struct tbl **next; -}; - - -EXTERN struct table taliases; /* tracked aliases */ -EXTERN struct table builtins; /* built-in commands */ -EXTERN struct table aliases; /* aliases */ -EXTERN struct table keywords; /* keywords */ -EXTERN struct table homedirs; /* homedir() cache */ - -struct builtin { - const char *name; - int (*func) ARGS((char **)); -}; - -/* these really are externs! Look in table.c for them */ -extern const struct builtin shbuiltins [], kshbuiltins []; - -/* var spec values */ -#define V_NONE 0 -#define V_PATH 1 -#define V_IFS 2 -#define V_SECONDS 3 -#define V_OPTIND 4 -#define V_MAIL 5 -#define V_MAILPATH 6 -#define V_MAILCHECK 7 -#define V_RANDOM 8 -#define V_HISTSIZE 9 -#define V_HISTFILE 10 -#define V_VISUAL 11 -#define V_EDITOR 12 -#define V_COLUMNS 13 -#define V_POSIXLY_CORRECT 14 -#define V_TMOUT 15 -#define V_TMPDIR 16 -#define V_LINENO 17 - -/* values for set_prompt() */ -#define PS1 0 /* command */ -#define PS2 1 /* command continuation */ - -EXTERN char *path; /* copy of either PATH or def_path */ -EXTERN const char *def_path; /* path to use if PATH not set */ -EXTERN char *tmpdir; /* TMPDIR value */ -EXTERN const char *prompt; -EXTERN int cur_prompt; /* PS1 or PS2 */ -EXTERN int current_lineno; /* LINENO value */ diff --git a/bin/ksh/trap.c b/bin/ksh/trap.c deleted file mode 100644 index fa212aab5..000000000 --- a/bin/ksh/trap.c +++ /dev/null @@ -1,460 +0,0 @@ -/* $NetBSD: trap.c,v 1.8 2006/10/16 00:07:32 christos Exp $ */ - -/* - * signal handling - */ -#include - -#ifndef lint -__RCSID("$NetBSD: trap.c,v 1.8 2006/10/16 00:07:32 christos Exp $"); -#endif - - -/* Kludge to avoid bogus re-declaration of sigtraps[] error on AIX 3.2.5 */ -#define FROM_TRAP_C -#include "sh.h" - -/* Table is indexed by signal number - * - * The script siglist.sh generates siglist.out, which is a sorted, complete - * list of signals - */ -Trap sigtraps[SIGNALS+1] = { - { .signal = SIGEXIT_, .name = "EXIT", .mess = "Signal 0" }, -#include "siglist.out" /* generated by siglist.sh */ - { .signal = SIGERR_, .name = "ERR", .mess = "Error handler" }, - }; - -static struct sigaction Sigact_ign, Sigact_trap; - -void -inittraps() -{ -#ifdef HAVE_SYS_SIGLIST -# ifndef SYS_SIGLIST_DECLARED - extern char *sys_siglist[]; -# endif - int i; - - /* Use system description, if available, for unknown signals... */ - for (i = 0; i < NSIG; i++) - if (!sigtraps[i].name && sys_siglist[i] && sys_siglist[i][0]) - sigtraps[i].mess = sys_siglist[i]; -#endif /* HAVE_SYS_SIGLIST */ - - sigemptyset(&Sigact_ign.sa_mask); - Sigact_ign.sa_flags = KSH_SA_FLAGS; - Sigact_ign.sa_handler = SIG_IGN; - Sigact_trap = Sigact_ign; - Sigact_trap.sa_handler = trapsig; - - sigtraps[SIGINT].flags |= TF_DFL_INTR | TF_TTY_INTR; - sigtraps[SIGQUIT].flags |= TF_DFL_INTR | TF_TTY_INTR; - sigtraps[SIGTERM].flags |= TF_DFL_INTR;/* not fatal for interactive */ - sigtraps[SIGHUP].flags |= TF_FATAL; - sigtraps[SIGCHLD].flags |= TF_SHELL_USES; - - /* these are always caught so we can clean up any temporary files. */ - setsig(&sigtraps[SIGINT], trapsig, SS_RESTORE_ORIG); - setsig(&sigtraps[SIGQUIT], trapsig, SS_RESTORE_ORIG); - setsig(&sigtraps[SIGTERM], trapsig, SS_RESTORE_ORIG); - setsig(&sigtraps[SIGHUP], trapsig, SS_RESTORE_ORIG); -} - -#ifdef KSH -static RETSIGTYPE alarm_catcher ARGS((int sig)); - -void -alarm_init() -{ - sigtraps[SIGALRM].flags |= TF_SHELL_USES; - setsig(&sigtraps[SIGALRM], alarm_catcher, - SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP); -} - -static RETSIGTYPE -alarm_catcher(sig) - int sig; -{ - int errno_ = errno; - - if (ksh_tmout_state == TMOUT_READING) { - int left = alarm(0); - - if (left == 0) { - ksh_tmout_state = TMOUT_LEAVING; - intrsig = 1; - } else - alarm(left); - } - errno = errno_; - return RETSIGVAL; -} -#endif /* KSH */ - -Trap * -gettrap(name, igncase) - const char *name; - int igncase; -{ - int i; - register Trap *p; - - if (digit(*name)) { - int n; - - if (getn(name, &n) && 0 <= n && n < SIGNALS) - return &sigtraps[n]; - return NULL; - } - for (p = sigtraps, i = SIGNALS+1; --i >= 0; p++) - if (p->name) { - if (igncase) { - if (p->name && (!strcasecmp(p->name, name) || - (strlen(name) > 3 && !strncasecmp("SIG", - p->name, 3) && - !strcasecmp(p->name, name + 3)))) - return p; - } else { - if (p->name && (!strcmp(p->name, name) || - (strlen(name) > 3 && !strncmp("SIG", - p->name, 3) && !strcmp(p->name, name + 3)))) - return p; - } - } - return NULL; -} - -/* - * trap signal handler - */ -RETSIGTYPE -trapsig(i) - int i; -{ - Trap *p = &sigtraps[i]; - int errno_ = errno; - - trap = p->set = 1; - if (p->flags & TF_DFL_INTR) - intrsig = 1; - if ((p->flags & TF_FATAL) && !p->trap) { - fatal_trap = 1; - intrsig = 1; - } - if (p->shtrap) - (*p->shtrap)(i); -#ifdef V7_SIGNALS - if (sigtraps[i].cursig == trapsig) /* this for SIGCHLD,SIGALRM */ - sigaction(i, &Sigact_trap, (struct sigaction *) 0); -#endif /* V7_SIGNALS */ - errno = errno_; - return RETSIGVAL; -} - -/* called when we want to allow the user to ^C out of something - won't - * work if user has trapped SIGINT. - */ -void -intrcheck() -{ - if (intrsig) - runtraps(TF_DFL_INTR|TF_FATAL); -} - -/* called after EINTR to check if a signal with normally causes process - * termination has been received. - */ -int -fatal_trap_check() -{ - int i; - Trap *p; - - /* todo: should check if signal is fatal, not the TF_DFL_INTR flag */ - for (p = sigtraps, i = SIGNALS+1; --i >= 0; p++) - if (p->set && (p->flags & (TF_DFL_INTR|TF_FATAL))) - /* return value is used as an exit code */ - return 128 + p->signal; - return 0; -} - -/* Returns the signal number of any pending traps: ie, a signal which has - * occurred for which a trap has been set or for which the TF_DFL_INTR flag - * is set. - */ -int -trap_pending() -{ - int i; - Trap *p; - - for (p = sigtraps, i = SIGNALS+1; --i >= 0; p++) - if (p->set && ((p->trap && p->trap[0]) - || ((p->flags & (TF_DFL_INTR|TF_FATAL)) - && !p->trap))) - return p->signal; - return 0; -} - -/* - * run any pending traps. If intr is set, only run traps that - * can interrupt commands. - */ -void -runtraps(flag) - int flag; -{ - int i; - register Trap *p; - -#ifdef KSH - if (ksh_tmout_state == TMOUT_LEAVING) { - ksh_tmout_state = TMOUT_EXECUTING; - warningf(FALSE, "timed out waiting for input"); - unwind(LEXIT); - } else - /* XXX: this means the alarm will have no effect if a trap - * is caught after the alarm() was started...not good. - */ - ksh_tmout_state = TMOUT_EXECUTING; -#endif /* KSH */ - if (!flag) - trap = 0; - if (flag & TF_DFL_INTR) - intrsig = 0; - if (flag & TF_FATAL) - fatal_trap = 0; - for (p = sigtraps, i = SIGNALS+1; --i >= 0; p++) - if (p->set && (!flag - || ((p->flags & flag) && p->trap == (char *) 0))) - runtrap(p); -} - -void -runtrap(p) - Trap *p; -{ - int i = p->signal; - char *trapstr = p->trap; - int oexstat; - int UNINITIALIZED(old_changed); - - p->set = 0; - if (trapstr == (char *) 0) { /* SIG_DFL */ - if (p->flags & TF_FATAL) { - /* eg, SIGHUP */ - exstat = 128 + i; - unwind(LLEAVE); - } - if (p->flags & TF_DFL_INTR) { - /* eg, SIGINT, SIGQUIT, SIGTERM, etc. */ - exstat = 128 + i; - unwind(LINTR); - } - return; - } - if (trapstr[0] == '\0') /* SIG_IGN */ - return; - if (i == SIGEXIT_ || i == SIGERR_) { /* avoid recursion on these */ - old_changed = p->flags & TF_CHANGED; - p->flags &= ~TF_CHANGED; - p->trap = (char *) 0; - } - oexstat = exstat; - /* Note: trapstr is fully parsed before anything is executed, thus - * no problem with afree(p->trap) in settrap() while still in use. - */ - command(trapstr); - exstat = oexstat; - if (i == SIGEXIT_ || i == SIGERR_) { - if (p->flags & TF_CHANGED) - /* don't clear TF_CHANGED */ - afree(trapstr, APERM); - else - p->trap = trapstr; - p->flags |= old_changed; - } -} - -/* clear pending traps and reset user's trap handlers; used after fork(2) */ -void -cleartraps() -{ - int i; - Trap *p; - - trap = 0; - intrsig = 0; - fatal_trap = 0; - for (i = SIGNALS+1, p = sigtraps; --i >= 0; p++) { - p->set = 0; - if ((p->flags & TF_USER_SET) && (p->trap && p->trap[0])) - settrap(p, (char *) 0); - } -} - -/* restore signals just before an exec(2) */ -void -restoresigs() -{ - int i; - Trap *p; - - for (i = SIGNALS+1, p = sigtraps; --i >= 0; p++) - if (p->flags & (TF_EXEC_IGN|TF_EXEC_DFL)) - setsig(p, (p->flags & TF_EXEC_IGN) ? SIG_IGN : SIG_DFL, - SS_RESTORE_CURR|SS_FORCE); -} - -void -settrap(p, s) - Trap *p; - char *s; -{ - handler_t f; - - if (p->trap) - afree(p->trap, APERM); - p->flags |= TF_CHANGED|TF_USER_SET; - if (s) { - p->trap = str_save(s, APERM); - f = s[0] ? trapsig : SIG_IGN; - } else { - p->trap = NULL; - f = SIG_DFL; - } - if ((p->flags & (TF_DFL_INTR|TF_FATAL)) && f == SIG_DFL) - f = trapsig; - else if (p->flags & TF_SHELL_USES) { - if (!(p->flags & TF_ORIG_IGN) || Flag(FTALKING)) { - /* do what user wants at exec time */ - p->flags &= ~(TF_EXEC_IGN|TF_EXEC_DFL); - if (f == SIG_IGN) - p->flags |= TF_EXEC_IGN; - else - p->flags |= TF_EXEC_DFL; - } - /* assumes handler already set to what shell wants it - * (normally trapsig, but could be j_sigchld() or SIG_IGN) - */ - return; - } - - /* todo: should we let user know signal is ignored? how? */ - setsig(p, f, SS_RESTORE_CURR|SS_USER); -} - -/* Called by c_print() when writing to a co-process to ensure SIGPIPE won't - * kill shell (unless user catches it and exits) - */ -int -block_pipe() -{ - int restore_dfl = 0; - Trap *p = &sigtraps[SIGPIPE]; - - if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) { - setsig(p, SIG_IGN, SS_RESTORE_CURR); - if (p->flags & TF_ORIG_DFL) - restore_dfl = 1; - } else if (p->cursig == SIG_DFL) { - setsig(p, SIG_IGN, SS_RESTORE_CURR); - restore_dfl = 1; /* restore to SIG_DFL */ - } - return restore_dfl; -} - -/* Called by c_print() to undo whatever block_pipe() did */ -void -restore_pipe(restore_dfl) - int restore_dfl; -{ - if (restore_dfl) - setsig(&sigtraps[SIGPIPE], SIG_DFL, SS_RESTORE_CURR); -} - -/* Set action for a signal. Action may not be set if original - * action was SIG_IGN, depending on the value of flags and - * FTALKING. - */ -int -setsig(p, f, flags) - Trap *p; - handler_t f; - int flags; -{ - struct sigaction sigact; - - if (p->signal == SIGEXIT_ || p->signal == SIGERR_) - return 1; - - /* First time setting this signal? If so, get and note the current - * setting. - */ - if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) { - sigaction(p->signal, &Sigact_ign, &sigact); - p->flags |= sigact.sa_handler == SIG_IGN ? - TF_ORIG_IGN : TF_ORIG_DFL; - p->cursig = SIG_IGN; - } - - /* Generally, an ignored signal stays ignored, except if - * - the user of an interactive shell wants to change it - * - the shell wants for force a change - */ - if ((p->flags & TF_ORIG_IGN) && !(flags & SS_FORCE) - && (!(flags & SS_USER) || !Flag(FTALKING))) - return 0; - - setexecsig(p, flags & SS_RESTORE_MASK); - - /* This is here 'cause there should be a way of clearing shtraps, but - * don't know if this is a sane way of doing it. At the moment, - * all users of shtrap are lifetime users (SIGCHLD, SIGALRM, SIGWINCH). - */ - if (!(flags & SS_USER)) - p->shtrap = (handler_t) 0; - if (flags & SS_SHTRAP) { - p->shtrap = f; - f = trapsig; - } - - if (p->cursig != f) { - p->cursig = f; - sigemptyset(&sigact.sa_mask); - sigact.sa_flags = KSH_SA_FLAGS; - sigact.sa_handler = f; - sigaction(p->signal, &sigact, (struct sigaction *) 0); - } - - return 1; -} - -/* control what signal is set to before an exec() */ -void -setexecsig(p, restore) - Trap *p; - int restore; -{ - /* XXX debugging */ - if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) - internal_errorf(1, "setexecsig: unset signal %d(%s)", - p->signal, p->name); - - /* restore original value for exec'd kids */ - p->flags &= ~(TF_EXEC_IGN|TF_EXEC_DFL); - switch (restore & SS_RESTORE_MASK) { - case SS_RESTORE_CURR: /* leave things as they currently are */ - break; - case SS_RESTORE_ORIG: - p->flags |= p->flags & TF_ORIG_IGN ? TF_EXEC_IGN : TF_EXEC_DFL; - break; - case SS_RESTORE_DFL: - p->flags |= TF_EXEC_DFL; - break; - case SS_RESTORE_IGN: - p->flags |= TF_EXEC_IGN; - break; - } -} diff --git a/bin/ksh/tree.c b/bin/ksh/tree.c deleted file mode 100644 index 96450221f..000000000 --- a/bin/ksh/tree.c +++ /dev/null @@ -1,766 +0,0 @@ -/* $NetBSD: tree.c,v 1.6 2005/06/26 19:09:00 christos Exp $ */ - -/* - * command tree climbing - */ -#include - -#ifndef lint -__RCSID("$NetBSD: tree.c,v 1.6 2005/06/26 19:09:00 christos Exp $"); -#endif - - -#include "sh.h" - -#define INDENT 4 - -#define tputc(c, shf) shf_putchar(c, shf); -static void ptree ARGS((struct op *t, int indent, struct shf *f)); -static void pioact ARGS((struct shf *f, int indent, struct ioword *iop)); -static void tputC ARGS((int c, struct shf *shf)); -static void tputS ARGS((char *wp, struct shf *shf)); -static void vfptreef ARGS((struct shf *shf, int indent, const char *fmt, va_list va)); -static struct ioword **iocopy ARGS((struct ioword **iow, Area *ap)); -static void iofree ARGS((struct ioword **iow, Area *ap)); - -/* - * print a command tree - */ - -static void -ptree(t, indent, shf) - register struct op *t; - int indent; - register struct shf *shf; -{ - register char **w; - struct ioword **ioact; - struct op *t1; - - Chain: - if (t == NULL) - return; - switch (t->type) { - case TCOM: - if (t->vars) - for (w = t->vars; *w != NULL; ) - fptreef(shf, indent, "%S ", *w++); - else - fptreef(shf, indent, "#no-vars# "); - if (t->args) - for (w = t->args; *w != NULL; ) - fptreef(shf, indent, "%S ", *w++); - else - fptreef(shf, indent, "#no-args# "); - break; - case TEXEC: -#if 0 /* ?not useful - can't be called? */ - /* Print original vars */ - if (t->left->vars) - for (w = t->left->vars; *w != NULL; ) - fptreef(shf, indent, "%S ", *w++); - else - fptreef(shf, indent, "#no-vars# "); - /* Print expanded vars */ - if (t->args) - for (w = t->args; *w != NULL; ) - fptreef(shf, indent, "%s ", *w++); - else - fptreef(shf, indent, "#no-args# "); - /* Print original io */ - t = t->left; -#else - t = t->left; - goto Chain; -#endif - case TPAREN: - fptreef(shf, indent + 2, "( %T) ", t->left); - break; - case TPIPE: - fptreef(shf, indent, "%T| ", t->left); - t = t->right; - goto Chain; - case TLIST: - fptreef(shf, indent, "%T%;", t->left); - t = t->right; - goto Chain; - case TOR: - case TAND: - fptreef(shf, indent, "%T%s %T", - t->left, (t->type==TOR) ? "||" : "&&", t->right); - break; - case TBANG: - fptreef(shf, indent, "! "); - t = t->right; - goto Chain; - case TDBRACKET: - { - int i; - - fptreef(shf, indent, "[["); - for (i = 0; t->args[i]; i++) - fptreef(shf, indent, " %S", t->args[i]); - fptreef(shf, indent, " ]] "); - break; - } -#ifdef KSH - case TSELECT: - fptreef(shf, indent, "select %s ", t->str); - /* fall through */ -#endif /* KSH */ - case TFOR: - if (t->type == TFOR) - fptreef(shf, indent, "for %s ", t->str); - if (t->vars != NULL) { - fptreef(shf, indent, "in "); - for (w = t->vars; *w; ) - fptreef(shf, indent, "%S ", *w++); - fptreef(shf, indent, "%;"); - } - fptreef(shf, indent + INDENT, "do%N%T", t->left); - fptreef(shf, indent, "%;done "); - break; - case TCASE: - fptreef(shf, indent, "case %S in", t->str); - for (t1 = t->left; t1 != NULL; t1 = t1->right) { - fptreef(shf, indent, "%N("); - for (w = t1->vars; *w != NULL; w++) - fptreef(shf, indent, "%S%c", *w, - (w[1] != NULL) ? '|' : ')'); - fptreef(shf, indent + INDENT, "%;%T%N;;", t1->left); - } - fptreef(shf, indent, "%Nesac "); - break; - case TIF: - case TELIF: - /* 3 == strlen("if ") */ - fptreef(shf, indent + 3, "if %T", t->left); - for (;;) { - t = t->right; - if (t->left != NULL) { - fptreef(shf, indent, "%;"); - fptreef(shf, indent + INDENT, "then%N%T", - t->left); - } - if (t->right == NULL || t->right->type != TELIF) - break; - t = t->right; - fptreef(shf, indent, "%;"); - /* 5 == strlen("elif ") */ - fptreef(shf, indent + 5, "elif %T", t->left); - } - if (t->right != NULL) { - fptreef(shf, indent, "%;"); - fptreef(shf, indent + INDENT, "else%;%T", t->right); - } - fptreef(shf, indent, "%;fi "); - break; - case TWHILE: - case TUNTIL: - /* 6 == strlen("while"/"until") */ - fptreef(shf, indent + 6, "%s %T", - (t->type==TWHILE) ? "while" : "until", - t->left); - fptreef(shf, indent, "%;do"); - fptreef(shf, indent + INDENT, "%;%T", t->right); - fptreef(shf, indent, "%;done "); - break; - case TBRACE: - fptreef(shf, indent + INDENT, "{%;%T", t->left); - fptreef(shf, indent, "%;} "); - break; - case TCOPROC: - fptreef(shf, indent, "%T|& ", t->left); - break; - case TASYNC: - fptreef(shf, indent, "%T& ", t->left); - break; - case TFUNCT: - fptreef(shf, indent, - t->u.ksh_func ? "function %s %T" : "%s() %T", - t->str, t->left); - break; - case TTIME: - fptreef(shf, indent, "time %T", t->left); - break; - default: - fptreef(shf, indent, ""); - break; - } - if ((ioact = t->ioact) != NULL) { - int need_nl = 0; - - while (*ioact != NULL) - pioact(shf, indent, *ioact++); - /* Print here documents after everything else... */ - for (ioact = t->ioact; *ioact != NULL; ) { - struct ioword *iop = *ioact++; - - /* heredoc is 0 when tracing (set -x) */ - if ((iop->flag & IOTYPE) == IOHERE && iop->heredoc) { - tputc('\n', shf); - shf_puts(iop->heredoc, shf); - fptreef(shf, indent, "%s", - evalstr(iop->delim, 0)); - need_nl = 1; - } - } - /* Last delimiter must be followed by a newline (this often - * leads to an extra blank line, but its not worth worrying - * about) - */ - if (need_nl) - tputc('\n', shf); - } -} - -static void -pioact(shf, indent, iop) - register struct shf *shf; - int indent; - register struct ioword *iop; -{ - int flag = iop->flag; - int type = flag & IOTYPE; - int expected; - - expected = (type == IOREAD || type == IORDWR || type == IOHERE) ? 0 - : (type == IOCAT || type == IOWRITE) ? 1 - : (type == IODUP && (iop->unit == !(flag & IORDUP))) ? - iop->unit - : iop->unit + 1; - if (iop->unit != expected) - tputc('0' + iop->unit, shf); - - switch (type) { - case IOREAD: - fptreef(shf, indent, "< "); - break; - case IOHERE: - if (flag&IOSKIP) - fptreef(shf, indent, "<<- "); - else - fptreef(shf, indent, "<< "); - break; - case IOCAT: - fptreef(shf, indent, ">> "); - break; - case IOWRITE: - if (flag&IOCLOB) - fptreef(shf, indent, ">| "); - else - fptreef(shf, indent, "> "); - break; - case IORDWR: - fptreef(shf, indent, "<> "); - break; - case IODUP: - if (flag & IORDUP) - fptreef(shf, indent, "<&"); - else - fptreef(shf, indent, ">&"); - break; - } - /* name/delim are 0 when printing syntax errors */ - if (type == IOHERE) { - if (iop->delim) - fptreef(shf, indent, "%S ", iop->delim); - } else if (iop->name) - fptreef(shf, indent, (iop->flag & IONAMEXP) ? "%s " : "%S ", - iop->name); -} - - -/* - * variants of fputc, fputs for ptreef and snptreef - */ - -static void -tputC(c, shf) - register int c; - register struct shf *shf; -{ - if ((c&0x60) == 0) { /* C0|C1 */ - tputc((c&0x80) ? '$' : '^', shf); - tputc(((c&0x7F)|0x40), shf); - } else if ((c&0x7F) == 0x7F) { /* DEL */ - tputc((c&0x80) ? '$' : '^', shf); - tputc('?', shf); - } else - tputc(c, shf); -} - -static void -tputS(wp, shf) - register char *wp; - register struct shf *shf; -{ - register int c, quoted=0; - - /* problems: - * `...` -> $(...) - * 'foo' -> "foo" - * could change encoding to: - * OQUOTE ["'] ... CQUOTE ["'] - * COMSUB [(`] ...\0 (handle $ ` \ and maybe " in `...` case) - */ - while (1) - switch ((c = *wp++)) { - case EOS: - return; - case CHAR: - tputC(*wp++, shf); - break; - case QCHAR: - c = *wp++; - if (!quoted || (c == '"' || c == '`' || c == '$')) - tputc('\\', shf); - tputC(c, shf); - break; - case COMSUB: - tputc('$', shf); - tputc('(', shf); - while (*wp != 0) - tputC(*wp++, shf); - tputc(')', shf); - wp++; - break; - case EXPRSUB: - tputc('$', shf); - tputc('(', shf); - tputc('(', shf); - while (*wp != 0) - tputC(*wp++, shf); - tputc(')', shf); - tputc(')', shf); - wp++; - break; - case OQUOTE: - quoted = 1; - tputc('"', shf); - break; - case CQUOTE: - quoted = 0; - tputc('"', shf); - break; - case OSUBST: - tputc('$', shf); - if (*wp++ == '{') - tputc('{', shf); - while ((c = *wp++) != 0) - tputC(c, shf); - break; - case CSUBST: - if (*wp++ == '}') - tputc('}', shf); - break; -#ifdef KSH - case OPAT: - tputc(*wp++, shf); - tputc('(', shf); - break; - case SPAT: - tputc('|', shf); - break; - case CPAT: - tputc(')', shf); - break; -#endif /* KSH */ - } -} - -/* - * this is the _only_ way to reliably handle - * variable args with an ANSI compiler - */ -/* VARARGS */ -int -#ifdef HAVE_PROTOTYPES -fptreef(struct shf *shf, int indent, const char *fmt, ...) -#else -fptreef(shf, indent, fmt, va_alist) - struct shf *shf; - int indent; - const char *fmt; - va_dcl -#endif -{ - va_list va; - - SH_VA_START(va, fmt); - - vfptreef(shf, indent, fmt, va); - va_end(va); - return 0; -} - -/* VARARGS */ -char * -#ifdef HAVE_PROTOTYPES -snptreef(char *s, int n, const char *fmt, ...) -#else -snptreef(s, n, fmt, va_alist) - char *s; - int n; - const char *fmt; - va_dcl -#endif -{ - va_list va; - struct shf shf; - - shf_sopen(s, n, SHF_WR | (s ? 0 : SHF_DYNAMIC), &shf); - - SH_VA_START(va, fmt); - vfptreef(&shf, 0, fmt, va); - va_end(va); - - return shf_sclose(&shf); /* null terminates */ -} - -static void -vfptreef(shf, indent, fmt, va) - register struct shf *shf; - int indent; - const char *fmt; - register va_list va; -{ - register int c; - - while ((c = *fmt++)) - if (c == '%') { - register long n; - register char *p; - int neg; - - switch ((c = *fmt++)) { - case 'c': - tputc(va_arg(va, int), shf); - break; - case 's': - p = va_arg(va, char *); - while (*p) - tputc(*p++, shf); - break; - case 'S': /* word */ - p = va_arg(va, char *); - tputS(p, shf); - break; - case 'd': case 'u': /* decimal */ - n = (c == 'd') ? va_arg(va, int) - : va_arg(va, unsigned int); - neg = c=='d' && n<0; - p = ulton((neg) ? -n : n, 10); - if (neg) - *--p = '-'; - while (*p) - tputc(*p++, shf); - break; - case 'T': /* format tree */ - ptree(va_arg(va, struct op *), indent, shf); - break; - case ';': /* newline or ; */ - case 'N': /* newline or space */ - if (shf->flags & SHF_STRING) { - if (c == ';') - tputc(';', shf); - tputc(' ', shf); - } else { - int i; - - tputc('\n', shf); - for (i = indent; i >= 8; i -= 8) - tputc('\t', shf); - for (; i > 0; --i) - tputc(' ', shf); - } - break; - case 'R': - pioact(shf, indent, va_arg(va, struct ioword *)); - break; - default: - tputc(c, shf); - break; - } - } else - tputc(c, shf); -} - -/* - * copy tree (for function definition) - */ - -struct op * -tcopy(t, ap) - register struct op *t; - Area *ap; -{ - register struct op *r; - register char **tw, **rw; - - if (t == NULL) - return NULL; - - r = (struct op *) alloc(sizeof(struct op), ap); - - r->type = t->type; - r->u.evalflags = t->u.evalflags; - - r->str = t->type == TCASE ? wdcopy(t->str, ap) : str_save(t->str, ap); - - if (t->vars == NULL) - r->vars = NULL; - else { - for (tw = t->vars; *tw++ != NULL; ) - ; - rw = r->vars = (char **) - alloc((tw - t->vars + 1) * sizeof(*tw), ap); - for (tw = t->vars; *tw != NULL; ) - *rw++ = wdcopy(*tw++, ap); - *rw = NULL; - } - - if (t->args == NULL) - r->args = NULL; - else { - for (tw = t->args; *tw++ != NULL; ) - ; - rw = r->args = (char **) - alloc((tw - t->args + 1) * sizeof(*tw), ap); - for (tw = t->args; *tw != NULL; ) - *rw++ = wdcopy(*tw++, ap); - *rw = NULL; - } - - r->ioact = (t->ioact == NULL) ? NULL : iocopy(t->ioact, ap); - - r->left = tcopy(t->left, ap); - r->right = tcopy(t->right, ap); - r->lineno = t->lineno; - - return r; -} - -char * -wdcopy(wp, ap) - const char *wp; - Area *ap; -{ - size_t len = wdscan(wp, EOS) - wp; - return memcpy(alloc(len, ap), wp, len); -} - -/* return the position of prefix c in wp plus 1 */ -char * -wdscan(wp, c) - register const char *wp; - register int c; -{ - register int nest = 0; - - while (1) - switch (*wp++) { - case EOS: - return (char *) __UNCONST(wp); - case CHAR: - case QCHAR: - wp++; - break; - case COMSUB: - case EXPRSUB: - while (*wp++ != 0) - ; - break; - case OQUOTE: - case CQUOTE: - break; - case OSUBST: - nest++; - while (*wp++ != '\0') - ; - break; - case CSUBST: - wp++; - if (c == CSUBST && nest == 0) - return (char *) __UNCONST(wp); - nest--; - break; -#ifdef KSH - case OPAT: - nest++; - wp++; - break; - case SPAT: - case CPAT: - if (c == wp[-1] && nest == 0) - return (char *) __UNCONST(wp); - if (wp[-1] == CPAT) - nest--; - break; -#endif /* KSH */ - default: - internal_errorf(0, - "wdscan: unknown char 0x%x (carrying on)", - wp[-1]); - } -} - -/* return a copy of wp without any of the mark up characters and - * with quote characters (" ' \) stripped. - * (string is allocated from ATEMP) - */ -char * -wdstrip(wp) - const char *wp; -{ - struct shf shf; - int c; - - shf_sopen((char *) 0, 32, SHF_WR | SHF_DYNAMIC, &shf); - - /* problems: - * `...` -> $(...) - * x${foo:-"hi"} -> x${foo:-hi} - * x${foo:-'hi'} -> x${foo:-hi} - */ - while (1) - switch ((c = *wp++)) { - case EOS: - return shf_sclose(&shf); /* null terminates */ - case CHAR: - case QCHAR: - shf_putchar(*wp++, &shf); - break; - case COMSUB: - shf_putchar('$', &shf); - shf_putchar('(', &shf); - while (*wp != 0) - shf_putchar(*wp++, &shf); - shf_putchar(')', &shf); - break; - case EXPRSUB: - shf_putchar('$', &shf); - shf_putchar('(', &shf); - shf_putchar('(', &shf); - while (*wp != 0) - shf_putchar(*wp++, &shf); - shf_putchar(')', &shf); - shf_putchar(')', &shf); - break; - case OQUOTE: - break; - case CQUOTE: - break; - case OSUBST: - shf_putchar('$', &shf); - if (*wp++ == '{') - shf_putchar('{', &shf); - while ((c = *wp++) != 0) - shf_putchar(c, &shf); - break; - case CSUBST: - if (*wp++ == '}') - shf_putchar('}', &shf); - break; -#ifdef KSH - case OPAT: - shf_putchar(*wp++, &shf); - shf_putchar('(', &shf); - break; - case SPAT: - shf_putchar('|', &shf); - break; - case CPAT: - shf_putchar(')', &shf); - break; -#endif /* KSH */ - } -} - -static struct ioword ** -iocopy(iow, ap) - register struct ioword **iow; - Area *ap; -{ - register struct ioword **ior; - register int i; - - for (ior = iow; *ior++ != NULL; ) - ; - ior = (struct ioword **) alloc((ior - iow + 1) * sizeof(*ior), ap); - - for (i = 0; iow[i] != NULL; i++) { - register struct ioword *p, *q; - - p = iow[i]; - q = (struct ioword *) alloc(sizeof(*p), ap); - ior[i] = q; - *q = *p; - if (p->name != (char *) 0) - q->name = wdcopy(p->name, ap); - if (p->delim != (char *) 0) - q->delim = wdcopy(p->delim, ap); - if (p->heredoc != (char *) 0) - q->heredoc = str_save(p->heredoc, ap); - } - ior[i] = NULL; - - return ior; -} - -/* - * free tree (for function definition) - */ - -void -tfree(t, ap) - register struct op *t; - Area *ap; -{ - register char **w; - - if (t == NULL) - return; - - if (t->str != NULL) - afree((void*)t->str, ap); - - if (t->vars != NULL) { - for (w = t->vars; *w != NULL; w++) - afree((void*)*w, ap); - afree((void*)t->vars, ap); - } - - if (t->args != NULL) { - for (w = t->args; *w != NULL; w++) - afree((void*)*w, ap); - afree((void*)t->args, ap); - } - - if (t->ioact != NULL) - iofree(t->ioact, ap); - - tfree(t->left, ap); - tfree(t->right, ap); - - afree((void*)t, ap); -} - -static void -iofree(iow, ap) - struct ioword **iow; - Area *ap; -{ - register struct ioword **iop; - register struct ioword *p; - - for (iop = iow; (p = *iop++) != NULL; ) { - if (p->name != NULL) - afree((void*)p->name, ap); - if (p->delim != NULL) - afree((void*)p->delim, ap); - if (p->heredoc != NULL) - afree((void*)p->heredoc, ap); - afree((void*)p, ap); - } -} diff --git a/bin/ksh/tree.h b/bin/ksh/tree.h deleted file mode 100644 index b0aea1e1c..000000000 --- a/bin/ksh/tree.h +++ /dev/null @@ -1,142 +0,0 @@ -/* $NetBSD: tree.h,v 1.4 2004/07/07 19:20:09 mycroft Exp $ */ - -/* - * command trees for compile/execute - */ - -/* $Id: tree.h,v 1.4 2004/07/07 19:20:09 mycroft Exp $ */ - -#define NOBLOCK ((struct op *)NULL) -#define NOWORD ((char *)NULL) -#define NOWORDS ((char **)NULL) - -/* - * Description of a command or an operation on commands. - */ -struct op { - short type; /* operation type, see below */ - union { /* WARNING: newtp(), tcopy() use evalflags = 0 to clear union */ - short evalflags; /* TCOM: arg expansion eval() flags */ - short ksh_func; /* TFUNC: function x (vs x()) */ - } u; - char **args; /* arguments to a command */ - char **vars; /* variable assignments */ - struct ioword **ioact; /* IO actions (eg, < > >>) */ - struct op *left, *right; /* descendents */ - char *str; /* word for case; identifier for for, - * select, and functions; - * path to execute for TEXEC; - * time hook for TCOM. - */ - int lineno; /* TCOM/TFUNC: LINENO for this */ -}; - -/* Tree.type values */ -#define TEOF 0 -#define TCOM 1 /* command */ -#define TPAREN 2 /* (c-list) */ -#define TPIPE 3 /* a | b */ -#define TLIST 4 /* a ; b */ -#define TOR 5 /* || */ -#define TAND 6 /* && */ -#define TBANG 7 /* ! */ -#define TDBRACKET 8 /* [[ .. ]] */ -#define TFOR 9 -#define TSELECT 10 -#define TCASE 11 -#define TIF 12 -#define TWHILE 13 -#define TUNTIL 14 -#define TELIF 15 -#define TPAT 16 /* pattern in case */ -#define TBRACE 17 /* {c-list} */ -#define TASYNC 18 /* c & */ -#define TFUNCT 19 /* function name { command; } */ -#define TTIME 20 /* time pipeline */ -#define TEXEC 21 /* fork/exec eval'd TCOM */ -#define TCOPROC 22 /* coprocess |& */ - -/* - * prefix codes for words in command tree - */ -#define EOS 0 /* end of string */ -#define CHAR 1 /* unquoted character */ -#define QCHAR 2 /* quoted character */ -#define COMSUB 3 /* $() substitution (0 terminated) */ -#define EXPRSUB 4 /* $(()) substitution (0 terminated) */ -#define OQUOTE 5 /* opening " or ' */ -#define CQUOTE 6 /* closing " or ' */ -#define OSUBST 7 /* opening ${ subst (followed by { or X) */ -#define CSUBST 8 /* closing } of above (followed by } or X) */ -#define OPAT 9 /* open pattern: *(, @(, etc. */ -#define SPAT 10 /* separate pattern: | */ -#define CPAT 11 /* close pattern: ) */ - -/* - * IO redirection - */ -struct ioword { - int unit; /* unit affected */ - int flag; /* action (below) */ - char *name; /* file name (unused if heredoc) */ - char *delim; /* delimiter for <<,<<- */ - char *heredoc;/* content of heredoc */ -}; - -/* ioword.flag - type of redirection */ -#define IOTYPE 0xF /* type: bits 0:3 */ -#define IOREAD 0x1 /* < */ -#define IOWRITE 0x2 /* > */ -#define IORDWR 0x3 /* <>: todo */ -#define IOHERE 0x4 /* << (here file) */ -#define IOCAT 0x5 /* >> */ -#define IODUP 0x6 /* <&/>& */ -#define IOEVAL BIT(4) /* expand in << */ -#define IOSKIP BIT(5) /* <<-, skip ^\t* */ -#define IOCLOB BIT(6) /* >|, override -o noclobber */ -#define IORDUP BIT(7) /* x<&y (as opposed to x>&y) */ -#define IONAMEXP BIT(8) /* name has been expanded */ - -/* execute/exchild flags */ -#define XEXEC BIT(0) /* execute without forking */ -#define XFORK BIT(1) /* fork before executing */ -#define XBGND BIT(2) /* command & */ -#define XPIPEI BIT(3) /* input is pipe */ -#define XPIPEO BIT(4) /* output is pipe */ -#define XPIPE (XPIPEI|XPIPEO) /* member of pipe */ -#define XXCOM BIT(5) /* `...` command */ -#define XPCLOSE BIT(6) /* exchild: close close_fd in parent */ -#define XCCLOSE BIT(7) /* exchild: close close_fd in child */ -#define XERROK BIT(8) /* non-zero exit ok (for set -e) */ -#define XCOPROC BIT(9) /* starting a co-process */ -#define XTIME BIT(10) /* timing TCOM command */ -#define XINTACT BIT(11) /* OS2: proc started from interactive session */ - -/* - * flags to control expansion of words (assumed by t->evalflags to fit - * in a short) - */ -#define DOBLANK BIT(0) /* perform blank interpretation */ -#define DOGLOB BIT(1) /* expand [?* */ -#define DOPAT BIT(2) /* quote *?[ */ -#define DOTILDE BIT(3) /* normal ~ expansion (first char) */ -#define DONTRUNCOMMAND BIT(4) /* do not run $(command) things */ -#define DOASNTILDE BIT(5) /* assignment ~ expansion (after =, :) */ -#define DOBRACE_ BIT(6) /* used by expand(): do brace expansion */ -#define DOMAGIC_ BIT(7) /* used by expand(): string contains MAGIC */ -#define DOTEMP_ BIT(8) /* ditto : in word part of ${..[%#=?]..} */ -#define DOVACHECK BIT(9) /* var assign check (for typeset, set, etc) */ -#define DOMARKDIRS BIT(10) /* force markdirs behaviour */ - -/* - * The arguments of [[ .. ]] expressions are kept in t->args[] and flags - * indicating how the arguments have been munged are kept in t->vars[]. - * The contents of t->vars[] are stuffed strings (so they can be treated - * like all other t->vars[]) in which the second character is the one that - * is examined. The DB_* defines are the values for these second characters. - */ -#define DB_NORM 1 /* normal argument */ -#define DB_OR 2 /* || -> -o conversion */ -#define DB_AND 3 /* && -> -a conversion */ -#define DB_BE 4 /* an inserted -BE */ -#define DB_PAT 5 /* a pattern argument */ diff --git a/bin/ksh/tty.c b/bin/ksh/tty.c deleted file mode 100644 index 8a60d7329..000000000 --- a/bin/ksh/tty.c +++ /dev/null @@ -1,187 +0,0 @@ -/* $NetBSD: tty.c,v 1.4 2003/06/23 11:39:06 agc Exp $ */ - -#include - -#ifndef lint -__RCSID("$NetBSD: tty.c,v 1.4 2003/06/23 11:39:06 agc Exp $"); -#endif - - -#include "sh.h" -#include "ksh_stat.h" -#define EXTERN -#include "tty.h" -#undef EXTERN - -int -get_tty(fd, ts) - int fd; - TTY_state *ts; -{ - int ret; - -# ifdef HAVE_TERMIOS_H - ret = tcgetattr(fd, ts); -# else /* HAVE_TERIOS_H */ -# ifdef HAVE_TERMIO_H - ret = ioctl(fd, TCGETA, ts); -# else /* HAVE_TERMIO_H */ - ret = ioctl(fd, TIOCGETP, &ts->sgttyb); -# ifdef TIOCGATC - if (ioctl(fd, TIOCGATC, &ts->lchars) < 0) - ret = -1; -# else - if (ioctl(fd, TIOCGETC, &ts->tchars) < 0) - ret = -1; -# ifdef TIOCGLTC - if (ioctl(fd, TIOCGLTC, &ts->ltchars) < 0) - ret = -1; -# endif /* TIOCGLTC */ -# endif /* TIOCGATC */ -# endif /* HAVE_TERMIO_H */ -# endif /* HAVE_TERIOS_H */ - return ret; -} - -int -set_tty(fd, ts, flags) - int fd; - TTY_state *ts; - int flags; -{ - int ret = 0; - -# ifdef HAVE_TERMIOS_H - ret = tcsetattr(fd, TCSADRAIN, ts); -# else /* HAVE_TERIOS_H */ -# ifdef HAVE_TERMIO_H -# ifndef TCSETAW /* e.g. Cray-2 */ - /* first wait for output to drain */ -# ifdef TCSBRK - if (ioctl(tty_fd, TCSBRK, 1) < 0) - ret = -1; -# else /* the following kludge is minimally intrusive, but sometimes fails */ - if (flags & TF_WAIT) - sleep((unsigned)1); /* fake it */ -# endif -# endif /* !TCSETAW */ -# if defined(_BSD_SYSV) || !defined(TCSETAW) -/* _BSD_SYSV must force TIOCSETN instead of TIOCSETP (preserve type-ahead) */ - if (ioctl(tty_fd, TCSETA, ts) < 0) - ret = -1; -# else - if (ioctl(tty_fd, TCSETAW, ts) < 0) - ret = -1; -# endif -# else /* HAVE_TERMIO_H */ -# if defined(__mips) && (defined(_SYSTYPE_BSD43) || defined(__SYSTYPE_BSD43)) - /* Under RISC/os 5.00, bsd43 environment, after a tty driver - * generated interrupt (eg, INTR, TSTP), all output to tty is - * lost until a SETP is done (there must be a better way of - * doing this...). - */ - if (flags & TF_MIPSKLUDGE) - ret = ioctl(fd, TIOCSETP, &ts->sgttyb); - else -# endif /* _SYSTYPE_BSD43 */ - ret = ioctl(fd, TIOCSETN, &ts->sgttyb); -# ifdef TIOCGATC - if (ioctl(fd, TIOCSATC, &ts->lchars) < 0) - ret = -1; -# else - if (ioctl(fd, TIOCSETC, &ts->tchars) < 0) - ret = -1; -# ifdef TIOCGLTC - if (ioctl(fd, TIOCSLTC, &ts->ltchars) < 0) - ret = -1; -# endif /* TIOCGLTC */ -# endif /* TIOCGATC */ -# endif /* HAVE_TERMIO_H */ -# endif /* HAVE_TERIOS_H */ - return ret; -} - - -/* Initialize tty_fd. Used for saving/reseting tty modes upon - * foreground job completion and for setting up tty process group. - */ -void -tty_init(init_ttystate) - int init_ttystate; -{ - int do_close = 1; - int tfd; - const char *devtty = _PATH_TTY; - - if (tty_fd >= 0) { - close(tty_fd); - tty_fd = -1; - } - tty_devtty = 1; - - /* SCO can't job control on /dev/tty, so don't try... */ -#if !defined(__SCO__) - if ((tfd = open(devtty, O_RDWR, 0)) < 0) { -#ifdef __NeXT - /* rlogin on NeXT boxes does not set up the controlling tty, - * so force it to be done here... - */ - { - extern char *ttyname ARGS((int)); - char *s = ttyname(isatty(2) ? 2 : 0); - int fd; - - if (s && (fd = open(s, O_RDWR, 0)) >= 0) { - close(fd); - tfd = open(devtty, O_RDWR, 0); - } - } -#endif /* __NeXT */ - -/* X11R5 xterm on mips doesn't set controlling tty properly - temporary hack */ -# if !defined(__mips) || !(defined(_SYSTYPE_BSD43) || defined(__SYSTYPE_BSD43)) - if (tfd < 0) { - tty_devtty = 0; - warningf(FALSE, - "No controlling tty (open %s: %s)", - devtty, strerror(errno)); - } -# endif /* __mips */ - } -#else /* !__SCO__ */ - tfd = -1; -#endif /* __SCO__ */ - - if (tfd < 0) { - do_close = 0; - if (isatty(0)) - tfd = 0; - else if (isatty(2)) - tfd = 2; - else { - warningf(FALSE, "Can't find tty file descriptor"); - return; - } - } - if ((tty_fd = ksh_dupbase(tfd, FDBASE)) < 0) { - warningf(FALSE, "j_ttyinit: dup of tty fd failed: %s", - strerror(errno)); - } else if (fd_clexec(tty_fd) < 0) { - warningf(FALSE, "j_ttyinit: can't set close-on-exec flag: %s", - strerror(errno)); - close(tty_fd); - tty_fd = -1; - } else if (init_ttystate) - get_tty(tty_fd, &tty_state); - if (do_close) - close(tfd); -} - -void -tty_close() -{ - if (tty_fd >= 0) { - close(tty_fd); - tty_fd = -1; - } -} diff --git a/bin/ksh/tty.h b/bin/ksh/tty.h deleted file mode 100644 index 08c6b7c59..000000000 --- a/bin/ksh/tty.h +++ /dev/null @@ -1,110 +0,0 @@ -/* $NetBSD: tty.h,v 1.2 1997/01/12 19:12:25 tls Exp $ */ - -/* - tty.h -- centralized definitions for a variety of terminal interfaces - - created by DPK, Oct. 1986 - - Rearranged to work with autoconf, added TTY_state, get_tty/set_tty - Michael Rendell, May '94 - - last edit: 30-Jul-1987 D A Gwyn -*/ -/* $NetBSD: tty.h,v 1.2 1997/01/12 19:12:25 tls Exp $ */ - -/* some useful #defines */ -#ifdef EXTERN -# define I__(i) = i -#else -# define I__(i) -# define EXTERN extern -# define EXTERN_DEFINED -#endif - -/* Don't know of a system on which including sys/ioctl.h with termios.h - * causes problems. If there is one, these lines need to be deleted and - * aclocal.m4 needs to have stuff un-commented. - */ -#ifdef SYS_IOCTL_WITH_TERMIOS -# define SYS_IOCTL_WITH_TERMIOS -#endif /* SYS_IOCTL_WITH_TERMIOS */ -#ifdef SYS_IOCTL_WITH_TERMIO -# define SYS_IOCTL_WITH_TERMIO -#endif /* SYS_IOCTL_WITH_TERMIO */ - -#ifdef HAVE_TERMIOS_H -# include -# ifdef SYS_IOCTL_WITH_TERMIOS -# if !(defined(sun) && !defined(__svr4__)) /* too many warnings on sunos */ - /* Need to include sys/ioctl.h on some systems to get the TIOCGWINSZ - * stuff (eg, digital unix). - */ -# include -# endif /* !(sun && !__svr4__) */ -# endif /* SYS_IOCTL_WITH_TERMIOS */ -typedef struct termios TTY_state; -#else -# ifdef HAVE_TERMIO_H -# include -# ifdef SYS_IOCTL_WITH_TERMIO -# include /* see comment above in termios stuff */ -# endif /* SYS_IOCTL_WITH_TERMIO */ -# if _BSD_SYSV /* BRL UNIX System V emulation */ -# ifndef NTTYDISC -# define TIOCGETD _IOR( 't', 0, int ) -# define TIOCSETD _IOW( 't', 1, int ) -# define NTTYDISC 2 -# endif -# ifndef TIOCSTI -# define TIOCSTI _IOW( 't', 114, char ) -# endif -# ifndef TIOCSPGRP -# define TIOCSPGRP _IOW( 't', 118, int ) -# endif -# endif /* _BSD_SYSV */ -typedef struct termio TTY_state; -# else /* HAVE_TERMIO_H */ -/* Assume BSD tty stuff. Uses TIOCGETP, TIOCSETN; uses TIOCGATC/TIOCSATC if - * available, otherwise it uses TIOCGETC/TIOCSETC (also uses TIOCGLTC/TIOCSLTC - * if available) - */ -# ifdef _MINIX -# include -# define TIOCSETN TIOCSETP -# else -# include -# endif -typedef struct { - struct sgttyb sgttyb; -# ifdef TIOCGATC - struct lchars lchars; -# else /* TIOCGATC */ - struct tchars tchars; -# ifdef TIOCGLTC - struct ltchars ltchars; -# endif /* TIOCGLTC */ -# endif /* TIOCGATC */ -} TTY_state; -# endif /* HAVE_TERMIO_H */ -#endif /* HAVE_TERMIOS_H */ - -/* Flags for set_tty() */ -#define TF_NONE 0x00 -#define TF_WAIT 0x01 /* drain output, even it requires sleep() */ -#define TF_MIPSKLUDGE 0x02 /* kludge to unwedge RISC/os 5.0 tty driver */ - -EXTERN int tty_fd I__(-1); /* dup'd tty file descriptor */ -EXTERN int tty_devtty; /* true if tty_fd is from /dev/tty */ -EXTERN TTY_state tty_state; /* saved tty state */ - -extern int get_tty ARGS((int fd, TTY_state *ts)); -extern int set_tty ARGS((int fd, TTY_state *ts, int flags)); -extern void tty_init ARGS((int init_ttystate)); -extern void tty_close ARGS((void)); - -/* be sure not to interfere with anyone else's idea about EXTERN */ -#ifdef EXTERN_DEFINED -# undef EXTERN_DEFINED -# undef EXTERN -#endif -#undef I__ diff --git a/bin/ksh/var.c b/bin/ksh/var.c deleted file mode 100644 index b98a5dd36..000000000 --- a/bin/ksh/var.c +++ /dev/null @@ -1,1260 +0,0 @@ -/* $NetBSD: var.c,v 1.17 2011/10/16 17:12:11 joerg Exp $ */ - -#include - -#ifndef lint -__RCSID("$NetBSD: var.c,v 1.17 2011/10/16 17:12:11 joerg Exp $"); -#endif - - -#include "sh.h" -#include "ksh_time.h" -#include "ksh_limval.h" -#include "ksh_stat.h" -#include - -/* - * Variables - * - * WARNING: unreadable code, needs a rewrite - * - * if (flag&INTEGER), val.i contains integer value, and type contains base. - * otherwise, (val.s + type) contains string value. - * if (flag&EXPORT), val.s contains "name=value" for E-Z exporting. - */ -static struct tbl vtemp; -static struct table specials; -static char *formatstr ARGS((struct tbl *vp, const char *s)); -static void export ARGS((struct tbl *vp, const char *val)); -static int special ARGS((const char *name)); -static void unspecial ARGS((const char *name)); -static void getspec ARGS((struct tbl *vp)); -static void setspec ARGS((struct tbl *vp)); -static void unsetspec ARGS((struct tbl *vp)); -static struct tbl *arraysearch ARGS((struct tbl *, int)); - -/* - * create a new block for function calls and simple commands - * assume caller has allocated and set up e->loc - */ -void -newblock() -{ - register struct block *l; - static char *const empty[] = {null}; - - l = (struct block *) alloc(sizeof(struct block), ATEMP); - l->flags = 0; - ainit(&l->area); /* todo: could use e->area (l->area => l->areap) */ - if (!e->loc) { - l->argc = 0; - l->argv = (char **) __UNCONST(empty); - } else { - l->argc = e->loc->argc; - l->argv = e->loc->argv; - } - l->exit = l->error = NULL; - tinit(&l->vars, &l->area, 0); - tinit(&l->funs, &l->area, 0); - l->next = e->loc; - e->loc = l; -} - -/* - * pop a block handling special variables - */ -void -popblock() -{ - register struct block *l = e->loc; - register struct tbl *vp, **vpp = l->vars.tbls, *vq; - register int i; - - e->loc = l->next; /* pop block */ - for (i = l->vars.size; --i >= 0; ) { - if ((vp = *vpp++) != NULL && (vp->flag&SPECIAL)) { - if ((vq = global(vp->name))->flag & ISSET) - setspec(vq); - else - unsetspec(vq); - } - } - if (l->flags & BF_DOGETOPTS) - user_opt = l->getopts_state; - afreeall(&l->area); - afree(l, ATEMP); -} - -/* called by main() to initialize variable data structures */ -void -initvar() -{ - static const struct { - const char *name; - int v; - } names[] = { - { "COLUMNS", V_COLUMNS }, - { "IFS", V_IFS }, - { "OPTIND", V_OPTIND }, - { "PATH", V_PATH }, - { "POSIXLY_CORRECT", V_POSIXLY_CORRECT }, - { "TMPDIR", V_TMPDIR }, -#ifdef HISTORY - { "HISTFILE", V_HISTFILE }, - { "HISTSIZE", V_HISTSIZE }, -#endif /* HISTORY */ -#ifdef EDIT - { "EDITOR", V_EDITOR }, - { "VISUAL", V_VISUAL }, -#endif /* EDIT */ -#ifdef KSH - { "MAIL", V_MAIL }, - { "MAILCHECK", V_MAILCHECK }, - { "MAILPATH", V_MAILPATH }, - { "RANDOM", V_RANDOM }, - { "SECONDS", V_SECONDS }, - { "TMOUT", V_TMOUT }, -#endif /* KSH */ - { "LINENO", V_LINENO }, - { (char *) 0, 0 } - }; - int i; - struct tbl *tp; - - tinit(&specials, APERM, 32); /* must be 2^n (currently 17 specials) */ - for (i = 0; names[i].name; i++) { - tp = tenter(&specials, names[i].name, hash(names[i].name)); - tp->flag = DEFINED|ISSET; - tp->type = names[i].v; - } -} - -/* Used to calculate an array index for global()/local(). Sets *arrayp to - * non-zero if this is an array, sets *valp to the array index, returns - * the basename of the array. - */ -const char *array_index_calc(const char *n, bool_t *arrayp, int *valp); - -const char * -array_index_calc(n, arrayp, valp) - const char *n; - bool_t *arrayp; - int *valp; -{ - const char *p; - int len; - - *arrayp = FALSE; - p = skip_varname(n, FALSE); - if (p != n && *p == '[' && (len = array_ref_len(p))) { - char *sub, *tmp; - long rval; - - /* Calculate the value of the subscript */ - *arrayp = TRUE; - tmp = str_nsave(p+1, len-2, ATEMP); - sub = substitute(tmp, 0); - afree(tmp, ATEMP); - n = str_nsave(n, p - n, ATEMP); - evaluate(sub, &rval, KSH_UNWIND_ERROR); - if (rval < 0 || rval > ARRAYMAX) - errorf("%s: subscript out of range", n); - *valp = rval; - afree(sub, ATEMP); - } - return n; -} - -/* - * Search for variable, if not found create globally. - */ -struct tbl * -global(n) - register const char *n; -{ - register struct block *l = e->loc; - register struct tbl *vp; - register int c; - unsigned h; - bool_t array; - int val; - - /* Check to see if this is an array */ - n = array_index_calc(n, &array, &val); - h = hash(n); - c = n[0]; - if (!letter(c)) { - if (array) - errorf("bad substitution"); - vp = &vtemp; - vp->flag = DEFINED; - vp->type = 0; - vp->areap = ATEMP; - *vp->name = c; - if (digit(c)) { - for (c = 0; digit(*n); n++) - c = c*10 + *n-'0'; - if (c <= l->argc) - /* setstr can't fail here */ - setstr(vp, l->argv[c], KSH_RETURN_ERROR); - vp->flag |= RDONLY; - return vp; - } - vp->flag |= RDONLY; - if (n[1] != '\0') - return vp; - vp->flag |= ISSET|INTEGER; - switch (c) { - case '$': - vp->val.i = kshpid; - break; - case '!': - /* If no job, expand to nothing */ - if ((vp->val.i = j_async()) == 0) - vp->flag &= ~(ISSET|INTEGER); - break; - case '?': - vp->val.i = exstat; - break; - case '#': - vp->val.i = l->argc; - break; - case '-': - vp->flag &= ~INTEGER; - vp->val.s = getoptions(); - break; - default: - vp->flag &= ~(ISSET|INTEGER); - } - return vp; - } - for (l = e->loc; ; l = l->next) { - vp = tsearch(&l->vars, n, h); - if (vp != NULL) { - if (array) - return arraysearch(vp, val); - else - return vp; - } - if (l->next == NULL) - break; - } - vp = tenter(&l->vars, n, h); - if (array) - vp = arraysearch(vp, val); - vp->flag |= DEFINED; - if (special(n)) - vp->flag |= SPECIAL; - return vp; -} - -/* - * Search for local variable, if not found create locally. - */ -struct tbl * -local(n, copy) - register const char *n; - bool_t copy; -{ - register struct block *l = e->loc; - register struct tbl *vp; - unsigned h; - bool_t array; - int val; - - /* Check to see if this is an array */ - n = array_index_calc(n, &array, &val); - h = hash(n); - if (!letter(*n)) { - vp = &vtemp; - vp->flag = DEFINED|RDONLY; - vp->type = 0; - vp->areap = ATEMP; - return vp; - } - vp = tenter(&l->vars, n, h); - if (copy && !(vp->flag & DEFINED)) { - struct block *ll = l; - struct tbl *vq = (struct tbl *) 0; - - while ((ll = ll->next) && !(vq = tsearch(&ll->vars, n, h))) - ; - if (vq) { - vp->flag |= vq->flag & (EXPORT|INTEGER|RDONLY - |LJUST|RJUST|ZEROFIL - |LCASEV|UCASEV_AL|INT_U|INT_L); - if (vq->flag & INTEGER) - vp->type = vq->type; - vp->u2.field = vq->u2.field; - } - } - if (array) - vp = arraysearch(vp, val); - vp->flag |= DEFINED; - if (special(n)) - vp->flag |= SPECIAL; - return vp; -} - -/* get variable string value */ -char * -str_val(vp) - register struct tbl *vp; -{ - char *s; - - if ((vp->flag&SPECIAL)) - getspec(vp); - if (!(vp->flag&ISSET)) - s = null; /* special to dollar() */ - else if (!(vp->flag&INTEGER)) /* string source */ - s = vp->val.s + vp->type; - else { /* integer source */ - /* worst case number length is when base=2, so use BITS(long) */ - /* minus base # number null */ - static char strbuf[1 + 2 + 1 + BITS(long) + 1]; - const char *digits = (vp->flag & UCASEV_AL) ? - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" - : "0123456789abcdefghijklmnopqrstuvwxyz"; - register unsigned long n; - register int base; - - s = strbuf + sizeof(strbuf); - if (vp->flag & INT_U) - n = (unsigned long) vp->val.i; - else - n = (vp->val.i < 0) ? -vp->val.i : vp->val.i; - base = (vp->type == 0) ? 10 : vp->type; - - *--s = '\0'; - do { - *--s = digits[n % base]; - n /= base; - } while (n != 0); - if (base != 10) { - *--s = '#'; - *--s = digits[base % 10]; - if (base >= 10) - *--s = digits[base / 10]; - } - if (!(vp->flag & INT_U) && vp->val.i < 0) - *--s = '-'; - if (vp->flag & (RJUST|LJUST)) { /* case already dealt with */ - s = formatstr(vp, s); - (void)strlcpy(strbuf, s, sizeof(strbuf)); - afree(s, ATEMP); - s = strbuf; - } - } - return s; -} - -/* get variable integer value, with error checking */ -long -intval(vp) - register struct tbl *vp; -{ - long num; - int base; - - base = getint(vp, &num); - if (base == -1) - /* XXX check calls - is error here ok by POSIX? */ - errorf("%s: bad number", str_val(vp)); - return num; -} - -/* set variable to string value */ -int -setstr(vq, s, error_ok) - register struct tbl *vq; - const char *s; - int error_ok; -{ - char *fs = NULL; - int no_ro_check = error_ok & 0x4; - error_ok &= ~0x4; - if ((vq->flag & RDONLY) && !no_ro_check) { - warningf(TRUE, "%s: is read only", vq->name); - if (!error_ok) - errorf("%s", null); - return 0; - } - if (!(vq->flag&INTEGER)) { /* string dest */ - if ((vq->flag&ALLOC)) { - /* debugging */ - if (s >= vq->val.s - && s <= vq->val.s + strlen(vq->val.s)) - internal_errorf(TRUE, - "setstr: %s=%s: assigning to self", - vq->name, s); - afree((void*)vq->val.s, vq->areap); - } - vq->flag &= ~(ISSET|ALLOC); - vq->type = 0; - if (s && (vq->flag & (UCASEV_AL|LCASEV|LJUST|RJUST))) - s = fs = formatstr(vq, s); - if ((vq->flag&EXPORT)) - export(vq, s); - else { - vq->val.s = str_save(s, vq->areap); - vq->flag |= ALLOC; - } - } else /* integer dest */ - if (!v_evaluate(vq, s, error_ok)) - return 0; - vq->flag |= ISSET; - if ((vq->flag&SPECIAL)) - setspec(vq); - if (fs) - afree(fs, ATEMP); - return 1; -} - -/* set variable to integer */ -void -setint(vq, n) - register struct tbl *vq; - long n; -{ - if (!(vq->flag&INTEGER)) { - register struct tbl *vp = &vtemp; - vp->flag = (ISSET|INTEGER); - vp->type = 0; - vp->areap = ATEMP; - vp->val.i = n; - /* setstr can't fail here */ - setstr(vq, str_val(vp), KSH_RETURN_ERROR); - } else - vq->val.i = n; - vq->flag |= ISSET; - if ((vq->flag&SPECIAL)) - setspec(vq); -} - -int -getint(vp, nump) - struct tbl *vp; - long *nump; -{ - register char *s; - register int c; - int base, neg; - int have_base = 0; - long num; - - if (vp->flag&SPECIAL) - getspec(vp); - /* XXX is it possible for ISSET to be set and val.s to be 0? */ - if (!(vp->flag&ISSET) || (!(vp->flag&INTEGER) && vp->val.s == NULL)) - return -1; - if (vp->flag&INTEGER) { - *nump = vp->val.i; - return vp->type; - } - s = vp->val.s + vp->type; - if (s == NULL) /* redundant given initial test */ - s = null; - base = 10; - num = 0; - neg = 0; - if (*s == '-') { - neg = 1; - s++; - } - if (s[0] == '0' && s[1] == 'x') { - base = 16; - have_base = 1; - s += 2; - } - for (c = (unsigned char)*s++; c ; c = (unsigned char)*s++) { - if (c == '#') { - base = (int) num; - if (have_base || base < 2 || base > 36) - return -1; - num = 0; - have_base = 1; - } else if (letnum(c)) { - if (isdigit(c)) - c -= '0'; - else if (islower(c)) - c -= 'a' - 10; /* todo: assumes ascii */ - else if (isupper(c)) - c -= 'A' - 10; /* todo: assumes ascii */ - else - c = -1; /* _: force error */ - if (c < 0 || c >= base) - return -1; - num = num * base + c; - } else - return -1; - } - if (neg) - num = -num; - *nump = num; - return base; -} - -/* convert variable vq to integer variable, setting its value from vp - * (vq and vp may be the same) - */ -struct tbl * -setint_v(vq, vp) - register struct tbl *vq, *vp; -{ - int base; - long num; - - if ((base = getint(vp, &num)) == -1) - return NULL; - if (!(vq->flag & INTEGER) && (vq->flag & ALLOC)) { - vq->flag &= ~ALLOC; - afree(vq->val.s, vq->areap); - } - vq->val.i = num; - if (vq->type == 0) /* default base */ - vq->type = base; - vq->flag |= ISSET|INTEGER; - if (vq->flag&SPECIAL) - setspec(vq); - return vq; -} - -static char * -formatstr(vp, s) - struct tbl *vp; - const char *s; -{ - int olen, nlen; - char *p, *q; - - olen = strlen(s); - - if (vp->flag & (RJUST|LJUST)) { - if (!vp->u2.field) /* default field width */ - vp->u2.field = olen; - nlen = vp->u2.field; - } else - nlen = olen; - - p = (char *) alloc(nlen + 1, ATEMP); - if (vp->flag & (RJUST|LJUST)) { - int slen; - - if (vp->flag & RJUST) { - const char *r = s + olen; - /* strip trailing spaces (at&t ksh uses q[-1] == ' ') */ - while (r > s && isspace((unsigned char)r[-1])) - --r; - slen = r - s; - if (slen > vp->u2.field) { - s += slen - vp->u2.field; - slen = vp->u2.field; - } - shf_snprintf(p, nlen + 1, - ((vp->flag & ZEROFIL) && digit(*s)) ? - "%0*s%.*s" : "%*s%.*s", - vp->u2.field - slen, null, slen, s); - } else { - /* strip leading spaces/zeros */ - while (isspace((unsigned char)*s)) - s++; - if (vp->flag & ZEROFIL) - while (*s == '0') - s++; - shf_snprintf(p, nlen + 1, "%-*.*s", - vp->u2.field, vp->u2.field, s); - } - } else - memcpy(p, s, olen + 1); - - if (vp->flag & UCASEV_AL) { - for (q = p; *q; q++) - if (islower((unsigned char)*q)) - *q = toupper((unsigned char)*q); - } else if (vp->flag & LCASEV) { - for (q = p; *q; q++) - if (isupper((unsigned char)*q)) - *q = tolower((unsigned char)*q); - } - - return p; -} - -/* - * make vp->val.s be "name=value" for quick exporting. - */ -static void -export(vp, val) - register struct tbl *vp; - const char *val; -{ - register char *xp; - char *op = (vp->flag&ALLOC) ? vp->val.s : NULL; - int namelen = strlen(vp->name); - int vallen = strlen(val) + 1; - - vp->flag |= ALLOC; - xp = (char*)alloc(namelen + 1 + vallen, vp->areap); - memcpy(vp->val.s = xp, vp->name, namelen); - xp += namelen; - *xp++ = '='; - vp->type = xp - vp->val.s; /* offset to value */ - memcpy(xp, val, vallen); - if (op != NULL) - afree((void*)op, vp->areap); -} - -/* - * lookup variable (according to (set&LOCAL)), - * set its attributes (INTEGER, RDONLY, EXPORT, TRACE, LJUST, RJUST, ZEROFIL, - * LCASEV, UCASEV_AL), and optionally set its value if an assignment. - */ -struct tbl * -typeset(var, set, clr, field, base) - register const char *var; - Tflag clr, set; - int field, base; -{ - register struct tbl *vp; - struct tbl *vpbase, *t; - char *tvar; - const char *val; - - /* check for valid variable name, search for value */ - val = skip_varname(var, FALSE); - if (val == var) - return NULL; - if (*val == '[') { - int len; - - len = array_ref_len(val); - if (len == 0) - return NULL; - /* IMPORT is only used when the shell starts up and is - * setting up its environment. Allow only simple array - * references at this time since parameter/command substitution - * is performed on the [expression], which would be a major - * security hole. - */ - if (set & IMPORT) { - int i; - for (i = 1; i < len - 1; i++) - if (!digit(val[i])) - return NULL; - } - val += len; - } - if (*val == '=') - tvar = str_nsave(var, val++ - var, ATEMP); - else { - /* Importing from original environment: must have an = */ - if (set & IMPORT) - return NULL; - tvar = (char *) __UNCONST(var); - val = NULL; - } - - /* Prevent typeset from creating a local PATH/ENV/SHELL */ - if (Flag(FRESTRICTED) && (strcmp(tvar, "PATH") == 0 - || strcmp(tvar, "ENV") == 0 - || strcmp(tvar, "SHELL") == 0)) - errorf("%s: restricted", tvar); - - vp = (set&LOCAL) ? local(tvar, (set & LOCAL_COPY) ? TRUE : FALSE) - : global(tvar); - set &= ~(LOCAL|LOCAL_COPY); - - vpbase = (vp->flag & ARRAY) ? global(arrayname(var)) : vp; - - /* only allow export flag to be set. at&t ksh allows any attribute to - * be changed, which means it can be truncated or modified - * (-L/-R/-Z/-i). - */ - if ((vpbase->flag&RDONLY) - && (val || clr || (set & ~EXPORT))) - /* XXX check calls - is error here ok by POSIX? */ - errorf("%s: is read only", tvar); - if (val) - afree(tvar, ATEMP); - - /* most calls are with set/clr == 0 */ - if (set | clr) { - int ok = 1; - /* XXX if x[0] isn't set, there will be problems: need to have - * one copy of attributes for arrays... - */ - for (t = vpbase; t; t = t->u.array) { - int fake_assign; - char UNINITIALIZED(*s); - char UNINITIALIZED(*free_me); - - fake_assign = (t->flag & ISSET) && (!val || t != vp) - && ((set & (UCASEV_AL|LCASEV|LJUST|RJUST|ZEROFIL)) - || ((t->flag & INTEGER) && (clr & INTEGER)) - || (!(t->flag & INTEGER) && (set & INTEGER))); - if (fake_assign) { - if (t->flag & INTEGER) { - s = str_val(t); - free_me = (char *) 0; - } else { - s = t->val.s + t->type; - free_me = (t->flag & ALLOC) ? t->val.s - : (char *) 0; - } - t->flag &= ~ALLOC; - } - if (!(t->flag & INTEGER) && (set & INTEGER)) { - t->type = 0; - t->flag &= ~ALLOC; - } - t->flag = (t->flag | set) & ~clr; - /* Don't change base if assignment is to be done, - * in case assignment fails. - */ - if ((set & INTEGER) && base > 0 && (!val || t != vp)) - t->type = base; - if (set & (LJUST|RJUST|ZEROFIL)) - t->u2.field = field; - if (fake_assign) { - if (!setstr(t, s, KSH_RETURN_ERROR)) { - /* Somewhat arbitrary action here: - * zap contents of variable, but keep - * the flag settings. - */ - ok = 0; - if (t->flag & INTEGER) - t->flag &= ~ISSET; - else { - if (t->flag & ALLOC) - afree((void*) t->val.s, - t->areap); - t->flag &= ~(ISSET|ALLOC); - t->type = 0; - } - } - if (free_me) - afree((void *) free_me, t->areap); - } - } - if (!ok) - errorf("%s", null); - } - - if (val != NULL) { - if (vp->flag&INTEGER) { - /* do not zero base before assignment */ - setstr(vp, val, KSH_UNWIND_ERROR | 0x4); - /* Done after assignment to override default */ - if (base > 0) - vp->type = base; - } else - /* setstr can't fail (readonly check already done) */ - setstr(vp, val, KSH_RETURN_ERROR | 0x4); - } - - /* only x[0] is ever exported, so use vpbase */ - if ((vpbase->flag&EXPORT) && !(vpbase->flag&INTEGER) - && vpbase->type == 0) - export(vpbase, (vpbase->flag&ISSET) ? vpbase->val.s : null); - - return vp; -} - -/* Unset a variable. array_ref is set if there was an array reference in - * the name lookup (eg, x[2]). - */ -void -unset(vp, array_ref) - register struct tbl *vp; - int array_ref; -{ - if (vp->flag & ALLOC) - afree((void*)vp->val.s, vp->areap); - if ((vp->flag & ARRAY) && !array_ref) { - struct tbl *a, *tmp; - - /* Free up entire array */ - for (a = vp->u.array; a; ) { - tmp = a; - a = a->u.array; - if (tmp->flag & ALLOC) - afree((void *) tmp->val.s, tmp->areap); - afree(tmp, tmp->areap); - } - vp->u.array = (struct tbl *) 0; - } - /* If foo[0] is being unset, the remainder of the array is kept... */ - vp->flag &= SPECIAL | (array_ref ? ARRAY|DEFINED : 0); - if (vp->flag & SPECIAL) - unsetspec(vp); /* responsible for `unspecial'ing var */ -} - -/* return a pointer to the first char past a legal variable name (returns the - * argument if there is no legal name, returns * a pointer to the terminating - * null if whole string is legal). - */ -char * -skip_varname(s, aok) - const char *s; - int aok; -{ - int alen; - - if (s && letter(*s)) { - while (*++s && letnum(*s)) - ; - if (aok && *s == '[' && (alen = array_ref_len(s))) - s += alen; - } - return (char *) __UNCONST(s); -} - -/* Return a pointer to the first character past any legal variable name. */ -char * -skip_wdvarname(s, aok) - const char *s; - int aok; /* skip array de-reference? */ -{ - if (s[0] == CHAR && letter(s[1])) { - do - s += 2; - while (s[0] == CHAR && letnum(s[1])); - if (aok && s[0] == CHAR && s[1] == '[') { - /* skip possible array de-reference */ - const char *p = s; - char c; - int depth = 0; - - while (1) { - if (p[0] != CHAR) - break; - c = p[1]; - p += 2; - if (c == '[') - depth++; - else if (c == ']' && --depth == 0) { - s = p; - break; - } - } - } - } - return (char *) __UNCONST(s); -} - -/* Check if coded string s is a variable name */ -int -is_wdvarname(s, aok) - const char *s; - int aok; -{ - char *p = skip_wdvarname(s, aok); - - return p != s && p[0] == EOS; -} - -/* Check if coded string s is a variable assignment */ -int -is_wdvarassign(s) - const char *s; -{ - char *p = skip_wdvarname(s, TRUE); - - return p != s && p[0] == CHAR && p[1] == '='; -} - -/* - * Make the exported environment from the exported names in the dictionary. - */ -char ** -makenv() -{ - struct block *l = e->loc; - XPtrV env; - register struct tbl *vp, **vpp; - register int i; - - XPinit(env, 64); - for (l = e->loc; l != NULL; l = l->next) - for (vpp = l->vars.tbls, i = l->vars.size; --i >= 0; ) - if ((vp = *vpp++) != NULL - && (vp->flag&(ISSET|EXPORT)) == (ISSET|EXPORT)) { - register struct block *l2; - register struct tbl *vp2; - unsigned h = hash(vp->name); - - /* unexport any redefined instances */ - for (l2 = l->next; l2 != NULL; l2 = l2->next) { - vp2 = tsearch(&l2->vars, vp->name, h); - if (vp2 != NULL) - vp2->flag &= ~EXPORT; - } - if ((vp->flag&INTEGER)) { - /* integer to string */ - char *val; - val = str_val(vp); - vp->flag &= ~(INTEGER|RDONLY); - /* setstr can't fail here */ - setstr(vp, val, KSH_RETURN_ERROR); - } - XPput(env, vp->val.s); - } - XPput(env, NULL); - return (char **) XPclose(env); -} - -/* - * Called after a fork in parent to bump the random number generator. - * Done to ensure children will not get the same random number sequence - * if the parent doesn't use $RANDOM. - */ -void -change_random() -{ - rand(); -} - -/* - * handle special variables with side effects - PATH, SECONDS. - */ - -/* Test if name is a special parameter */ -static int -special(name) - register const char * name; -{ - register struct tbl *tp; - - tp = tsearch(&specials, name, hash(name)); - return tp && (tp->flag & ISSET) ? tp->type : V_NONE; -} - -/* Make a variable non-special */ -static void -unspecial(name) - register const char * name; -{ - register struct tbl *tp; - - tp = tsearch(&specials, name, hash(name)); - if (tp) - tdelete(tp); -} - -#ifdef KSH -static time_t seconds; /* time SECONDS last set */ -#endif /* KSH */ -static int user_lineno; /* what user set $LINENO to */ - -static void -getspec(vp) - register struct tbl *vp; -{ - switch (special(vp->name)) { -#ifdef KSH - case V_SECONDS: - vp->flag &= ~SPECIAL; - /* On start up the value of SECONDS is used before seconds - * has been set - don't do anything in this case - * (see initcoms[] in main.c). - */ - if (vp->flag & ISSET) - setint(vp, (long) (time((time_t *)0) - seconds)); - vp->flag |= SPECIAL; - break; - case V_RANDOM: - vp->flag &= ~SPECIAL; - setint(vp, (long) (rand() & 0x7fff)); - vp->flag |= SPECIAL; - break; -#endif /* KSH */ -#ifdef HISTORY - case V_HISTSIZE: - vp->flag &= ~SPECIAL; - setint(vp, (long) histsize); - vp->flag |= SPECIAL; - break; -#endif /* HISTORY */ - case V_OPTIND: - vp->flag &= ~SPECIAL; - setint(vp, (long) user_opt.uoptind); - vp->flag |= SPECIAL; - break; - case V_LINENO: - vp->flag &= ~SPECIAL; - setint(vp, (long) current_lineno + user_lineno); - vp->flag |= SPECIAL; - break; - } -} - -static void -setspec(vp) - register struct tbl *vp; -{ - char *s; - - switch (special(vp->name)) { - case V_PATH: - if (path) - afree(path, APERM); - path = str_save(str_val(vp), APERM); - flushcom(1); /* clear tracked aliases */ - break; - case V_IFS: - setctypes(s = str_val(vp), C_IFS); - ifs0 = *s; - break; - case V_OPTIND: - vp->flag &= ~SPECIAL; - getopts_reset((int) intval(vp)); - vp->flag |= SPECIAL; - break; - case V_POSIXLY_CORRECT: - change_flag(FPOSIX, OF_SPECIAL, 1); - break; - case V_TMPDIR: - if (tmpdir) { - afree(tmpdir, APERM); - tmpdir = (char *) 0; - } - /* Use tmpdir iff it is an absolute path, is writable and - * searchable and is a directory... - */ - { - struct stat statb; - s = str_val(vp); - if (ISABSPATH(s) && eaccess(s, W_OK|X_OK) == 0 - && stat(s, &statb) == 0 && S_ISDIR(statb.st_mode)) - tmpdir = str_save(s, APERM); - } - break; -#ifdef HISTORY - case V_HISTSIZE: - vp->flag &= ~SPECIAL; - sethistsize((int) intval(vp)); - vp->flag |= SPECIAL; - break; - case V_HISTFILE: - sethistfile(str_val(vp)); - break; -#endif /* HISTORY */ -#ifdef EDIT - case V_VISUAL: - set_editmode(str_val(vp)); - break; - case V_EDITOR: - if (!(global("VISUAL")->flag & ISSET)) - set_editmode(str_val(vp)); - break; - case V_COLUMNS: - if ((x_cols = intval(vp)) <= MIN_COLS) - x_cols = MIN_COLS; - break; -#endif /* EDIT */ -#ifdef KSH - case V_MAIL: - mbset(str_val(vp)); - break; - case V_MAILPATH: - mpset(str_val(vp)); - break; - case V_MAILCHECK: - vp->flag &= ~SPECIAL; - mcset(intval(vp)); - vp->flag |= SPECIAL; - break; - case V_RANDOM: - vp->flag &= ~SPECIAL; - srand((unsigned int)intval(vp)); - vp->flag |= SPECIAL; - break; - case V_SECONDS: - vp->flag &= ~SPECIAL; - seconds = time((time_t*) 0) - intval(vp); - vp->flag |= SPECIAL; - break; - case V_TMOUT: - /* at&t ksh seems to do this (only listen if integer) */ - if (vp->flag & INTEGER) - ksh_tmout = vp->val.i >= 0 ? vp->val.i : 0; - break; -#endif /* KSH */ - case V_LINENO: - vp->flag &= ~SPECIAL; - /* The -1 is because line numbering starts at 1. */ - user_lineno = (unsigned int) intval(vp) - current_lineno - 1; - vp->flag |= SPECIAL; - break; - } -} - -static void -unsetspec(vp) - register struct tbl *vp; -{ - switch (special(vp->name)) { - case V_PATH: - if (path) - afree(path, APERM); - path = str_save(def_path, APERM); - flushcom(1); /* clear tracked aliases */ - break; - case V_IFS: - setctypes(" \t\n", C_IFS); - ifs0 = ' '; - break; - case V_TMPDIR: - /* should not become unspecial */ - if (tmpdir) { - afree(tmpdir, APERM); - tmpdir = (char *) 0; - } - break; -#ifdef KSH - case V_MAIL: - mbset((char *) 0); - break; - case V_MAILPATH: - mpset((char *) 0); - break; -#endif /* KSH */ - - case V_LINENO: -#ifdef KSH - case V_MAILCHECK: /* at&t ksh leaves previous value in place */ - case V_RANDOM: - case V_SECONDS: - case V_TMOUT: /* at&t ksh leaves previous value in place */ -#endif /* KSH */ - unspecial(vp->name); - break; - - /* at&t ksh man page says OPTIND, OPTARG and _ lose special meaning, - * but OPTARG does not (still set by getopts) and _ is also still - * set in various places. - * Don't know what at&t does for: - * MAIL, MAILPATH, HISTSIZE, HISTFILE, - * Unsetting these in at&t ksh does not loose the `specialness': - * no effect: IFS, COLUMNS, PATH, TMPDIR, - * VISUAL, EDITOR, - * pdkshisms: no effect: - * POSIXLY_CORRECT (use set +o posix instead) - */ - } -} - -/* - * Search for (and possibly create) a table entry starting with - * vp, indexed by val. - */ -static struct tbl * -arraysearch(vp, val) - struct tbl *vp; - int val; -{ - struct tbl *prev, *curr, *new; - size_t namelen = strlen(vp->name) + 1; - - vp->flag |= ARRAY|DEFINED; - - /* The table entry is always [0] */ - if (val == 0) { - vp->index = 0; - return vp; - } - prev = vp; - curr = vp->u.array; - while (curr && curr->index < val) { - prev = curr; - curr = curr->u.array; - } - if (curr && curr->index == val) { - if (curr->flag&ISSET) - return curr; - else - new = curr; - } else - new = (struct tbl *)alloc(sizeof(struct tbl) + namelen, - vp->areap); - strlcpy(new->name, vp->name, namelen); - new->flag = vp->flag & ~(ALLOC|DEFINED|ISSET|SPECIAL); - new->type = vp->type; - new->areap = vp->areap; - new->u2.field = vp->u2.field; - new->index = val; - if (curr != new) { /* not reusing old array entry */ - prev->u.array = new; - new->u.array = curr; - } - return new; -} - -/* Return the length of an array reference (eg, [1+2]) - cp is assumed - * to point to the open bracket. Returns 0 if there is no matching closing - * bracket. - */ -int -array_ref_len(cp) - const char *cp; -{ - const char *s = cp; - int c; - int depth = 0; - - while ((c = *s++) && (c != ']' || --depth)) - if (c == '[') - depth++; - if (!c) - return 0; - return s - cp; -} - -/* - * Make a copy of the base of an array name - */ -char * -arrayname(str) - const char *str; -{ - const char *p; - - if ((p = strchr(str, '[')) == 0) - /* Shouldn't happen, but why worry? */ - return (char *) __UNCONST(str); - - return str_nsave(str, p - str, ATEMP); -} - -/* Set (or overwrite, if !reset) the array variable var to the values in vals. - */ -void -set_array(var, reset, vals) - const char *var; - int reset; - char **vals; -{ - struct tbl *vp, *vq; - int i; - - /* to get local array, use "typeset foo; set -A foo" */ - vp = global(var); - - /* Note: at&t ksh allows set -A but not set +A of a read-only var */ - if ((vp->flag&RDONLY)) - errorf("%s: is read only", var); - /* This code is quite non-optimal */ - if (reset > 0) - /* trash existing values and attributes */ - unset(vp, 0); - /* todo: would be nice for assignment to completely succeed or - * completely fail. Only really effects integer arrays: - * evaluation of some of vals[] may fail... - */ - for (i = 0; vals[i]; i++) { - vq = arraysearch(vp, i); - /* would be nice to deal with errors here... (see above) */ - setstr(vq, vals[i], KSH_RETURN_ERROR); - } -} diff --git a/bin/ksh/version.c b/bin/ksh/version.c deleted file mode 100644 index 3db43d0e4..000000000 --- a/bin/ksh/version.c +++ /dev/null @@ -1,16 +0,0 @@ -/* $NetBSD: version.c,v 1.5 2005/06/26 19:09:00 christos Exp $ */ - -/* - * value of $KSH_VERSION (or $SH_VERSION) - */ -#include - -#ifndef lint -__RCSID("$NetBSD: version.c,v 1.5 2005/06/26 19:09:00 christos Exp $"); -#endif - - -#include "sh.h" - -char ksh_version [] = - "@(#)PD KSH v5.2.14 99/07/13.2"; diff --git a/bin/ksh/vi.c b/bin/ksh/vi.c deleted file mode 100644 index ed3d06fc6..000000000 --- a/bin/ksh/vi.c +++ /dev/null @@ -1,2203 +0,0 @@ -/* $NetBSD: vi.c,v 1.12 2011/06/22 03:56:17 mrg Exp $ */ - -/* - * vi command editing - * written by John Rochester (initially for nsh) - * bludgeoned to fit pdksh by Larry Bouzane, Jeff Sparkes & Eric Gisin - * - */ -#include - -#ifndef lint -__RCSID("$NetBSD: vi.c,v 1.12 2011/06/22 03:56:17 mrg Exp $"); -#endif - -#include "config.h" -#ifdef VI - -#include "sh.h" -#include -#include "ksh_stat.h" /* completion */ -#include "edit.h" - -#define CMDLEN 1024 -#define Ctrl(c) (c&0x1f) -#define is_wordch(c) (letnum(c)) - -struct edstate { - int winleft; - char *cbuf; - int cbufsize; - int linelen; - int cursor; -}; - - -static int vi_hook ARGS((int)); -static void vi_reset ARGS((char *, size_t)); -static int nextstate ARGS((int)); -static int vi_insert ARGS((int)); -static int vi_cmd ARGS((int, const char *)); -static int domove ARGS((int, const char *, int)); -static int redo_insert ARGS((int)); -static void yank_range ARGS((int, int)); -static int bracktype ARGS((int)); -static void save_cbuf ARGS((void)); -static void restore_cbuf ARGS((void)); -static void edit_reset ARGS((char *, size_t)); -static int putbuf ARGS((const char *, int, int)); -static void del_range ARGS((int, int)); -static int findch ARGS((int, int, int, int)); -static int forwword ARGS((int)); -static int backword ARGS((int)); -static int endword ARGS((int)); -static int Forwword ARGS((int)); -static int Backword ARGS((int)); -static int Endword ARGS((int)); -static int grabhist ARGS((int, int)); -static int grabsearch ARGS((int, int, int, char *)); -static void redraw_line ARGS((int)); -static void refresh ARGS((int)); -static int outofwin ARGS((void)); -static void rewindow ARGS((void)); -static int newcol ARGS((int, int)); -static void display ARGS((char *, char *, int)); -static void ed_mov_opt ARGS((int, char *)); -static int expand_word ARGS((int)); -static int complete_word ARGS((int, int)); -static int print_expansions ARGS((struct edstate *, int)); -static int char_len ARGS((int)); -static void x_vi_zotc ARGS((int)); -static void vi_pprompt ARGS((int)); -static void vi_error ARGS((void)); -static void vi_macro_reset ARGS((void)); -static int x_vi_putbuf ARGS((const char *, size_t)); - -#define C_ 0x1 /* a valid command that isn't a M_, E_, U_ */ -#define M_ 0x2 /* movement command (h, l, etc.) */ -#define E_ 0x4 /* extended command (c, d, y) */ -#define X_ 0x8 /* long command (@, f, F, t, T, etc.) */ -#define U_ 0x10 /* an UN-undoable command (that isn't a M_) */ -#define B_ 0x20 /* bad command (^@) */ -#define Z_ 0x40 /* repeat count defaults to 0 (not 1) */ -#define S_ 0x80 /* search (/, ?) */ - -#define is_bad(c) (classify[(c)&0x7f]&B_) -#define is_cmd(c) (classify[(c)&0x7f]&(M_|E_|C_|U_)) -#define is_move(c) (classify[(c)&0x7f]&M_) -#define is_extend(c) (classify[(c)&0x7f]&E_) -#define is_long(c) (classify[(c)&0x7f]&X_) -#define is_undoable(c) (!(classify[(c)&0x7f]&U_)) -#define is_srch(c) (classify[(c)&0x7f]&S_) -#define is_zerocount(c) (classify[(c)&0x7f]&Z_) - -const unsigned char classify[128] = { - /* 0 1 2 3 4 5 6 7 */ - /* 0 ^@ ^A ^B ^C ^D ^E ^F ^G */ - B_, 0, 0, 0, 0, C_|U_, C_|Z_, 0, - /* 01 ^H ^I ^J ^K ^L ^M ^N ^O */ - M_, C_|Z_, 0, 0, C_|U_, 0, C_, 0, - /* 02 ^P ^Q ^R ^S ^T ^U ^V ^W */ - C_, 0, C_|U_, 0, 0, 0, C_, 0, - /* 03 ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */ - C_, 0, 0, C_|Z_, 0, 0, 0, 0, - /* 04 ! " # $ % & ' */ - M_, 0, 0, C_, M_, M_, 0, 0, - /* 05 ( ) * + , - . / */ - 0, 0, C_, C_, M_, C_, 0, C_|S_, - /* 06 0 1 2 3 4 5 6 7 */ - M_, 0, 0, 0, 0, 0, 0, 0, - /* 07 8 9 : ; < = > ? */ - 0, 0, 0, M_, 0, C_, 0, C_|S_, - /* 010 @ A B C D E F G */ - C_|X_, C_, M_, C_, C_, M_, M_|X_, C_|U_|Z_, - /* 011 H I J K L M N O */ - 0, C_, 0, 0, 0, 0, C_|U_, 0, - /* 012 P Q R S T U V W */ - C_, 0, C_, C_, M_|X_, C_, 0, M_, - /* 013 X Y Z [ \ ] ^ _ */ - C_, C_|U_, 0, 0, C_|Z_, 0, M_, C_|Z_, - /* 014 ` a b c d e f g */ - 0, C_, M_, E_, E_, M_, M_|X_, C_|Z_, - /* 015 h i j k l m n o */ - M_, C_, C_|U_, C_|U_, M_, 0, C_|U_, 0, - /* 016 p q r s t u v w */ - C_, 0, X_, C_, M_|X_, C_|U_, C_|U_|Z_,M_, - /* 017 x y z { | } ~ ^? */ - C_, E_|U_, 0, 0, M_|Z_, 0, C_, 0 -}; - -#define MAXVICMD 3 -#define SRCHLEN 40 - -#define INSERT 1 -#define REPLACE 2 - -#define VNORMAL 0 /* command, insert or replace mode */ -#define VARG1 1 /* digit prefix (first, eg, 5l) */ -#define VEXTCMD 2 /* cmd + movement (eg, cl) */ -#define VARG2 3 /* digit prefix (second, eg, 2c3l) */ -#define VXCH 4 /* f, F, t, T, @ */ -#define VFAIL 5 /* bad command */ -#define VCMD 6 /* single char command (eg, X) */ -#define VREDO 7 /* . */ -#define VLIT 8 /* ^V */ -#define VSEARCH 9 /* /, ? */ -#define VVERSION 10 /* ^V */ - -static char undocbuf[CMDLEN]; - -static struct edstate *save_edstate ARGS((struct edstate *old)); -static void restore_edstate ARGS((struct edstate *old, struct edstate *new)); -static void free_edstate ARGS((struct edstate *old)); - -static struct edstate ebuf; -static struct edstate undobuf = { 0, undocbuf, CMDLEN, 0, 0 }; - -static struct edstate *es; /* current editor state */ -static struct edstate *undo; - -static char ibuf[CMDLEN]; /* input buffer */ -static int first_insert; /* set when starting in insert mode */ -static int saved_inslen; /* saved inslen for first insert */ -static int inslen; /* length of input buffer */ -static int srchlen; /* length of current search pattern */ -static char ybuf[CMDLEN]; /* yank buffer */ -static int yanklen; /* length of yank buffer */ -static int fsavecmd = ' '; /* last find command */ -static int fsavech; /* character to find */ -static char lastcmd[MAXVICMD]; /* last non-move command */ -static int lastac; /* argcnt for lastcmd */ -static int lastsearch = ' '; /* last search command */ -static char srchpat[SRCHLEN]; /* last search pattern */ -static int insert; /* non-zero in insert mode */ -static int hnum; /* position in history */ -static int ohnum; /* history line copied (after mod) */ -static int hlast; /* 1 past last position in history */ -static int modified; /* buffer has been "modified" */ -static int state; - -/* Information for keeping track of macros that are being expanded. - * The format of buf is the alias contents followed by a null byte followed - * by the name (letter) of the alias. The end of the buffer is marked by - * a double null. The name of the alias is stored so recursive macros can - * be detected. - */ -struct macro_state { - unsigned char *p; /* current position in buf */ - unsigned char *buf; /* pointer to macro(s) being expanded */ - int len; /* how much data in buffer */ -}; -static struct macro_state macro; - -enum expand_mode { NONE, EXPAND, COMPLETE, PRINT }; -static enum expand_mode expanded = NONE;/* last input was expanded */ - -int -x_vi(buf, len) - char *buf; - size_t len; -{ - int c; - - vi_reset(buf, len > CMDLEN ? CMDLEN : len); - vi_pprompt(1); - x_flush(); - while (1) { - if (macro.p) { - c = *macro.p++; - /* end of current macro? */ - if (!c) { - /* more macros left to finish? */ - if (*macro.p++) - continue; - /* must be the end of all the macros */ - vi_macro_reset(); - c = x_getc(); - } - } else { - c = x_getc(); - } - if (c == -1) - break; - if (state != VLIT) { - if (c == edchars.intr || c == edchars.quit) { - /* pretend we got an interrupt */ - x_vi_zotc(c); - x_flush(); - trapsig(c == edchars.intr ? SIGINT : SIGQUIT); - x_mode(FALSE); - unwind(LSHELL); - } else if (c == edchars.eof && state != VVERSION) { - if (es->linelen == 0) { - x_vi_zotc(edchars.eof); - c = -1; - break; - } - continue; - } - } - if (vi_hook(c)) - break; - x_flush(); - } - - x_putc('\r'); x_putc('\n'); x_flush(); - - if (c == -1 || len <= (size_t)es->linelen) - return -1; - - if (es->cbuf != buf) - memmove(buf, es->cbuf, es->linelen); - - buf[es->linelen++] = '\n'; - - return es->linelen; -} - -static int -vi_hook(ch) - int ch; -{ - static char curcmd[MAXVICMD]; - static char locpat[SRCHLEN]; - static int cmdlen; - static int argc1, argc2; - - switch (state) { - - case VNORMAL: - if (insert != 0) { - if (ch == Ctrl('v')) { - state = VLIT; - ch = '^'; - } - switch (vi_insert(ch)) { - case -1: -#ifdef OS2 - /* Arrow keys generate 0xe0X, where X is H.. */ - state = VCMD; - argc1 = 1; - switch (x_getc()) { - case 'H': - *curcmd='k'; - break; - case 'K': - *curcmd='h'; - break; - case 'P': - *curcmd='j'; - break; - case 'M': - *curcmd='l'; - break; - default: - vi_error(); - state = VNORMAL; - } - break; -#else /* OS2 */ - vi_error(); - state = VNORMAL; -#endif /* OS2 */ - break; - case 0: - if (state == VLIT) { - es->cursor--; - refresh(0); - } else - refresh(insert != 0); - break; - case 1: - return 1; - } - } else { - if (ch == '\r' || ch == '\n') - return 1; - cmdlen = 0; - argc1 = 0; - if (ch >= '1' && ch <= '9') { - argc1 = ch - '0'; - state = VARG1; - } else { - curcmd[cmdlen++] = ch; - state = nextstate(ch); - if (state == VSEARCH) { - save_cbuf(); - es->cursor = 0; - es->linelen = 0; - if (ch == '/') { - if (putbuf("/", 1, 0) != 0) { - return -1; - } - } else if (putbuf("?", 1, 0) != 0) - return -1; - refresh(0); - } - if (state == VVERSION) { - save_cbuf(); - es->cursor = 0; - es->linelen = 0; - putbuf(ksh_version + 4, - strlen(ksh_version + 4), 0); - refresh(0); - } - } - } - break; - - case VLIT: - if (is_bad(ch)) { - del_range(es->cursor, es->cursor + 1); - vi_error(); - } else - es->cbuf[es->cursor++] = ch; - refresh(1); - state = VNORMAL; - break; - - case VVERSION: - restore_cbuf(); - state = VNORMAL; - refresh(0); - break; - - case VARG1: - if (isdigit(ch)) - argc1 = argc1 * 10 + ch - '0'; - else { - curcmd[cmdlen++] = ch; - state = nextstate(ch); - } - break; - - case VEXTCMD: - argc2 = 0; - if (ch >= '1' && ch <= '9') { - argc2 = ch - '0'; - state = VARG2; - return 0; - } else { - curcmd[cmdlen++] = ch; - if (ch == curcmd[0]) - state = VCMD; - else if (is_move(ch)) - state = nextstate(ch); - else - state = VFAIL; - } - break; - - case VARG2: - if (isdigit(ch)) - argc2 = argc2 * 10 + ch - '0'; - else { - if (argc1 == 0) - argc1 = argc2; - else - argc1 *= argc2; - curcmd[cmdlen++] = ch; - if (ch == curcmd[0]) - state = VCMD; - else if (is_move(ch)) - state = nextstate(ch); - else - state = VFAIL; - } - break; - - case VXCH: - if (ch == Ctrl('[')) - state = VNORMAL; - else { - curcmd[cmdlen++] = ch; - state = VCMD; - } - break; - - case VSEARCH: - if (ch == '\r' || ch == '\n' /*|| ch == Ctrl('[')*/ ) { - restore_cbuf(); - /* Repeat last search? */ - if (srchlen == 0) { - if (!srchpat[0]) { - vi_error(); - state = VNORMAL; - refresh(0); - return 0; - } - } else { - locpat[srchlen] = '\0'; - (void) strlcpy(srchpat, locpat, sizeof srchpat); - } - state = VCMD; - } else if (ch == edchars.erase || ch == Ctrl('h')) { - if (srchlen != 0) { - srchlen--; - es->linelen -= char_len((unsigned char) locpat[srchlen]); - es->cursor = es->linelen; - refresh(0); - return 0; - } - restore_cbuf(); - state = VNORMAL; - refresh(0); - } else if (ch == edchars.kill) { - srchlen = 0; - es->linelen = 1; - es->cursor = 1; - refresh(0); - return 0; - } else if (ch == edchars.werase) { - int i; - int n = srchlen; - - while (n > 0 && isspace((unsigned char)locpat[n - 1])) - n--; - while (n > 0 && !isspace((unsigned char)locpat[n - 1])) - n--; - for (i = srchlen; --i >= n; ) - es->linelen -= char_len((unsigned char) locpat[i]); - srchlen = n; - es->cursor = es->linelen; - refresh(0); - return 0; - } else { - if (srchlen == SRCHLEN - 1) - vi_error(); - else { - locpat[srchlen++] = ch; - if ((ch & 0x80) && Flag(FVISHOW8)) { - if (es->linelen + 2 > es->cbufsize) - vi_error(); - es->cbuf[es->linelen++] = 'M'; - es->cbuf[es->linelen++] = '-'; - ch &= 0x7f; - } - if (ch < ' ' || ch == 0x7f) { - if (es->linelen + 2 > es->cbufsize) - vi_error(); - es->cbuf[es->linelen++] = '^'; - es->cbuf[es->linelen++] = ch ^ '@'; - } else { - if (es->linelen >= es->cbufsize) - vi_error(); - es->cbuf[es->linelen++] = ch; - } - es->cursor = es->linelen; - refresh(0); - } - return 0; - } - break; - } - - switch (state) { - case VCMD: - state = VNORMAL; - switch (vi_cmd(argc1, curcmd)) { - case -1: - vi_error(); - refresh(0); - break; - case 0: - if (insert != 0) - inslen = 0; - refresh(insert != 0); - break; - case 1: - refresh(0); - return 1; - case 2: - /* back from a 'v' command - don't redraw the screen */ - return 1; - } - break; - - case VREDO: - state = VNORMAL; - if (argc1 != 0) - lastac = argc1; - switch (vi_cmd(lastac, lastcmd)) { - case -1: - vi_error(); - refresh(0); - break; - case 0: - if (insert != 0) { - if (lastcmd[0] == 's' || lastcmd[0] == 'c' || - lastcmd[0] == 'C') { - if (redo_insert(1) != 0) - vi_error(); - } else { - if (redo_insert(lastac) != 0) - vi_error(); - } - } - refresh(0); - break; - case 1: - refresh(0); - return 1; - case 2: - /* back from a 'v' command - can't happen */ - break; - } - break; - - case VFAIL: - state = VNORMAL; - vi_error(); - break; - } - return 0; -} - -static void -vi_reset(buf, len) - char *buf; - size_t len; -{ - state = VNORMAL; - ohnum = hnum = hlast = histnum(-1) + 1; - insert = INSERT; - saved_inslen = inslen; - first_insert = 1; - inslen = 0; - modified = 1; - vi_macro_reset(); - edit_reset(buf, len); -} - -static int -nextstate(ch) - int ch; -{ - if (is_extend(ch)) - return VEXTCMD; - else if (is_srch(ch)) - return VSEARCH; - else if (is_long(ch)) - return VXCH; - else if (ch == '.') - return VREDO; - else if (ch == Ctrl('v')) - return VVERSION; - else if (is_cmd(ch)) - return VCMD; - else - return VFAIL; -} - -static int -vi_insert(ch) - int ch; -{ - int tcursor; - - if (ch == edchars.erase || ch == Ctrl('h')) { - if (insert == REPLACE) { - if (es->cursor == undo->cursor) { - vi_error(); - return 0; - } - if (inslen > 0) - inslen--; - es->cursor--; - if (es->cursor >= undo->linelen) - es->linelen--; - else - es->cbuf[es->cursor] = undo->cbuf[es->cursor]; - } else { - if (es->cursor == 0) { - /* x_putc(BEL); no annoying bell here */ - return 0; - } - if (inslen > 0) - inslen--; - es->cursor--; - es->linelen--; - memmove(&es->cbuf[es->cursor], &es->cbuf[es->cursor+1], - es->linelen - es->cursor + 1); - } - expanded = NONE; - return 0; - } - if (ch == edchars.kill) { - if (es->cursor != 0) { - inslen = 0; - memmove(es->cbuf, &es->cbuf[es->cursor], - es->linelen - es->cursor); - es->linelen -= es->cursor; - es->cursor = 0; - } - expanded = NONE; - return 0; - } - if (ch == edchars.werase) { - if (es->cursor != 0) { - tcursor = Backword(1); - memmove(&es->cbuf[tcursor], &es->cbuf[es->cursor], - es->linelen - es->cursor); - es->linelen -= es->cursor - tcursor; - if (inslen < es->cursor - tcursor) - inslen = 0; - else - inslen -= es->cursor - tcursor; - es->cursor = tcursor; - } - expanded = NONE; - return 0; - } - /* If any chars are entered before escape, trash the saved insert - * buffer (if user inserts & deletes char, ibuf gets trashed and - * we don't want to use it) - */ - if (first_insert && ch != Ctrl('[')) - saved_inslen = 0; - switch (ch) { - -#ifdef OS2 - case 224: /* function key prefix */ -#endif /* OS2 */ - case '\0': - return -1; - - case '\r': - case '\n': - return 1; - - case Ctrl('['): - expanded = NONE; - if (first_insert) { - first_insert = 0; - if (inslen == 0) { - inslen = saved_inslen; - return redo_insert(0); - } - lastcmd[0] = 'a'; - lastac = 1; - } - if (lastcmd[0] == 's' || lastcmd[0] == 'c' || - lastcmd[0] == 'C') - return redo_insert(0); - else - return redo_insert(lastac - 1); - - /* { Begin nonstandard vi commands */ - case Ctrl('x'): - expand_word(0); - break; - - case Ctrl('f'): - complete_word(0, 0); - break; - - case Ctrl('e'): - print_expansions(es, 0); - break; - - case Ctrl('i'): - if (Flag(FVITABCOMPLETE)) { - complete_word(0, 0); - break; - } - /* FALLTHROUGH */ - /* End nonstandard vi commands } */ - - default: - if (es->linelen >= es->cbufsize - 1) - return -1; - ibuf[inslen++] = ch; - if (insert == INSERT) { - memmove(&es->cbuf[es->cursor+1], &es->cbuf[es->cursor], - es->linelen - es->cursor); - es->linelen++; - } - es->cbuf[es->cursor++] = ch; - if (insert == REPLACE && es->cursor > es->linelen) - es->linelen++; - expanded = NONE; - } - return 0; -} - -static int -vi_cmd(argcnt, cmd) - int argcnt; - const char *cmd; -{ - int ncursor; - int cur, c1, c2, c3 = 0; - int any; - struct edstate *t; - - if (argcnt == 0 && !is_zerocount(*cmd)) - argcnt = 1; - - if (is_move(*cmd)) { - if ((cur = domove(argcnt, cmd, 0)) >= 0) { - if (cur == es->linelen && cur != 0) - cur--; - es->cursor = cur; - } else - return -1; - } else { - /* Don't save state in middle of macro.. */ - if (is_undoable(*cmd) && !macro.p) { - undo->winleft = es->winleft; - memmove(undo->cbuf, es->cbuf, es->linelen); - undo->linelen = es->linelen; - undo->cursor = es->cursor; - lastac = argcnt; - memmove(lastcmd, cmd, MAXVICMD); - } - switch (*cmd) { - - case Ctrl('l'): - case Ctrl('r'): - redraw_line(1); - break; - - case '@': - { - static char alias[] = "_\0"; - struct tbl *ap; - int olen, nlen; - char *p, *nbuf; - - /* lookup letter in alias list... */ - alias[1] = cmd[1]; - ap = tsearch(&aliases, alias, hash(alias)); - if (!cmd[1] || !ap || !(ap->flag & ISSET)) - return -1; - /* check if this is a recursive call... */ - if ((p = (char *) macro.p)) - while ((p = strchr(p, '\0')) && p[1]) - if (*++p == cmd[1]) - return -1; - /* insert alias into macro buffer */ - nlen = strlen(ap->val.s) + 1; - olen = !macro.p ? 2 - : macro.len - (macro.p - macro.buf); - nbuf = alloc(nlen + 1 + olen, APERM); - memcpy(nbuf, ap->val.s, nlen); - nbuf[nlen++] = cmd[1]; - if (macro.p) { - memcpy(nbuf + nlen, macro.p, olen); - afree(macro.buf, APERM); - nlen += olen; - } else { - nbuf[nlen++] = '\0'; - nbuf[nlen++] = '\0'; - } - macro.p = macro.buf = (unsigned char *) nbuf; - macro.len = nlen; - } - break; - - case 'a': - modified = 1; hnum = hlast; - if (es->linelen != 0) - es->cursor++; - insert = INSERT; - break; - - case 'A': - modified = 1; hnum = hlast; - del_range(0, 0); - es->cursor = es->linelen; - insert = INSERT; - break; - - case 'S': - es->cursor = domove(1, "^", 1); - del_range(es->cursor, es->linelen); - modified = 1; hnum = hlast; - insert = INSERT; - break; - - case 'Y': - cmd = "y$"; - /* ahhhhhh... */ - case 'c': - case 'd': - case 'y': - if (*cmd == cmd[1]) { - c1 = *cmd == 'c' ? domove(1, "^", 1) : 0; - c2 = es->linelen; - } else if (!is_move(cmd[1])) - return -1; - else { - if ((ncursor = domove(argcnt, &cmd[1], 1)) < 0) - return -1; - if (*cmd == 'c' && - (cmd[1]=='w' || cmd[1]=='W') && - !isspace((unsigned char)es->cbuf[es->cursor])) { - while (isspace((unsigned char)es->cbuf[--ncursor])) - ; - ncursor++; - } - if (ncursor > es->cursor) { - c1 = es->cursor; - c2 = ncursor; - } else { - c1 = ncursor; - c2 = es->cursor; - if (cmd[1] == '%') - c2++; - } - } - if (*cmd != 'c' && c1 != c2) - yank_range(c1, c2); - if (*cmd != 'y') { - del_range(c1, c2); - es->cursor = c1; - } - if (*cmd == 'c') { - modified = 1; hnum = hlast; - insert = INSERT; - } - break; - - case 'p': - modified = 1; hnum = hlast; - if (es->linelen != 0) - es->cursor++; - while (putbuf(ybuf, yanklen, 0) == 0 && --argcnt > 0) - ; - if (es->cursor != 0) - es->cursor--; - if (argcnt != 0) - return -1; - break; - - case 'P': - modified = 1; hnum = hlast; - any = 0; - while (putbuf(ybuf, yanklen, 0) == 0 && --argcnt > 0) - any = 1; - if (any && es->cursor != 0) - es->cursor--; - if (argcnt != 0) - return -1; - break; - - case 'C': - modified = 1; hnum = hlast; - del_range(es->cursor, es->linelen); - insert = INSERT; - break; - - case 'D': - yank_range(es->cursor, es->linelen); - del_range(es->cursor, es->linelen); - if (es->cursor != 0) - es->cursor--; - break; - - case 'g': - if (!argcnt) - argcnt = hlast + 1; - /* fall through */ - case 'G': - if (!argcnt) - argcnt = 1; - else - argcnt = hlast - (source->line - argcnt); - if (grabhist(modified, argcnt - 1) < 0) - return -1; - else { - modified = 0; - hnum = argcnt - 1; - } - break; - - case 'i': - modified = 1; hnum = hlast; - insert = INSERT; - break; - - case 'I': - modified = 1; hnum = hlast; - es->cursor = domove(1, "^", 1); - insert = INSERT; - break; - - case 'j': - case '+': - case Ctrl('n'): - if (grabhist(modified, hnum + argcnt) < 0) - return -1; - else { - modified = 0; - hnum += argcnt; - } - break; - - case 'k': - case '-': - case Ctrl('p'): - if (grabhist(modified, hnum - argcnt) < 0) - return -1; - else { - modified = 0; - hnum -= argcnt; - } - break; - - case 'r': - if (es->linelen == 0) - return -1; - modified = 1; hnum = hlast; - if (cmd[1] == 0) - vi_error(); - else - es->cbuf[es->cursor] = cmd[1]; - break; - - case 'R': - modified = 1; hnum = hlast; - insert = REPLACE; - break; - - case 's': - if (es->linelen == 0) - return -1; - modified = 1; hnum = hlast; - if (es->cursor + argcnt > es->linelen) - argcnt = es->linelen - es->cursor; - del_range(es->cursor, es->cursor + argcnt); - insert = INSERT; - break; - - case 'v': - if (es->linelen == 0) - return -1; - if (!argcnt) { - if (modified) { - es->cbuf[es->linelen] = '\0'; - source->line++; - histsave(source->line, es->cbuf, 1); - } else - argcnt = source->line + 1 - - (hlast - hnum); - } - shf_snprintf(es->cbuf, es->cbufsize, - argcnt ? "%s %d" : "%s", - "fc -e ${VISUAL:-${EDITOR:-vi}} --", - argcnt); - es->linelen = strlen(es->cbuf); - return 2; - - case 'x': - if (es->linelen == 0) - return -1; - modified = 1; hnum = hlast; - if (es->cursor + argcnt > es->linelen) - argcnt = es->linelen - es->cursor; - yank_range(es->cursor, es->cursor + argcnt); - del_range(es->cursor, es->cursor + argcnt); - break; - - case 'X': - if (es->cursor > 0) { - modified = 1; hnum = hlast; - if (es->cursor < argcnt) - argcnt = es->cursor; - yank_range(es->cursor - argcnt, es->cursor); - del_range(es->cursor - argcnt, es->cursor); - es->cursor -= argcnt; - } else - return -1; - break; - - case 'u': - t = es; - es = undo; - undo = t; - break; - - case 'U': - if (!modified) - return -1; - if (grabhist(modified, ohnum) < 0) - return -1; - modified = 0; - hnum = ohnum; - break; - - case '?': - if (hnum == hlast) - hnum = -1; - /* ahhh */ - case '/': - c3 = 1; - srchlen = 0; - lastsearch = *cmd; - /* fall through */ - case 'n': - case 'N': - if (lastsearch == ' ') - return -1; - if (lastsearch == '?') - c1 = 1; - else - c1 = 0; - if (*cmd == 'N') - c1 = !c1; - if ((c2 = grabsearch(modified, hnum, - c1, srchpat)) < 0) { - if (c3) { - restore_cbuf(); - refresh(0); - } - return -1; - } else { - modified = 0; - hnum = c2; - ohnum = hnum; - } - break; - case '_': { - int inspace; - char *p, *sp; - - if (histnum(-1) < 0) - return -1; - p = *histpos(); -#define issp(c) (isspace((unsigned char)(c)) || (c) == '\n') - if (argcnt) { - while (*p && issp(*p)) - p++; - while (*p && --argcnt) { - while (*p && !issp(*p)) - p++; - while (*p && issp(*p)) - p++; - } - if (!*p) - return -1; - sp = p; - } else { - sp = p; - inspace = 0; - while (*p) { - if (issp(*p)) - inspace = 1; - else if (inspace) { - inspace = 0; - sp = p; - } - p++; - } - p = sp; - } - modified = 1; hnum = hlast; - if (es->cursor != es->linelen) - es->cursor++; - while (*p && !issp(*p)) { - argcnt++; - p++; - } - if (putbuf(space, 1, 0) != 0) - argcnt = -1; - else if (putbuf(sp, argcnt, 0) != 0) - argcnt = -1; - if (argcnt < 0) { - if (es->cursor != 0) - es->cursor--; - return -1; - } - insert = INSERT; - } - break; - - case '~': { - char *p; - int i; - - if (es->linelen == 0) - return -1; - for (i = 0; i < argcnt; i++) { - p = &es->cbuf[es->cursor]; - if (islower((unsigned char)*p)) { - modified = 1; hnum = hlast; - *p = toupper((unsigned char)*p); - } else if (isupper((unsigned char)*p)) { - modified = 1; hnum = hlast; - *p = tolower((unsigned char)*p); - } - if (es->cursor < es->linelen - 1) - es->cursor++; - } - break; - } - - case '#': - { - int ret = x_do_comment(es->cbuf, es->cbufsize, - &es->linelen); - if (ret >= 0) - es->cursor = 0; - return ret; - } - - case '=': /* at&t ksh */ - case Ctrl('e'): /* Nonstandard vi/ksh */ - print_expansions(es, 1); - break; - - - case Ctrl('i'): /* Nonstandard vi/ksh */ - if (!Flag(FVITABCOMPLETE)) - return -1; - complete_word(1, argcnt); - break; - - case Ctrl('['): /* some annoying at&t ksh's */ - if (!Flag(FVIESCCOMPLETE)) - return -1; - case '\\': /* at&t ksh */ - case Ctrl('f'): /* Nonstandard vi/ksh */ - complete_word(1, argcnt); - break; - - - case '*': /* at&t ksh */ - case Ctrl('x'): /* Nonstandard vi/ksh */ - expand_word(1); - break; - } - if (insert == 0 && es->cursor != 0 && es->cursor >= es->linelen) - es->cursor--; - } - return 0; -} - -static int -domove(argcnt, cmd, sub) - int argcnt; - const char *cmd; - int sub; -{ - int bcount, UNINITIALIZED(i), t; - int UNINITIALIZED(ncursor); - - switch (*cmd) { - - case 'b': - if (!sub && es->cursor == 0) - return -1; - ncursor = backword(argcnt); - break; - - case 'B': - if (!sub && es->cursor == 0) - return -1; - ncursor = Backword(argcnt); - break; - - case 'e': - if (!sub && es->cursor + 1 >= es->linelen) - return -1; - ncursor = endword(argcnt); - if (sub && ncursor < es->linelen) - ncursor++; - break; - - case 'E': - if (!sub && es->cursor + 1 >= es->linelen) - return -1; - ncursor = Endword(argcnt); - if (sub && ncursor < es->linelen) - ncursor++; - break; - - case 'f': - case 'F': - case 't': - case 'T': - fsavecmd = *cmd; - fsavech = cmd[1]; - /* drop through */ - - case ',': - case ';': - if (fsavecmd == ' ') - return -1; - i = fsavecmd == 'f' || fsavecmd == 'F'; - t = fsavecmd > 'a'; - if (*cmd == ',') - t = !t; - if ((ncursor = findch(fsavech, argcnt, t, i)) < 0) - return -1; - if (sub && t) - ncursor++; - break; - - case 'h': - case Ctrl('h'): - if (!sub && es->cursor == 0) - return -1; - ncursor = es->cursor - argcnt; - if (ncursor < 0) - ncursor = 0; - break; - - case ' ': - case 'l': - if (!sub && es->cursor + 1 >= es->linelen) - return -1; - if (es->linelen != 0) { - ncursor = es->cursor + argcnt; - if (ncursor > es->linelen) - ncursor = es->linelen; - } - break; - - case 'w': - if (!sub && es->cursor + 1 >= es->linelen) - return -1; - ncursor = forwword(argcnt); - break; - - case 'W': - if (!sub && es->cursor + 1 >= es->linelen) - return -1; - ncursor = Forwword(argcnt); - break; - - case '0': - ncursor = 0; - break; - - case '^': - ncursor = 0; - while (ncursor < es->linelen - 1 && isspace((unsigned char)es->cbuf[ncursor])) - ncursor++; - break; - - case '|': - ncursor = argcnt; - if (ncursor > es->linelen) - ncursor = es->linelen; - if (ncursor) - ncursor--; - break; - - case '$': - if (es->linelen != 0) - ncursor = es->linelen; - else - ncursor = 0; - break; - - case '%': - ncursor = es->cursor; - while (ncursor < es->linelen && - (i = bracktype(es->cbuf[ncursor])) == 0) - ncursor++; - if (ncursor == es->linelen) - return -1; - bcount = 1; - do { - if (i > 0) { - if (++ncursor >= es->linelen) - return -1; - } else { - if (--ncursor < 0) - return -1; - } - t = bracktype(es->cbuf[ncursor]); - if (t == i) - bcount++; - else if (t == -i) - bcount--; - } while (bcount != 0); - if (sub && i > 0) - ncursor++; - break; - - default: - return -1; - } - return ncursor; -} - -static int -redo_insert(count) - int count; -{ - while (count-- > 0) - if (putbuf(ibuf, inslen, insert==REPLACE) != 0) - return -1; - if (es->cursor > 0) - es->cursor--; - insert = 0; - return 0; -} - -static void -yank_range(a, b) - int a, b; -{ - yanklen = b - a; - if (yanklen != 0) - memmove(ybuf, &es->cbuf[a], yanklen); -} - -static int -bracktype(ch) - int ch; -{ - switch (ch) { - - case '(': - return 1; - - case '[': - return 2; - - case '{': - return 3; - - case ')': - return -1; - - case ']': - return -2; - - case '}': - return -3; - - default: - return 0; - } -} - -/* - * Non user interface editor routines below here - */ - -static int cur_col; /* current column on line */ -static int pwidth; /* width of prompt */ -static int prompt_trunc; /* how much of prompt to truncate */ -static int prompt_skip; /* how much of prompt to skip */ -static int winwidth; /* width of window */ -static char *wbuf[2]; /* window buffers */ -static int wbuf_len; /* length of window buffers (x_cols-3)*/ -static int win; /* window buffer in use */ -static char morec; /* more character at right of window */ -static int lastref; /* argument to last refresh() */ -static char holdbuf[CMDLEN]; /* place to hold last edit buffer */ -static int holdlen; /* length of holdbuf */ - -static void -save_cbuf() -{ - memmove(holdbuf, es->cbuf, es->linelen); - holdlen = es->linelen; - holdbuf[holdlen] = '\0'; -} - -static void -restore_cbuf() -{ - es->cursor = 0; - es->linelen = holdlen; - memmove(es->cbuf, holdbuf, holdlen); -} - -/* return a new edstate */ -static struct edstate * -save_edstate(old) - struct edstate *old; -{ - struct edstate *new; - - new = (struct edstate *)alloc(sizeof(struct edstate), APERM); - new->cbuf = alloc(old->cbufsize, APERM); - memcpy(new->cbuf, old->cbuf, old->linelen); - new->cbufsize = old->cbufsize; - new->linelen = old->linelen; - new->cursor = old->cursor; - new->winleft = old->winleft; - return new; -} - -static void -restore_edstate(new, old) - struct edstate *old, *new; -{ - memcpy(new->cbuf, old->cbuf, old->linelen); - new->linelen = old->linelen; - new->cursor = old->cursor; - new->winleft = old->winleft; - free_edstate(old); -} - -static void -free_edstate(old) - struct edstate *old; -{ - afree(old->cbuf, APERM); - afree((char *)old, APERM); -} - - - -static void -edit_reset(buf, len) - char *buf; - size_t len; -{ - const char *p; - - es = &ebuf; - es->cbuf = buf; - es->cbufsize = len; - undo = &undobuf; - undo->cbufsize = len; - - es->linelen = undo->linelen = 0; - es->cursor = undo->cursor = 0; - es->winleft = undo->winleft = 0; - - cur_col = pwidth = promptlen(prompt, &p); - prompt_skip = p - prompt; - if (pwidth > x_cols - 3 - MIN_EDIT_SPACE) { - cur_col = x_cols - 3 - MIN_EDIT_SPACE; - prompt_trunc = pwidth - cur_col; - pwidth -= prompt_trunc; - } else - prompt_trunc = 0; - if (!wbuf_len || wbuf_len != x_cols - 3) { - wbuf_len = x_cols - 3; - wbuf[0] = aresize(wbuf[0], wbuf_len, APERM); - wbuf[1] = aresize(wbuf[1], wbuf_len, APERM); - } - (void) memset(wbuf[0], ' ', wbuf_len); - (void) memset(wbuf[1], ' ', wbuf_len); - winwidth = x_cols - pwidth - 3; - win = 0; - morec = ' '; - lastref = 1; - holdlen = 0; -} - -/* - * this is used for calling x_escape() in complete_word() - */ -static int -x_vi_putbuf(s, len) - const char *s; - size_t len; -{ - return putbuf(s, len, 0); -} - -static int -putbuf(buf, len, repl) - const char *buf; - int len; - int repl; -{ - if (len == 0) - return 0; - if (repl) { - if (es->cursor + len >= es->cbufsize) - return -1; - if (es->cursor + len > es->linelen) - es->linelen = es->cursor + len; - } else { - if (es->linelen + len >= es->cbufsize) - return -1; - memmove(&es->cbuf[es->cursor + len], &es->cbuf[es->cursor], - es->linelen - es->cursor); - es->linelen += len; - } - memmove(&es->cbuf[es->cursor], buf, len); - es->cursor += len; - return 0; -} - -static void -del_range(a, b) - int a, b; -{ - if (es->linelen != b) - memmove(&es->cbuf[a], &es->cbuf[b], es->linelen - b); - es->linelen -= b - a; -} - -static int -findch(ch, cnt, forw, incl) - int ch; - int cnt; - int forw; - int incl; -{ - int ncursor; - - if (es->linelen == 0) - return -1; - ncursor = es->cursor; - while (cnt--) { - do { - if (forw) { - if (++ncursor == es->linelen) - return -1; - } else { - if (--ncursor < 0) - return -1; - } - } while (es->cbuf[ncursor] != ch); - } - if (!incl) { - if (forw) - ncursor--; - else - ncursor++; - } - return ncursor; -} - -static int -forwword(argcnt) - int argcnt; -{ - int ncursor; - - ncursor = es->cursor; - while (ncursor < es->linelen && argcnt--) { - if (is_wordch(es->cbuf[ncursor])) - while (is_wordch(es->cbuf[ncursor]) && - ncursor < es->linelen) - ncursor++; - else if (!isspace((unsigned char)es->cbuf[ncursor])) - while (!is_wordch(es->cbuf[ncursor]) && - !isspace((unsigned char)es->cbuf[ncursor]) && - ncursor < es->linelen) - ncursor++; - while (isspace((unsigned char)es->cbuf[ncursor]) && ncursor < es->linelen) - ncursor++; - } - return ncursor; -} - -static int -backword(argcnt) - int argcnt; -{ - int ncursor; - - ncursor = es->cursor; - while (ncursor > 0 && argcnt--) { - while (--ncursor > 0 && isspace((unsigned char)es->cbuf[ncursor])) - ; - if (ncursor > 0) { - if (is_wordch(es->cbuf[ncursor])) - while (--ncursor >= 0 && - is_wordch(es->cbuf[ncursor])) - ; - else - while (--ncursor >= 0 && - !is_wordch(es->cbuf[ncursor]) && - !isspace((unsigned char)es->cbuf[ncursor])) - ; - ncursor++; - } - } - return ncursor; -} - -static int -endword(argcnt) - int argcnt; -{ - int ncursor; - - ncursor = es->cursor; - while (ncursor < es->linelen && argcnt--) { - while (++ncursor < es->linelen - 1 && - isspace((unsigned char)es->cbuf[ncursor])) - ; - if (ncursor < es->linelen - 1) { - if (is_wordch(es->cbuf[ncursor])) - while (++ncursor < es->linelen && - is_wordch(es->cbuf[ncursor])) - ; - else - while (++ncursor < es->linelen && - !is_wordch(es->cbuf[ncursor]) && - !isspace((unsigned char)es->cbuf[ncursor])) - ; - ncursor--; - } - } - return ncursor; -} - -static int -Forwword(argcnt) - int argcnt; -{ - int ncursor; - - ncursor = es->cursor; - while (ncursor < es->linelen && argcnt--) { - while (!isspace((unsigned char)es->cbuf[ncursor]) && ncursor < es->linelen) - ncursor++; - while (isspace((unsigned char)es->cbuf[ncursor]) && ncursor < es->linelen) - ncursor++; - } - return ncursor; -} - -static int -Backword(argcnt) - int argcnt; -{ - int ncursor; - - ncursor = es->cursor; - while (ncursor > 0 && argcnt--) { - while (--ncursor >= 0 && isspace((unsigned char)es->cbuf[ncursor])) - ; - while (ncursor >= 0 && !isspace((unsigned char)es->cbuf[ncursor])) - ncursor--; - ncursor++; - } - return ncursor; -} - -static int -Endword(argcnt) - int argcnt; -{ - int ncursor; - - ncursor = es->cursor; - while (ncursor < es->linelen - 1 && argcnt--) { - while (++ncursor < es->linelen - 1 && - isspace((unsigned char)es->cbuf[ncursor])) - ; - if (ncursor < es->linelen - 1) { - while (++ncursor < es->linelen && - !isspace((unsigned char)es->cbuf[ncursor])) - ; - ncursor--; - } - } - return ncursor; -} - -static int -grabhist(save, n) - int save; - int n; -{ - char *hptr; - - if (n < 0 || n > hlast) - return -1; - if (n == hlast) { - restore_cbuf(); - ohnum = n; - return 0; - } - (void) histnum(n); - if ((hptr = *histpos()) == NULL) { - internal_errorf(0, "grabhist: bad history array"); - return -1; - } - if (save) - save_cbuf(); - if ((es->linelen = strlen(hptr)) >= es->cbufsize) - es->linelen = es->cbufsize - 1; - memmove(es->cbuf, hptr, es->linelen); - es->cursor = 0; - ohnum = n; - return 0; -} - -static int -grabsearch(save, start, fwd, pat) - int save, start, fwd; - char *pat; -{ - char *hptr; - int hist; - int anchored; - - if ((start == 0 && fwd == 0) || (start >= hlast-1 && fwd == 1)) - return -1; - if (fwd) - start++; - else - start--; - anchored = *pat == '^' ? (++pat, 1) : 0; - if ((hist = findhist(start, fwd, pat, anchored)) < 0) { - /* if (start != 0 && fwd && match(holdbuf, pat) >= 0) { */ - /* XXX should FILECMP be strncmp? */ - if (start != 0 && fwd && FILECMP(holdbuf, pat) >= 0) { - restore_cbuf(); - return 0; - } else - return -1; - } - if (save) - save_cbuf(); - histnum(hist); - hptr = *histpos(); - if ((es->linelen = strlen(hptr)) >= es->cbufsize) - es->linelen = es->cbufsize - 1; - memmove(es->cbuf, hptr, es->linelen); - es->cursor = 0; - return hist; -} - -static void -redraw_line(newlinex) - int newlinex; -{ - (void) memset(wbuf[win], ' ', wbuf_len); - if (newlinex) { - x_putc('\r'); - x_putc('\n'); - } - vi_pprompt(0); - cur_col = pwidth; - morec = ' '; -} - -static void -refresh(leftside) - int leftside; -{ - if (leftside < 0) - leftside = lastref; - else - lastref = leftside; - if (outofwin()) - rewindow(); - display(wbuf[1 - win], wbuf[win], leftside); - win = 1 - win; -} - -static int -outofwin() -{ - int cur, col; - - if (es->cursor < es->winleft) - return 1; - col = 0; - cur = es->winleft; - while (cur < es->cursor) - col = newcol((unsigned char) es->cbuf[cur++], col); - if (col >= winwidth) - return 1; - return 0; -} - -static void -rewindow() -{ - register int tcur, tcol; - int holdcur1, holdcol1; - int holdcur2, holdcol2; - - holdcur1 = holdcur2 = tcur = 0; - holdcol1 = holdcol2 = tcol = 0; - while (tcur < es->cursor) { - if (tcol - holdcol2 > winwidth / 2) { - holdcur1 = holdcur2; - holdcol1 = holdcol2; - holdcur2 = tcur; - holdcol2 = tcol; - } - tcol = newcol((unsigned char) es->cbuf[tcur++], tcol); - } - while (tcol - holdcol1 > winwidth / 2) - holdcol1 = newcol((unsigned char) es->cbuf[holdcur1++], - holdcol1); - es->winleft = holdcur1; -} - -static int -newcol(ch, col) - int ch, col; -{ - if (ch == '\t') - return (col | 7) + 1; - return col + char_len(ch); -} - -static void -display(wb1, wb2, leftside) - char *wb1, *wb2; - int leftside; -{ - unsigned char ch; - char *twb1, *twb2, mc; - int cur, col, cnt; - int UNINITIALIZED(ncol); - int moreright; - - col = 0; - cur = es->winleft; - moreright = 0; - twb1 = wb1; - while (col < winwidth && cur < es->linelen) { - if (cur == es->cursor && leftside) - ncol = col + pwidth; - if ((ch = es->cbuf[cur]) == '\t') { - do { - *twb1++ = ' '; - } while (++col < winwidth && (col & 7) != 0); - } else { - if ((ch & 0x80) && Flag(FVISHOW8)) { - *twb1++ = 'M'; - if (++col < winwidth) { - *twb1++ = '-'; - col++; - } - ch &= 0x7f; - } - if (col < winwidth) { - if (ch < ' ' || ch == 0x7f) { - *twb1++ = '^'; - if (++col < winwidth) { - *twb1++ = ch ^ '@'; - col++; - } - } else { - *twb1++ = ch; - col++; - } - } - } - if (cur == es->cursor && !leftside) - ncol = col + pwidth - 1; - cur++; - } - if (cur == es->cursor) - ncol = col + pwidth; - if (col < winwidth) { - while (col < winwidth) { - *twb1++ = ' '; - col++; - } - } else - moreright++; - *twb1 = ' '; - - col = pwidth; - cnt = winwidth; - twb1 = wb1; - twb2 = wb2; - while (cnt--) { - if (*twb1 != *twb2) { - if (cur_col != col) - ed_mov_opt(col, wb1); - x_putc(*twb1); - cur_col++; - } - twb1++; - twb2++; - col++; - } - if (es->winleft > 0 && moreright) - /* POSIX says to use * for this but that is a globbing - * character and may confuse people; + is more innocuous - */ - mc = '+'; - else if (es->winleft > 0) - mc = '<'; - else if (moreright) - mc = '>'; - else - mc = ' '; - if (mc != morec) { - ed_mov_opt(pwidth + winwidth + 1, wb1); - x_putc(mc); - cur_col++; - morec = mc; - } - if (cur_col != ncol) - ed_mov_opt(ncol, wb1); -} - -static void -ed_mov_opt(col, wb) - int col; - char *wb; -{ - if (col < cur_col) { - if (col + 1 < cur_col - col) { - x_putc('\r'); - vi_pprompt(0); - cur_col = pwidth; - while (cur_col++ < col) - x_putc(*wb++); - } else { - while (cur_col-- > col) - x_putc('\b'); - } - } else { - wb = &wb[cur_col - pwidth]; - while (cur_col++ < col) - x_putc(*wb++); - } - cur_col = col; -} - - -/* replace word with all expansions (ie, expand word*) */ -static int -expand_word(commandx) - int commandx; -{ - static struct edstate *buf; - int rval = 0; - int nwords; - int start, end; - char **words; - int i; - - /* Undo previous expansion */ - if (commandx == 0 && expanded == EXPAND && buf) { - restore_edstate(es, buf); - buf = 0; - expanded = NONE; - return 0; - } - if (buf) { - free_edstate(buf); - buf = 0; - } - - nwords = x_cf_glob(XCF_COMMAND_FILE|XCF_FULLPATH, - es->cbuf, es->linelen, es->cursor, - &start, &end, &words, (int *) 0); - if (nwords == 0) { - vi_error(); - return -1; - } - - buf = save_edstate(es); - expanded = EXPAND; - del_range(start, end); - es->cursor = start; - for (i = 0; i < nwords; ) { - if (x_escape(words[i], strlen(words[i]), x_vi_putbuf) != 0) { - rval = -1; - break; - } - if (++i < nwords && putbuf(space, 1, 0) != 0) { - rval = -1; - break; - } - } - i = buf->cursor - end; - if (rval == 0 && i > 0) - es->cursor += i; - modified = 1; hnum = hlast; - insert = INSERT; - lastac = 0; - refresh(0); - return rval; -} - -static int -complete_word(commandx, count) - int commandx; - int count; -{ - static struct edstate *buf; - int rval = 0; - int nwords; - int start, end; - char **words; - char *match; - int match_len; - int is_unique; - int is_command; - - /* Undo previous completion */ - if (commandx == 0 && expanded == COMPLETE && buf) { - print_expansions(buf, 0); - expanded = PRINT; - return 0; - } - if (commandx == 0 && expanded == PRINT && buf) { - restore_edstate(es, buf); - buf = 0; - expanded = NONE; - return 0; - } - if (buf) { - free_edstate(buf); - buf = 0; - } - - /* XCF_FULLPATH for count 'cause the menu printed by print_expansions() - * was done this way. - */ - nwords = x_cf_glob(XCF_COMMAND_FILE | (count ? XCF_FULLPATH : 0), - es->cbuf, es->linelen, es->cursor, - &start, &end, &words, &is_command); - if (nwords == 0) { - vi_error(); - return -1; - } - if (count) { - int i; - - count--; - if (count >= nwords) { - vi_error(); - x_print_expansions(nwords, words, is_command); - x_free_words(nwords, words); - redraw_line(0); - return -1; - } - /* - * Expand the count'th word to its basename - */ - if (is_command) { - match = words[count] - + x_basename(words[count], (char *) 0); - /* If more than one possible match, use full path */ - for (i = 0; i < nwords; i++) - if (i != count && - FILECMP(words[i] - + x_basename(words[i], (char *) 0), - match) == 0) - { - match = words[count]; - break; - } - } else - match = words[count]; - match_len = strlen(match); - is_unique = 1; - /* expanded = PRINT; next call undo */ - } else { - match = words[0]; - match_len = x_longest_prefix(nwords, words); - expanded = COMPLETE; /* next call will list completions */ - is_unique = nwords == 1; - } - - buf = save_edstate(es); - del_range(start, end); - es->cursor = start; - - /* escape all shell-sensitive characters and put the result into - * command buffer */ - rval = x_escape(match, match_len, x_vi_putbuf); - - if (rval == 0 && is_unique) { - /* If exact match, don't undo. Allows directory completions - * to be used (ie, complete the next portion of the path). - */ - expanded = NONE; - - /* If not a directory, add a space to the end... */ - if (match_len > 0 && !ISDIRSEP(match[match_len - 1])) - rval = putbuf(space, 1, 0); - } - x_free_words(nwords, words); - - modified = 1; hnum = hlast; - insert = INSERT; - lastac = 0; /* prevent this from being redone... */ - refresh(0); - - return rval; -} - -static int -print_expansions(ex, commandx) - struct edstate *ex; - int commandx; -{ - int nwords; - int start, end; - char **words; - int is_command; - - nwords = x_cf_glob(XCF_COMMAND_FILE|XCF_FULLPATH, - ex->cbuf, ex->linelen, ex->cursor, - &start, &end, &words, &is_command); - if (nwords == 0) { - vi_error(); - return -1; - } - x_print_expansions(nwords, words, is_command); - x_free_words(nwords, words); - redraw_line(0); - return 0; -} - -/* How long is char when displayed (not counting tabs) */ -static int -char_len(c) - int c; -{ - int len = 1; - - if ((c & 0x80) && Flag(FVISHOW8)) { - len += 2; - c &= 0x7f; - } - if (c < ' ' || c == 0x7f) - len++; - return len; -} - -/* Similar to x_zotc(emacs.c), but no tab weirdness */ -static void -x_vi_zotc(c) - int c; -{ - if (Flag(FVISHOW8) && (c & 0x80)) { - x_puts("M-"); - c &= 0x7f; - } - if (c < ' ' || c == 0x7f) { - x_putc('^'); - c ^= '@'; - } - x_putc(c); -} - -static void -vi_pprompt(full) - int full; -{ - pprompt(prompt + (full ? 0 : prompt_skip), prompt_trunc); -} - -static void -vi_error() -{ - /* Beem out of any macros as soon as an error occurs */ - vi_macro_reset(); - x_putc(BEL); - x_flush(); -} - -static void -vi_macro_reset() -{ - if (macro.p) { - afree(macro.buf, APERM); - memset((char *) ¯o, 0, sizeof(macro)); - } -} - -#endif /* VI */ diff --git a/bin/ln/Makefile b/bin/ln/Makefile deleted file mode 100644 index 53e91d02a..000000000 --- a/bin/ln/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $NetBSD: Makefile,v 1.10 1999/09/27 17:44:50 jdolecek Exp $ -# @(#)Makefile 8.2 (Berkeley) 5/31/93 - -PROG= ln -MAN= ln.1 - -.include diff --git a/bin/ln/ln.1 b/bin/ln/ln.1 deleted file mode 100644 index 368897072..000000000 --- a/bin/ln/ln.1 +++ /dev/null @@ -1,173 +0,0 @@ -.\" $NetBSD: ln.1,v 1.25 2012/03/22 07:58:17 wiz Exp $ -.\" -.\" Copyright (c) 1980, 1990, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Institute of Electrical and Electronics Engineers, Inc. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)ln.1 8.2 (Berkeley) 12/30/93 -.\" -.Dd October 29, 2007 -.Dt LN 1 -.Os -.Sh NAME -.Nm ln -.Nd make links -.Sh SYNOPSIS -.Nm -.Op Fl fhinsv -.Ar source_file -.Op Ar target_file -.Nm -.Op Fl fhinsv -.Ar source_file ... target_dir -.Sh DESCRIPTION -The -.Nm -utility creates a new directory entry (linked file) which has the -same modes as the original file. -It is useful for maintaining multiple copies of a file in many places -at once without using up storage for the -.Dq copies ; -instead, a link -.Dq points -to the original copy. -There are two types of links: hard links and symbolic links. -How a link -.Dq points -to a file is one of the differences between a hard or symbolic link. -.Pp -The options are as follows: -.Bl -tag -width flag -.It Fl f -Unlink any already existing file, permitting the link to occur. -.It Fl h -If the -.Ar target_file -or -.Ar target_dir -is a symbolic link, do not follow it. -This is most useful with the -.Fl f -option, to replace a symlink which may point to a directory. -.It Fl i -Cause -.Nm -to write a prompt to standard error if the target file exists. -If the response from the standard input begins with the character -.Sq Li y -or -.Sq Li Y , -then unlink the target file so that the link may occur. -Otherwise, do not attempt the link. -(The -.Fl i -option overrides any previous -.Fl f -options.) -.It Fl n -Same as -.Fl h , -for compatibility with other -.Nm -implementations, namely GNU coreutils. -.It Fl s -Create a symbolic link. -.It Fl v -Cause -.Nm -to be verbose, showing files as they are processed. -.El -.Pp -By default -.Nm -makes -.Em hard -links. -A hard link to a file is indistinguishable from the original directory entry; -any changes to a file are effective independent of the name used to reference -the file. -Hard links may not normally refer to directories and may not span file systems. -.Pp -A symbolic link contains the name of the file to -which it is linked. -The referenced file is used when an -.Xr open 2 -operation is performed on the link. -A -.Xr stat 2 -on a symbolic link will return the linked-to file; an -.Xr lstat 2 -must be done to obtain information about the link. -The -.Xr readlink 2 -call may be used to read the contents of a symbolic link. -Symbolic links may span file systems and may refer to directories. -.Pp -Given one or two arguments, -.Nm -creates a link to an existing file -.Ar source_file . -If -.Ar target_file -is given, the link has that name; -.Ar target_file -may also be a directory in which to place the link; -otherwise it is placed in the current directory. -If only the directory is specified, the link will be made -to the last component of -.Ar source_file . -.Pp -Given more than two arguments, -.Nm -makes links in -.Ar target_dir -to all the named source files. -The links made will have the same name as the files being linked to. -.Sh SEE ALSO -.Xr link 2 , -.Xr lstat 2 , -.Xr readlink 2 , -.Xr stat 2 , -.Xr symlink 2 , -.Xr symlink 7 -.Sh STANDARDS -The -.Nm -utility conforms to -.St -p1003.2-92 . -.Pp -The -.Fl v -option is an extension to -.St -p1003.2-92 . -.Sh HISTORY -A -.Nm -utility appeared in -.At v6 . diff --git a/bin/ln/ln.c b/bin/ln/ln.c deleted file mode 100644 index 912747774..000000000 --- a/bin/ln/ln.c +++ /dev/null @@ -1,230 +0,0 @@ -/* $NetBSD: ln.c,v 1.35 2011/08/29 14:38:30 joerg Exp $ */ - -/* - * Copyright (c) 1987, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1987, 1993, 1994\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)ln.c 8.2 (Berkeley) 3/31/94"; -#else -__RCSID("$NetBSD: ln.c,v 1.35 2011/08/29 14:38:30 joerg Exp $"); -#endif -#endif /* not lint */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -static int fflag; /* Unlink existing files. */ -static int hflag; /* Check new name for symlink first. */ -static int iflag; /* Interactive mode. */ -static int sflag; /* Symbolic, not hard, link. */ -static int vflag; /* Verbose output */ - - /* System link call. */ -static int (*linkf)(const char *, const char *); -static char linkch; - -static int linkit(const char *, const char *, int); -__dead static void usage(void); - -int -main(int argc, char *argv[]) -{ - struct stat sb; - int ch, exitval; - char *sourcedir; - - setprogname(argv[0]); - (void)setlocale(LC_ALL, ""); - - while ((ch = getopt(argc, argv, "fhinsv")) != -1) - switch (ch) { - case 'f': - fflag = 1; - iflag = 0; - break; - case 'h': - case 'n': - hflag = 1; - break; - case 'i': - iflag = 1; - fflag = 0; - break; - case 's': - sflag = 1; - break; - case 'v': - vflag = 1; - break; - case '?': - default: - usage(); - /* NOTREACHED */ - } - - argv += optind; - argc -= optind; - - if (sflag) { - linkf = symlink; - linkch = '-'; - } else { - linkf = link; - linkch = '='; - } - - switch(argc) { - case 0: - usage(); - /* NOTREACHED */ - case 1: /* ln target */ - exit(linkit(argv[0], ".", 1)); - /* NOTREACHED */ - case 2: /* ln target source */ - exit(linkit(argv[0], argv[1], 0)); - /* NOTREACHED */ - } - - /* ln target1 target2 directory */ - sourcedir = argv[argc - 1]; - if (hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) { - /* we were asked not to follow symlinks, but found one at - the target--simulate "not a directory" error */ - errno = ENOTDIR; - err(EXIT_FAILURE, "%s", sourcedir); - /* NOTREACHED */ - } - if (stat(sourcedir, &sb)) { - err(EXIT_FAILURE, "%s", sourcedir); - /* NOTREACHED */ - } - if (!S_ISDIR(sb.st_mode)) { - usage(); - /* NOTREACHED */ - } - for (exitval = 0; *argv != sourcedir; ++argv) - exitval |= linkit(*argv, sourcedir, 1); - exit(exitval); - /* NOTREACHED */ -} - -static int -linkit(const char *target, const char *source, int isdir) -{ - struct stat sb; - const char *p; - char path[MAXPATHLEN]; - int ch, exists, first; - - if (!sflag) { - /* If target doesn't exist, quit now. */ - if (stat(target, &sb)) { - warn("%s", target); - return (1); - } - } - - /* If the source is a directory (and not a symlink if hflag), - append the target's name. */ - if (isdir || - (!lstat(source, &sb) && S_ISDIR(sb.st_mode)) || - (!hflag && !stat(source, &sb) && S_ISDIR(sb.st_mode))) { - if ((p = strrchr(target, '/')) == NULL) - p = target; - else - ++p; - (void)snprintf(path, sizeof(path), "%s/%s", source, p); - source = path; - } - - exists = !lstat(source, &sb); - - /* - * If the file exists, then unlink it forcibly if -f was specified - * and interactively if -i was specified. - */ - if (fflag && exists) { - if (unlink(source)) { - warn("%s", source); - return (1); - } - } else if (iflag && exists) { - fflush(stdout); - (void)fprintf(stderr, "replace %s? ", source); - - first = ch = getchar(); - while (ch != '\n' && ch != EOF) - ch = getchar(); - if (first != 'y' && first != 'Y') { - (void)fprintf(stderr, "not replaced\n"); - return (1); - } - - if (unlink(source)) { - warn("%s", source); - return (1); - } - } - - /* Attempt the link. */ - if ((*linkf)(target, source)) { - warn("%s", source); - return (1); - } - if (vflag) - (void)printf("%s %c> %s\n", source, linkch, target); - - return (0); -} - -static void -usage(void) -{ - - (void)fprintf(stderr, - "usage:\t%s [-fhinsv] file1 file2\n\t%s [-fhinsv] file ... directory\n", - getprogname(), getprogname()); - exit(1); - /* NOTREACHED */ -} diff --git a/bin/ls/Makefile b/bin/ls/Makefile deleted file mode 100644 index 55497f661..000000000 --- a/bin/ls/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# $NetBSD: Makefile,v 1.14 2006/12/14 20:09:36 he Exp $ -# @(#)Makefile 8.1 (Berkeley) 6/2/93 - -PROG= ls -SRCS= cmp.c ls.c main.c print.c util.c - -LDADD+= -lutil -DPADD+= ${LIBUTIL} - -.include diff --git a/bin/ls/cmp.c b/bin/ls/cmp.c deleted file mode 100644 index 21d50e131..000000000 --- a/bin/ls/cmp.c +++ /dev/null @@ -1,199 +0,0 @@ -/* $NetBSD: cmp.c,v 1.17 2003/08/07 09:05:14 agc Exp $ */ - -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Michael Fischbein. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)cmp.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: cmp.c,v 1.17 2003/08/07 09:05:14 agc Exp $"); -#endif -#endif /* not lint */ - -#include -#include - -#include -#include - -#include "ls.h" -#include "extern.h" - -#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) || \ - defined(_XOPEN_SOURCE) || defined(__NetBSD__) -#define ATIMENSEC_CMP(x, op, y) ((x)->st_atimensec op (y)->st_atimensec) -#define CTIMENSEC_CMP(x, op, y) ((x)->st_ctimensec op (y)->st_ctimensec) -#define MTIMENSEC_CMP(x, op, y) ((x)->st_mtimensec op (y)->st_mtimensec) -#else -#define ATIMENSEC_CMP(x, op, y) \ - ((x)->st_atimespec.tv_nsec op (y)->st_atimespec.tv_nsec) -#define CTIMENSEC_CMP(x, op, y) \ - ((x)->st_ctimespec.tv_nsec op (y)->st_ctimespec.tv_nsec) -#define MTIMENSEC_CMP(x, op, y) \ - ((x)->st_mtimespec.tv_nsec op (y)->st_mtimespec.tv_nsec) -#endif - -int -namecmp(const FTSENT *a, const FTSENT *b) -{ - - return (strcmp(a->fts_name, b->fts_name)); -} - -int -revnamecmp(const FTSENT *a, const FTSENT *b) -{ - - return (strcmp(b->fts_name, a->fts_name)); -} - -int -modcmp(const FTSENT *a, const FTSENT *b) -{ - - if (b->fts_statp->st_mtime > a->fts_statp->st_mtime) - return (1); - else if (b->fts_statp->st_mtime < a->fts_statp->st_mtime) - return (-1); - else if (MTIMENSEC_CMP(b->fts_statp, >, a->fts_statp)) - return (1); - else if (MTIMENSEC_CMP(b->fts_statp, <, a->fts_statp)) - return (-1); - else - return (namecmp(a, b)); -} - -int -revmodcmp(const FTSENT *a, const FTSENT *b) -{ - - if (b->fts_statp->st_mtime > a->fts_statp->st_mtime) - return (-1); - else if (b->fts_statp->st_mtime < a->fts_statp->st_mtime) - return (1); - else if (MTIMENSEC_CMP(b->fts_statp, >, a->fts_statp)) - return (-1); - else if (MTIMENSEC_CMP(b->fts_statp, <, a->fts_statp)) - return (1); - else - return (revnamecmp(a, b)); -} - -int -acccmp(const FTSENT *a, const FTSENT *b) -{ - - if (b->fts_statp->st_atime > a->fts_statp->st_atime) - return (1); - else if (b->fts_statp->st_atime < a->fts_statp->st_atime) - return (-1); - else if (ATIMENSEC_CMP(b->fts_statp, >, a->fts_statp)) - return (1); - else if (ATIMENSEC_CMP(b->fts_statp, <, a->fts_statp)) - return (-1); - else - return (namecmp(a, b)); -} - -int -revacccmp(const FTSENT *a, const FTSENT *b) -{ - - if (b->fts_statp->st_atime > a->fts_statp->st_atime) - return (-1); - else if (b->fts_statp->st_atime < a->fts_statp->st_atime) - return (1); - else if (ATIMENSEC_CMP(b->fts_statp, >, a->fts_statp)) - return (-1); - else if (ATIMENSEC_CMP(b->fts_statp, <, a->fts_statp)) - return (1); - else - return (revnamecmp(a, b)); -} - -int -statcmp(const FTSENT *a, const FTSENT *b) -{ - - if (b->fts_statp->st_ctime > a->fts_statp->st_ctime) - return (1); - else if (b->fts_statp->st_ctime < a->fts_statp->st_ctime) - return (-1); - else if (CTIMENSEC_CMP(b->fts_statp, >, a->fts_statp)) - return (1); - else if (CTIMENSEC_CMP(b->fts_statp, <, a->fts_statp)) - return (-1); - else - return (namecmp(a, b)); -} - -int -revstatcmp(const FTSENT *a, const FTSENT *b) -{ - - if (b->fts_statp->st_ctime > a->fts_statp->st_ctime) - return (-1); - else if (b->fts_statp->st_ctime < a->fts_statp->st_ctime) - return (1); - else if (CTIMENSEC_CMP(b->fts_statp, >, a->fts_statp)) - return (-1); - else if (CTIMENSEC_CMP(b->fts_statp, <, a->fts_statp)) - return (1); - else - return (revnamecmp(a, b)); -} - -int -sizecmp(const FTSENT *a, const FTSENT *b) -{ - - if (b->fts_statp->st_size > a->fts_statp->st_size) - return (1); - if (b->fts_statp->st_size < a->fts_statp->st_size) - return (-1); - else - return (namecmp(a, b)); -} - -int -revsizecmp(const FTSENT *a, const FTSENT *b) -{ - - if (b->fts_statp->st_size > a->fts_statp->st_size) - return (-1); - if (b->fts_statp->st_size < a->fts_statp->st_size) - return (1); - else - return (revnamecmp(a, b)); -} diff --git a/bin/ls/extern.h b/bin/ls/extern.h deleted file mode 100644 index 0a9eea016..000000000 --- a/bin/ls/extern.h +++ /dev/null @@ -1,53 +0,0 @@ -/* $NetBSD: extern.h,v 1.17 2011/08/29 14:44:21 joerg Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)extern.h 8.1 (Berkeley) 5/31/93 - */ - -int acccmp(const FTSENT *, const FTSENT *); -int revacccmp(const FTSENT *, const FTSENT *); -int modcmp(const FTSENT *, const FTSENT *); -int revmodcmp(const FTSENT *, const FTSENT *); -int namecmp(const FTSENT *, const FTSENT *); -int revnamecmp(const FTSENT *, const FTSENT *); -int statcmp(const FTSENT *, const FTSENT *); -int revstatcmp(const FTSENT *, const FTSENT *); -int sizecmp(const FTSENT *, const FTSENT *); -int revsizecmp(const FTSENT *, const FTSENT *); - -int ls_main(int, char *[]); - -int printescaped(const char *); -void printacol(DISPLAY *); -void printcol(DISPLAY *); -void printlong(DISPLAY *); -void printscol(DISPLAY *); -void printstream(DISPLAY *); -int safe_print(const char *); diff --git a/bin/ls/ls.1 b/bin/ls/ls.1 deleted file mode 100644 index 39e3b5153..000000000 --- a/bin/ls/ls.1 +++ /dev/null @@ -1,516 +0,0 @@ -.\" $NetBSD: ls.1,v 1.79 2016/08/10 17:45:12 sevan Exp $ -.\" -.\" Copyright (c) 1980, 1990, 1991, 1993, 1994 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Institute of Electrical and Electronics Engineers, Inc. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)ls.1 8.7 (Berkeley) 7/29/94 -.\" -.Dd August 10, 2016 -.Dt LS 1 -.Os -.Sh NAME -.Nm ls -.Nd list directory contents -.Sh SYNOPSIS -.Nm -.Op Fl 1AaBbCcdFfghikLlMmnOoPpqRrSsTtuWwXx -.Op Ar -.Sh DESCRIPTION -For each -.Ar file -operand that names a file of a type other than -directory, -.Nm -displays its name as well as any requested, -associated information. -For each -.Ar file -operand that names a file of type directory, -.Nm -displays the names of files contained -within that directory, as well as any requested, associated -information. -.Pp -If no operands are given, the contents of the current -directory are displayed. -If more than one operand is given, -non-directory operands are displayed first; directory -and non-directory operands are sorted separately and in -lexicographical order. -.Pp -The following options are available: -.Bl -tag -width indent -.It Fl \&1 -(The numeric digit -.Dq one ) . -Force output to be one entry per line. -This is the default when output is not to a terminal. -.It Fl A -List all entries except for -.Ql \&. -and -.Ql \&.. . -Always set for the super-user. -.It Fl a -Include directory entries whose names begin with a -dot -.Pq Sq \&. . -.It Fl B -Force printing of non-graphic characters in file names as \exxx, where xxx -is the numeric value of the character in octal. -.It Fl b -As -.Fl B , -but use C escape codes whenever possible. -.It Fl C -Force multi-column output; this is the default when output is to a terminal. -.It Fl c -Use time when file status was last changed, -instead of time of last modification of the file for printing -.Pq Fl l -or sorting -.Pq Fl t . -Overrides -.Fl u . -.It Fl d -Directories are listed as plain files (not searched recursively) and -symbolic links in the argument list are not followed. -Turns off -.Fl R -if also given. -.It Fl F -Display a slash -.Pq Sq \&/ -immediately after each pathname that is a directory, -an asterisk -.Pq Sq \&* -after each that is executable, -an at sign -.Pq Sq \&@ -after each symbolic link, -a percent sign -.Pq Sq \&% -after each whiteout, -an equal sign -.Pq Sq \&= -after each socket, -and a vertical bar -.Pq Sq \&| -after each that is a -.Tn FIFO . -.It Fl f -Output is not sorted. -This option implies -.Fl a . -.It Fl g -The same as -.Fl l , -except that the owner is not printed. -.It Fl h -Modifies the -.Fl l -and -.Fl s -options, causing the sizes to be reported in bytes displayed in a human -readable format. -Overrides -.Fl k -and -.Fl M . -.It Fl i -For each file, print the file's file serial number (inode number). -.It Fl k -Modifies the -.Fl s -option, causing the sizes to be reported in kilobytes. -Overrides -.Fl h . -.It Fl L -For each file, if it's a link, evaluate file information and file type -of the referenced file and not the link itself; however still print -the link name, unless used with -.Fl l , -for example. -.It Fl l -(The lowercase letter -.Dq ell ) . -List in long format. -(See below.) -.It Fl M -Modifies the -.Fl l -and -.Fl s -options, causing the sizes or block counts reported to be separated with -commas (or a locale appropriate separator) resulting in a more readable -output. -Overrides -.Fl h ; -does not override -.Fl k . -.It Fl m -Stream output format; list files across the page, separated by commas. -.It Fl n -The same as -.Fl l , -except that -the owner and group IDs are displayed numerically rather than converting -to a owner or group name. -.It Fl O -Output only leaf files (not directories), eliding other -.Nm -output. -.It Fl o -Include the file flags in a long -.Pq Fl l -output. -If no file flags are set, -.Dq - -is displayed. -(See -.Xr chflags 1 -for a list of possible flags and their meanings.) -.It Fl P -Print the full pathname for each file. -.It Fl p -Display a slash -.Pq Sq \&/ -immediately after each pathname that is a directory. -.It Fl q -Force printing of non-printable characters in file names as -the character -.Sq \&? ; -this is the default when output is to a terminal. -.It Fl R -Recursively list subdirectories encountered. -See also -.Fl d . -.It Fl r -Reverse the order of the sort to get reverse -lexicographical order or the smallest or oldest entries first. -.It Fl S -Sort by size, largest file first. -.It Fl s -Display the number of file system blocks actually used by each file, in units -of 512 bytes or -.Ev BLOCKSIZE -(see -.Sx ENVIRONMENT ) -where partial units are rounded up to the -next integer value. -If the output is to a terminal, a total sum for all the file -sizes is output on a line before the listing. -.It Fl T -When used with the -.Fl l -(the lowercase letter -.Dq ell ) -option, display complete time information for the file, including -month, day, hour, minute, second, and year. -.It Fl t -Sort by time modified (most recently modified -first) before sorting the operands by lexicographical -order. -.It Fl u -Use time of last access, -instead of last modification -of the file for printing -.Pq Fl l -or sorting -.Pq Fl t . -Overrides -.Fl c . -.It Fl W -Display whiteouts when scanning directories. -.It Fl w -Force raw printing of non-printable characters. -This is the default when output is not to a terminal. -.It Fl x -Multi-column output sorted across the page rather than down the page. -.It Fl X -Don't cross mount points when recursing. -.El -.Pp -The -.Fl B , -.Fl b , -.Fl q , -and -.Fl w -options all override each other; the last one specified determines -the format used for non-printable characters. -.Pp -The -.Fl 1 , -.Fl C , -.Fl g , -.Fl l , -.Fl m , -and -.Fl x -options all override each other; the last one specified determines -the format used with the exception that if both -.Fl l -and -.Fl g -are specified, -.Fl l -will always override -.Fl g , -even if -.Fl g -was specified last. -.Pp -By default, -.Nm -lists one entry per line to standard -output; the exceptions are to terminals or when the -.Fl C -or -.Fl m -options are specified. -.Pp -File information is displayed with one or more -.Aq blank -characters separating the information associated with the -.Fl i , -.Fl l , -and -.Fl s -options. -.Ss The Long Format -If the -.Fl l -option is given, the following information -is displayed for each file: -.Bl -item -offset indent -compact -.It -file mode -.It -number of links -.It -owner name -.It -group name -.It -file flags (if -.Fl o -given) -.It -number of bytes in the file -.It -abbreviated month file was last modified -.It -day-of-month file was last modified -.It -hour and minute file was last modified -.It -pathname -.El -.Pp -In addition, for each directory whose contents are displayed, the total -number of file system blocks in units of 512 bytes or -.Ev BLOCKSIZE -(see -.Sx ENVIRONMENT ) -used by the files in the directory is displayed on a line by itself -immediately before the information for the files in the directory. -.Pp -If the owner or group names are not a known owner or group name, -or the -.Fl n -option is given, -the numeric ID's are displayed. -.Pp -If the file is a character special or block special file, -the major and minor device numbers for the file are displayed -in the size field. -If the file is a symbolic link the pathname of the -linked-to file is preceded by -.Dq \-\*[Gt] . -.Pp -The file mode printed under the -.Fl l -option consists of the entry type, owner permissions, group -permissions, and other permissions. -The entry type character describes the type of file, as -follows: -.Pp -.Bl -tag -width 4n -offset indent -compact -.It Sy \- -Regular file. -.It Sy a -Archive state 1. -.It Sy A -Archive state 2. -.It Sy b -Block special file. -.It Sy c -Character special file. -.It Sy d -Directory. -.It Sy l -Symbolic link. -.It Sy p -FIFO. -.It Sy s -Socket link. -.It Sy w -Whiteout. -.El -.Pp -The next three fields -are three characters each: -owner permissions, -group permissions, and -other permissions. -Each field has three character positions: -.Bl -enum -offset indent -.It -If -.Sy r , -the file is readable; if -.Sy \- , -it is not readable. -.It -If -.Sy w , -the file is writable; if -.Sy \- , -it is not writable. -.It -The first of the following that applies: -.Bl -tag -width 4n -offset indent -.It Sy S -If in the owner permissions, the file is not executable and -set-user-ID mode is set. -If in the group permissions, the file is not executable -and set-group-ID mode is set. -.It Sy s -If in the owner permissions, the file is executable -and set-user-ID mode is set. -If in the group permissions, the file is executable -and setgroup-ID mode is set. -.It Sy x -The file is executable or the directory is -searchable. -.It Sy \- -The file is neither readable, writable, executable, -nor set-user-ID nor set-group-ID mode, nor sticky. -(See below.) -.El -.Pp -These next two apply only to the third character in the last group -(other permissions). -.Bl -tag -width 4n -offset indent -.It Sy T -The sticky bit is set -(mode -.Li 1000 ) , -but not execute or search permission. -(See -.Xr chmod 1 -or -.Xr sticky 7 . ) -.It Sy t -The sticky bit is set (mode -.Li 1000 ) , -and is searchable or executable. -(See -.Xr chmod 1 -or -.Xr sticky 7 . ) -.El -.El -.Pp -The number of bytes displayed for a directory is a function of the -number of -.Xr dirent 3 -structures in the directory, not all of which may be allocated to -any existing file. -.Sh ENVIRONMENT -The following environment variables affect the execution of -.Nm : -.Bl -tag -width BLOCKSIZE -.It Ev BLOCKSIZE -If the environment variable -.Ev BLOCKSIZE -is set, and the -.Fl k -option is not specified, the block counts -(see -.Fl l -and -.Fl s ) -will be displayed in units of that size block. -.It Ev COLUMNS -If this variable contains a string representing a -decimal integer, it is used as the -column position width for displaying -multiple-text-column output. -The -.Nm -utility calculates how -many pathname text columns to display -based on the width provided. -(See -.Fl C . ) -.It Ev TZ -The timezone to use when displaying dates. -See -.Xr environ 7 -for more information. -.El -.Sh EXIT STATUS -.Ex -std -.Sh COMPATIBILITY -The group field is now automatically included in the long listing for -files in order to be compatible with the -.St -p1003.2 -specification. -.Sh SEE ALSO -.Xr chflags 1 , -.Xr chmod 1 , -.Xr stat 2 , -.Xr dirent 3 , -.Xr getbsize 3 , -.Xr sticky 7 , -.Xr symlink 7 -.Sh STANDARDS -The -.Nm -utility is expected to be a superset of the -.St -p1003.2 -specification. -.Sh HISTORY -An -.Nm -utility appeared in -.At v1 . diff --git a/bin/ls/ls.c b/bin/ls/ls.c deleted file mode 100644 index 282207f90..000000000 --- a/bin/ls/ls.c +++ /dev/null @@ -1,715 +0,0 @@ -/* $NetBSD: ls.c,v 1.76 2017/02/06 21:06:04 rin Exp $ */ - -/* - * Copyright (c) 1989, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Michael Fischbein. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)ls.c 8.7 (Berkeley) 8/5/94"; -#else -__RCSID("$NetBSD: ls.c,v 1.76 2017/02/06 21:06:04 rin Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ls.h" -#include "extern.h" - -static void display(FTSENT *, FTSENT *); -static int mastercmp(const FTSENT **, const FTSENT **); -static void traverse(int, char **, int); - -static void (*printfcn)(DISPLAY *); -static int (*sortfcn)(const FTSENT *, const FTSENT *); - -#define BY_NAME 0 -#define BY_SIZE 1 -#define BY_TIME 2 - -long blocksize; /* block size units */ -int termwidth = 80; /* default terminal width */ -int sortkey = BY_NAME; -int rval = EXIT_SUCCESS; /* exit value - set if error encountered */ - -/* flags */ -int f_accesstime; /* use time of last access */ -int f_column; /* columnated format */ -int f_columnacross; /* columnated format, sorted across */ -int f_flags; /* show flags associated with a file */ -int f_grouponly; /* long listing without owner */ -int f_humanize; /* humanize the size field */ -int f_commas; /* separate size field with comma */ -int f_inode; /* print inode */ -int f_listdir; /* list actual directory, not contents */ -int f_listdot; /* list files beginning with . */ -int f_longform; /* long listing format */ -int f_nonprint; /* show unprintables as ? */ -int f_nosort; /* don't sort output */ -int f_numericonly; /* don't convert uid/gid to name */ -int f_octal; /* print octal escapes for nongraphic characters */ -int f_octal_escape; /* like f_octal but use C escapes if possible */ -int f_recursive; /* ls subdirectories also */ -int f_reversesort; /* reverse whatever sort is used */ -int f_sectime; /* print the real time for all files */ -int f_singlecol; /* use single column output */ -int f_size; /* list size in short listing */ -int f_statustime; /* use time of last mode change */ -int f_stream; /* stream format */ -int f_type; /* add type character for non-regular files */ -int f_typedir; /* add type character for directories */ -int f_whiteout; /* show whiteout entries */ -int f_fullpath; /* print full pathname, not filename */ -int f_leafonly; /* when recursing, print leaf names only */ - -__dead static void -usage(void) -{ - - (void)fprintf(stderr, - "usage: %s [-1AaBbCcdFfghikLlMmnOoPpqRrSsTtuWwXx] [file ...]\n", - getprogname()); - exit(EXIT_FAILURE); - /* NOTREACHED */ -} - -int -ls_main(int argc, char *argv[]) -{ - static char dot[] = ".", *dotav[] = { dot, NULL }; - struct winsize win; - int ch, fts_options; - int kflag = 0; - const char *p; - - setprogname(argv[0]); - (void)setlocale(LC_ALL, ""); - - /* Terminal defaults to -Cq, non-terminal defaults to -1. */ - if (isatty(STDOUT_FILENO)) { - if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == 0 && - win.ws_col > 0) - termwidth = win.ws_col; - f_column = f_nonprint = 1; - } else - f_singlecol = 1; - - /* Root is -A automatically. */ - if (!getuid()) - f_listdot = 1; - - fts_options = FTS_PHYSICAL; - while ((ch = getopt(argc, argv, "1AaBbCcdFfghikLlMmnOoPpqRrSsTtuWwXx")) - != -1) { - switch (ch) { - /* - * The -1, -C, -l, -m and -x options all override each other so - * shell aliasing works correctly. - */ - case '1': - f_singlecol = 1; - f_column = f_columnacross = f_longform = f_stream = 0; - break; - case 'C': - f_column = 1; - f_columnacross = f_longform = f_singlecol = f_stream = - 0; - break; - case 'g': - if (f_grouponly != -1) - f_grouponly = 1; - f_longform = 1; - f_column = f_columnacross = f_singlecol = f_stream = 0; - break; - case 'l': - f_longform = 1; - f_column = f_columnacross = f_singlecol = f_stream = 0; - /* Never let -g take precedence over -l. */ - f_grouponly = -1; - break; - case 'm': - f_stream = 1; - f_column = f_columnacross = f_longform = f_singlecol = - 0; - break; - case 'x': - f_columnacross = 1; - f_column = f_longform = f_singlecol = f_stream = 0; - break; - /* The -c and -u options override each other. */ - case 'c': - f_statustime = 1; - f_accesstime = 0; - break; - case 'u': - f_accesstime = 1; - f_statustime = 0; - break; - case 'F': - f_type = 1; - break; - case 'L': - fts_options &= ~FTS_PHYSICAL; - fts_options |= FTS_LOGICAL; - break; - case 'R': - f_recursive = 1; - break; - case 'f': - f_nosort = 1; - /* FALLTHROUGH */ - case 'a': - fts_options |= FTS_SEEDOT; - /* FALLTHROUGH */ - case 'A': - f_listdot = 1; - break; - /* The -B option turns off the -b, -q and -w options. */ - case 'B': - f_nonprint = 0; - f_octal = 1; - f_octal_escape = 0; - break; - /* The -b option turns off the -B, -q and -w options. */ - case 'b': - f_nonprint = 0; - f_octal = 0; - f_octal_escape = 1; - break; - /* The -d option turns off the -R option. */ - case 'd': - f_listdir = 1; - f_recursive = 0; - break; - case 'i': - f_inode = 1; - break; - case 'k': - blocksize = 1024; - kflag = 1; - f_humanize = 0; - break; - /* The -h option forces all sizes to be measured in bytes. */ - case 'h': - f_humanize = 1; - kflag = 0; - f_commas = 0; - break; - case 'M': - f_humanize = 0; - f_commas = 1; - break; - case 'n': - f_numericonly = 1; - f_longform = 1; - f_column = f_columnacross = f_singlecol = f_stream = 0; - break; - case 'O': - f_leafonly = 1; - break; - case 'o': - f_flags = 1; - break; - case 'P': - f_fullpath = 1; - break; - case 'p': - f_typedir = 1; - break; - /* The -q option turns off the -B, -b and -w options. */ - case 'q': - f_nonprint = 1; - f_octal = 0; - f_octal_escape = 0; - break; - case 'r': - f_reversesort = 1; - break; - case 'S': - sortkey = BY_SIZE; - break; - case 's': - f_size = 1; - break; - case 'T': - f_sectime = 1; - break; - case 't': - sortkey = BY_TIME; - break; - case 'W': - f_whiteout = 1; - break; - /* The -w option turns off the -B, -b and -q options. */ - case 'w': - f_nonprint = 0; - f_octal = 0; - f_octal_escape = 0; - break; - case 'X': - fts_options |= FTS_XDEV; - break; - default: - case '?': - usage(); - } - } - argc -= optind; - argv += optind; - - if (f_column || f_columnacross || f_stream) { - if ((p = getenv("COLUMNS")) != NULL) - termwidth = atoi(p); - } - - /* - * If both -g and -l options, let -l take precedence. - */ - if (f_grouponly == -1) - f_grouponly = 0; - - /* - * If not -F, -i, -l, -p, -S, -s or -t options, don't require stat - * information. - */ - if (!f_inode && !f_longform && !f_size && !f_type && !f_typedir && - sortkey == BY_NAME) - fts_options |= FTS_NOSTAT; - - /* - * If not -F, -d or -l options, follow any symbolic links listed on - * the command line. - */ - if (!f_longform && !f_listdir && !f_type) - fts_options |= FTS_COMFOLLOW; - - /* - * If -W, show whiteout entries - */ -#ifdef FTS_WHITEOUT - if (f_whiteout) - fts_options |= FTS_WHITEOUT; -#endif - - /* If -i, -l, or -s, figure out block size. */ - if (f_inode || f_longform || f_size) { - if (!kflag) - (void)getbsize(NULL, &blocksize); - blocksize /= 512; - } - - /* Select a sort function. */ - if (f_reversesort) { - switch (sortkey) { - case BY_NAME: - sortfcn = revnamecmp; - break; - case BY_SIZE: - sortfcn = revsizecmp; - break; - case BY_TIME: - if (f_accesstime) - sortfcn = revacccmp; - else if (f_statustime) - sortfcn = revstatcmp; - else /* Use modification time. */ - sortfcn = revmodcmp; - break; - } - } else { - switch (sortkey) { - case BY_NAME: - sortfcn = namecmp; - break; - case BY_SIZE: - sortfcn = sizecmp; - break; - case BY_TIME: - if (f_accesstime) - sortfcn = acccmp; - else if (f_statustime) - sortfcn = statcmp; - else /* Use modification time. */ - sortfcn = modcmp; - break; - } - } - - /* Select a print function. */ - if (f_singlecol) - printfcn = printscol; - else if (f_columnacross) - printfcn = printacol; - else if (f_longform) - printfcn = printlong; - else if (f_stream) - printfcn = printstream; - else - printfcn = printcol; - - if (argc) - traverse(argc, argv, fts_options); - else - traverse(1, dotav, fts_options); - return rval; - /* NOTREACHED */ -} - -static int output; /* If anything output. */ - -/* - * Traverse() walks the logical directory structure specified by the argv list - * in the order specified by the mastercmp() comparison function. During the - * traversal it passes linked lists of structures to display() which represent - * a superset (may be exact set) of the files to be displayed. - */ -static void -traverse(int argc, char *argv[], int options) -{ - FTS *ftsp; - FTSENT *p, *chp; - int ch_options, error; - - if ((ftsp = - fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL) - err(EXIT_FAILURE, NULL); - - display(NULL, fts_children(ftsp, 0)); - if (f_listdir) { - (void)fts_close(ftsp); - return; - } - - /* - * If not recursing down this tree and don't need stat info, just get - * the names. - */ - ch_options = !f_recursive && options & FTS_NOSTAT ? FTS_NAMEONLY : 0; - - while ((p = fts_read(ftsp)) != NULL) - switch (p->fts_info) { - case FTS_DC: - warnx("%s: directory causes a cycle", p->fts_name); - break; - case FTS_DNR: - case FTS_ERR: - warnx("%s: %s", p->fts_name, strerror(p->fts_errno)); - rval = EXIT_FAILURE; - break; - case FTS_D: - if (p->fts_level != FTS_ROOTLEVEL && - p->fts_name[0] == '.' && !f_listdot) - break; - - /* - * If already output something, put out a newline as - * a separator. If multiple arguments, precede each - * directory with its name. - */ - if (!f_leafonly) { - if (output) - (void)printf("\n%s:\n", p->fts_path); - else if (argc > 1) { - (void)printf("%s:\n", p->fts_path); - output = 1; - } - } - - chp = fts_children(ftsp, ch_options); - display(p, chp); - - if (!f_recursive && chp != NULL) - (void)fts_set(ftsp, p, FTS_SKIP); - break; - } - error = errno; - (void)fts_close(ftsp); - errno = error; - if (errno) - err(EXIT_FAILURE, "fts_read"); -} - -/* - * Display() takes a linked list of FTSENT structures and passes the list - * along with any other necessary information to the print function. P - * points to the parent directory of the display list. - */ -static void -display(FTSENT *p, FTSENT *list) -{ - struct stat *sp; - DISPLAY d; - FTSENT *cur; - NAMES *np; - u_int64_t btotal, stotal; - off_t maxsize; - blkcnt_t maxblock; - ino_t maxinode; - int maxmajor, maxminor; - uint32_t maxnlink; - int bcfile, entries, flen, glen, ulen, maxflags, maxgroup; - unsigned int maxlen; - int maxuser, needstats; - const char *user, *group; - char buf[21]; /* 64 bits == 20 digits, +1 for NUL */ - char nuser[12], ngroup[12]; - char *flags = NULL; - - /* - * If list is NULL there are two possibilities: that the parent - * directory p has no children, or that fts_children() returned an - * error. We ignore the error case since it will be replicated - * on the next call to fts_read() on the post-order visit to the - * directory p, and will be signalled in traverse(). - */ - if (list == NULL) - return; - - needstats = f_inode || f_longform || f_size; - flen = 0; - maxinode = maxnlink = 0; - bcfile = 0; - maxuser = maxgroup = maxflags = maxlen = 0; - btotal = stotal = maxblock = maxsize = 0; - maxmajor = maxminor = 0; - for (cur = list, entries = 0; cur; cur = cur->fts_link) { - if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) { - warnx("%s: %s", - cur->fts_name, strerror(cur->fts_errno)); - cur->fts_number = NO_PRINT; - rval = EXIT_FAILURE; - continue; - } - - /* - * P is NULL if list is the argv list, to which different rules - * apply. - */ - if (p == NULL) { - /* Directories will be displayed later. */ - if (cur->fts_info == FTS_D && !f_listdir) { - cur->fts_number = NO_PRINT; - continue; - } - } else { - /* Only display dot file if -a/-A set. */ - if (cur->fts_name[0] == '.' && !f_listdot) { - cur->fts_number = NO_PRINT; - continue; - } - } - if (cur->fts_namelen > maxlen) - maxlen = cur->fts_namelen; - if (needstats) { - sp = cur->fts_statp; - if (sp->st_blocks > maxblock) - maxblock = sp->st_blocks; - if (sp->st_ino > maxinode) - maxinode = sp->st_ino; - if (sp->st_nlink > maxnlink) - maxnlink = sp->st_nlink; - if (sp->st_size > maxsize) - maxsize = sp->st_size; - if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) { - bcfile = 1; - if (major(sp->st_rdev) > maxmajor) - maxmajor = major(sp->st_rdev); - if (minor(sp->st_rdev) > maxminor) - maxminor = minor(sp->st_rdev); - } - - btotal += sp->st_blocks; - stotal += sp->st_size; - if (f_longform) { - if (f_numericonly || - (user = user_from_uid(sp->st_uid, 0)) == - NULL) { - (void)snprintf(nuser, sizeof(nuser), - "%u", sp->st_uid); - user = nuser; - } - if (f_numericonly || - (group = group_from_gid(sp->st_gid, 0)) == - NULL) { - (void)snprintf(ngroup, sizeof(ngroup), - "%u", sp->st_gid); - group = ngroup; - } - if ((ulen = strlen(user)) > maxuser) - maxuser = ulen; - if ((glen = strlen(group)) > maxgroup) - maxgroup = glen; - if (f_flags) { - flags = - flags_to_string((u_long)sp->st_flags, "-"); - if ((flen = strlen(flags)) > maxflags) - maxflags = flen; - } else - flen = 0; - - if ((np = malloc(sizeof(NAMES) + - ulen + glen + flen + 2)) == NULL) - err(EXIT_FAILURE, NULL); - - np->user = &np->data[0]; - (void)strcpy(np->user, user); - np->group = &np->data[ulen + 1]; - (void)strcpy(np->group, group); - - if (f_flags) { - np->flags = &np->data[ulen + glen + 2]; - (void)strcpy(np->flags, flags); - free(flags); - } - cur->fts_pointer = np; - } - } - ++entries; - } - - if (!entries) - return; - - d.list = list; - d.entries = entries; - d.maxlen = maxlen; - if (needstats) { - d.btotal = btotal; - d.stotal = stotal; - if (f_humanize) { - d.s_block = 4; /* min buf length for humanize_number */ - } else { - (void)snprintf(buf, sizeof(buf), "%lld", - (long long)howmany(maxblock, blocksize)); - d.s_block = strlen(buf); - if (f_commas) /* allow for commas before every third digit */ - d.s_block += (d.s_block - 1) / 3; - } - d.s_flags = maxflags; - d.s_group = maxgroup; - (void)snprintf(buf, sizeof(buf), "%llu", - (unsigned long long)maxinode); - d.s_inode = strlen(buf); - (void)snprintf(buf, sizeof(buf), "%u", maxnlink); - d.s_nlink = strlen(buf); - if (f_humanize) { - d.s_size = 4; /* min buf length for humanize_number */ - } else { - (void)snprintf(buf, sizeof(buf), "%lld", - (long long)maxsize); - d.s_size = strlen(buf); - if (f_commas) /* allow for commas before every third digit */ - d.s_size += (d.s_size - 1) / 3; - } - d.s_user = maxuser; - if (bcfile) { - (void)snprintf(buf, sizeof(buf), "%d", maxmajor); - d.s_major = strlen(buf); - (void)snprintf(buf, sizeof(buf), "%d", maxminor); - d.s_minor = strlen(buf); - if (d.s_major + d.s_minor + 2 > d.s_size) - d.s_size = d.s_major + d.s_minor + 2; - else if (d.s_size - d.s_minor - 2 > d.s_major) - d.s_major = d.s_size - d.s_minor - 2; - } else { - d.s_major = 0; - d.s_minor = 0; - } - } - - printfcn(&d); - output = 1; - - if (f_longform) - for (cur = list; cur; cur = cur->fts_link) - free(cur->fts_pointer); -} - -/* - * Ordering for mastercmp: - * If ordering the argv (fts_level = FTS_ROOTLEVEL) return non-directories - * as larger than directories. Within either group, use the sort function. - * All other levels use the sort function. Error entries remain unsorted. - */ -static int -mastercmp(const FTSENT **a, const FTSENT **b) -{ - int a_info, b_info; - - a_info = (*a)->fts_info; - if (a_info == FTS_ERR) - return (0); - b_info = (*b)->fts_info; - if (b_info == FTS_ERR) - return (0); - - if (a_info == FTS_NS || b_info == FTS_NS) { - if (b_info != FTS_NS) - return (1); - else if (a_info != FTS_NS) - return (-1); - else - return (namecmp(*a, *b)); - } - - if (a_info != b_info && !f_listdir && - (*a)->fts_level == FTS_ROOTLEVEL) { - if (a_info == FTS_D) - return (1); - else if (b_info == FTS_D) - return (-1); - } - return (sortfcn(*a, *b)); -} diff --git a/bin/ls/ls.h b/bin/ls/ls.h deleted file mode 100644 index d9b6505a3..000000000 --- a/bin/ls/ls.h +++ /dev/null @@ -1,81 +0,0 @@ -/* $NetBSD: ls.h,v 1.19 2014/02/20 18:56:36 christos Exp $ */ - -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Michael Fischbein. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ls.h 8.1 (Berkeley) 5/31/93 - */ - -#define NO_PRINT 1 - -extern long blocksize; /* block size units */ - -extern int f_accesstime; /* use time of last access */ -extern int f_flags; /* show flags associated with a file */ -extern int f_grouponly; /* long listing without owner */ -extern int f_humanize; /* humanize size field */ -extern int f_commas; /* separate size field with commas */ -extern int f_inode; /* print inode */ -extern int f_longform; /* long listing format */ -extern int f_octal; /* print octal escapes for nongraphic characters */ -extern int f_octal_escape; /* like f_octal but use C escapes if possible */ -extern int f_sectime; /* print the real time for all files */ -extern int f_size; /* list size in short listing */ -extern int f_statustime; /* use time of last mode change */ -extern int f_type; /* add type character for non-regular files */ -extern int f_typedir; /* add type character for directories */ -extern int f_nonprint; /* show unprintables as ? */ -extern int f_fullpath; /* print full pathname, not filename */ -extern int f_leafonly; /* when recursing, print leaf names only */ - -typedef struct { - FTSENT *list; - u_int64_t btotal; - u_int64_t stotal; - int entries; - unsigned int maxlen; - int s_block; - int s_flags; - int s_group; - int s_inode; - int s_nlink; - int s_size; - int s_user; - int s_major; - int s_minor; -} DISPLAY; - -typedef struct { - char *user; - char *group; - char *flags; - char data[1]; -} NAMES; diff --git a/bin/ls/main.c b/bin/ls/main.c deleted file mode 100644 index c1316aaec..000000000 --- a/bin/ls/main.c +++ /dev/null @@ -1,50 +0,0 @@ -/* $NetBSD: main.c,v 1.5 2016/09/05 01:00:07 sevan Exp $ */ - -/*- - * Copyright (c) 1999 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Luke Mewburn. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#ifndef lint -__RCSID("$NetBSD: main.c,v 1.5 2016/09/05 01:00:07 sevan Exp $"); -#endif /* not lint */ - -#include -#include - -#include "ls.h" -#include "extern.h" - -int -main(int argc, char *argv[]) -{ - - return ls_main(argc, argv); - /* NOTREACHED */ -} diff --git a/bin/ls/print.c b/bin/ls/print.c deleted file mode 100644 index b3aecd8c5..000000000 --- a/bin/ls/print.c +++ /dev/null @@ -1,497 +0,0 @@ -/* $NetBSD: print.c,v 1.55 2014/05/10 09:39:18 martin Exp $ */ - -/* - * Copyright (c) 1989, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Michael Fischbein. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)print.c 8.5 (Berkeley) 7/28/94"; -#else -__RCSID("$NetBSD: print.c,v 1.55 2014/05/10 09:39:18 martin Exp $"); -#endif -#endif /* not lint */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ls.h" -#include "extern.h" - -extern int termwidth; - -static int printaname(FTSENT *, int, int); -static void printlink(FTSENT *); -static void printtime(time_t); -static void printtotal(DISPLAY *dp); -static int printtype(u_int); - -static time_t now; - -#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) - -static int -safe_printpath(const FTSENT *p) { - int chcnt; - - if (f_fullpath) { - chcnt = safe_print(p->fts_path); - chcnt += safe_print("/"); - } else - chcnt = 0; - return chcnt + safe_print(p->fts_name); -} - -static int -printescapedpath(const FTSENT *p) { - int chcnt; - - if (f_fullpath) { - chcnt = printescaped(p->fts_path); - chcnt += printescaped("/"); - } else - chcnt = 0; - - return chcnt + printescaped(p->fts_name); -} - -static int -printpath(const FTSENT *p) { - if (f_fullpath) - return printf("%s/%s", p->fts_path, p->fts_name); - else - return printf("%s", p->fts_name); -} - -void -printscol(DISPLAY *dp) -{ - FTSENT *p; - - for (p = dp->list; p; p = p->fts_link) { - if (IS_NOPRINT(p)) - continue; - (void)printaname(p, dp->s_inode, dp->s_block); - (void)putchar('\n'); - } -} - -void -printlong(DISPLAY *dp) -{ - struct stat *sp; - FTSENT *p; - NAMES *np; - char buf[20], szbuf[5]; - - now = time(NULL); - - if (!f_leafonly) - printtotal(dp); /* "total: %u\n" */ - - for (p = dp->list; p; p = p->fts_link) { - if (IS_NOPRINT(p)) - continue; - sp = p->fts_statp; - if (f_inode) - (void)printf("%*"PRIu64" ", dp->s_inode, sp->st_ino); - if (f_size) { - if (f_humanize) { - if ((humanize_number(szbuf, sizeof(szbuf), - sp->st_blocks * S_BLKSIZE, - "", HN_AUTOSCALE, - (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1) - err(1, "humanize_number"); - (void)printf("%*s ", dp->s_block, szbuf); - } else { - (void)printf(f_commas ? "%'*llu " : "%*llu ", - dp->s_block, - (unsigned long long)howmany(sp->st_blocks, - blocksize)); - } - } - (void)strmode(sp->st_mode, buf); - np = p->fts_pointer; - (void)printf("%s %*lu ", buf, dp->s_nlink, - (unsigned long)sp->st_nlink); - if (!f_grouponly) - (void)printf("%-*s ", dp->s_user, np->user); - (void)printf("%-*s ", dp->s_group, np->group); - if (f_flags) - (void)printf("%-*s ", dp->s_flags, np->flags); - if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) - (void)printf("%*lld, %*lld ", - dp->s_major, (long long)major(sp->st_rdev), - dp->s_minor, (long long)minor(sp->st_rdev)); - else - if (f_humanize) { - if ((humanize_number(szbuf, sizeof(szbuf), - sp->st_size, "", HN_AUTOSCALE, - (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1) - err(1, "humanize_number"); - (void)printf("%*s ", dp->s_size, szbuf); - } else { - (void)printf(f_commas ? "%'*llu " : "%*llu ", - dp->s_size, (unsigned long long) - sp->st_size); - } - if (f_accesstime) - printtime(sp->st_atime); - else if (f_statustime) - printtime(sp->st_ctime); - else - printtime(sp->st_mtime); - if (f_octal || f_octal_escape) - (void)safe_printpath(p); - else if (f_nonprint) - (void)printescapedpath(p); - else - (void)printpath(p); - - if (f_type || (f_typedir && S_ISDIR(sp->st_mode))) - (void)printtype(sp->st_mode); - if (S_ISLNK(sp->st_mode)) - printlink(p); - (void)putchar('\n'); - } -} - -void -printcol(DISPLAY *dp) -{ - static FTSENT **array; - static int lastentries = -1; - FTSENT *p; - int base, chcnt, col, colwidth, num; - int numcols, numrows, row; - - colwidth = dp->maxlen; - if (f_inode) - colwidth += dp->s_inode + 1; - if (f_size) { - if (f_humanize) - colwidth += dp->s_size + 1; - else - colwidth += dp->s_block + 1; - } - if (f_type || f_typedir) - colwidth += 1; - - colwidth += 1; - - if (termwidth < 2 * colwidth) { - printscol(dp); - return; - } - - /* - * Have to do random access in the linked list -- build a table - * of pointers. - */ - if (dp->entries > lastentries) { - FTSENT **newarray; - - newarray = realloc(array, dp->entries * sizeof(FTSENT *)); - if (newarray == NULL) { - warn(NULL); - printscol(dp); - return; - } - lastentries = dp->entries; - array = newarray; - } - for (p = dp->list, num = 0; p; p = p->fts_link) - if (p->fts_number != NO_PRINT) - array[num++] = p; - - numcols = termwidth / colwidth; - colwidth = termwidth / numcols; /* spread out if possible */ - numrows = num / numcols; - if (num % numcols) - ++numrows; - - printtotal(dp); /* "total: %u\n" */ - - for (row = 0; row < numrows; ++row) { - for (base = row, chcnt = col = 0; col < numcols; ++col) { - chcnt = printaname(array[base], dp->s_inode, - f_humanize ? dp->s_size : dp->s_block); - if ((base += numrows) >= num) - break; - while (chcnt++ < colwidth) - (void)putchar(' '); - } - (void)putchar('\n'); - } -} - -void -printacol(DISPLAY *dp) -{ - FTSENT *p; - int chcnt, col, colwidth; - int numcols; - - colwidth = dp->maxlen; - if (f_inode) - colwidth += dp->s_inode + 1; - if (f_size) { - if (f_humanize) - colwidth += dp->s_size + 1; - else - colwidth += dp->s_block + 1; - } - if (f_type || f_typedir) - colwidth += 1; - - colwidth += 1; - - if (termwidth < 2 * colwidth) { - printscol(dp); - return; - } - - numcols = termwidth / colwidth; - colwidth = termwidth / numcols; /* spread out if possible */ - - printtotal(dp); /* "total: %u\n" */ - - chcnt = col = 0; - for (p = dp->list; p; p = p->fts_link) { - if (IS_NOPRINT(p)) - continue; - if (col >= numcols) { - chcnt = col = 0; - (void)putchar('\n'); - } - chcnt = printaname(p, dp->s_inode, - f_humanize ? dp->s_size : dp->s_block); - while (chcnt++ < colwidth) - (void)putchar(' '); - col++; - } - (void)putchar('\n'); -} - -void -printstream(DISPLAY *dp) -{ - FTSENT *p; - int col; - int extwidth; - - extwidth = 0; - if (f_inode) - extwidth += dp->s_inode + 1; - if (f_size) { - if (f_humanize) - extwidth += dp->s_size + 1; - else - extwidth += dp->s_block + 1; - } - if (f_type) - extwidth += 1; - - for (col = 0, p = dp->list; p != NULL; p = p->fts_link) { - if (IS_NOPRINT(p)) - continue; - if (col > 0) { - (void)putchar(','), col++; - if (col + 1 + extwidth + (int)p->fts_namelen >= termwidth) - (void)putchar('\n'), col = 0; - else - (void)putchar(' '), col++; - } - col += printaname(p, dp->s_inode, - f_humanize ? dp->s_size : dp->s_block); - } - (void)putchar('\n'); -} - -/* - * print [inode] [size] name - * return # of characters printed, no trailing characters. - */ -static int -printaname(FTSENT *p, int inodefield, int sizefield) -{ - struct stat *sp; - int chcnt; - char szbuf[5]; - - sp = p->fts_statp; - chcnt = 0; - if (f_inode) - chcnt += printf("%*"PRIu64" ", inodefield, sp->st_ino); - if (f_size) { - if (f_humanize) { - if ((humanize_number(szbuf, sizeof(szbuf), sp->st_size, - "", HN_AUTOSCALE, - (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1) - err(1, "humanize_number"); - chcnt += printf("%*s ", sizefield, szbuf); - } else { - chcnt += printf(f_commas ? "%'*llu " : "%*llu ", - sizefield, (unsigned long long) - howmany(sp->st_blocks, blocksize)); - } - } - if (f_octal || f_octal_escape) - chcnt += safe_printpath(p); - else if (f_nonprint) - chcnt += printescapedpath(p); - else - chcnt += printpath(p); - if (f_type || (f_typedir && S_ISDIR(sp->st_mode))) - chcnt += printtype(sp->st_mode); - return (chcnt); -} - -static void -printtime(time_t ftime) -{ - int i; - const char *longstring; - - if ((longstring = ctime(&ftime)) == NULL) { - /* 012345678901234567890123 */ - longstring = "????????????????????????"; - } - for (i = 4; i < 11; ++i) - (void)putchar(longstring[i]); - -#define SIXMONTHS ((DAYSPERNYEAR / 2) * SECSPERDAY) - if (f_sectime) - for (i = 11; i < 24; i++) - (void)putchar(longstring[i]); - else if (ftime + SIXMONTHS > now && ftime - SIXMONTHS < now) - for (i = 11; i < 16; ++i) - (void)putchar(longstring[i]); - else { - (void)putchar(' '); - for (i = 20; i < 24; ++i) - (void)putchar(longstring[i]); - } - (void)putchar(' '); -} - -/* - * Display total used disk space in the form "total: %u\n". - * Note: POSIX (IEEE Std 1003.1-2001) says this should be always in 512 blocks, - * but we humanise it with -h, or separate it with commas with -M, and use 1024 - * with -k. - */ -static void -printtotal(DISPLAY *dp) -{ - char szbuf[5]; - - if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) { - if (f_humanize) { - if ((humanize_number(szbuf, sizeof(szbuf), (int64_t)dp->stotal, - "", HN_AUTOSCALE, - (HN_DECIMAL | HN_B | HN_NOSPACE))) == -1) - err(1, "humanize_number"); - (void)printf("total %s\n", szbuf); - } else { - (void)printf(f_commas ? "total %'llu\n" : - "total %llu\n", (unsigned long long) - howmany(dp->btotal, blocksize)); - } - } -} - -static int -printtype(u_int mode) -{ - switch (mode & S_IFMT) { - case S_IFDIR: - (void)putchar('/'); - return (1); - case S_IFIFO: - (void)putchar('|'); - return (1); - case S_IFLNK: - (void)putchar('@'); - return (1); - case S_IFSOCK: - (void)putchar('='); - return (1); - case S_IFWHT: - (void)putchar('%'); - return (1); - } - if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { - (void)putchar('*'); - return (1); - } - return (0); -} - -static void -printlink(FTSENT *p) -{ - int lnklen; - char name[MAXPATHLEN + 1], path[MAXPATHLEN + 1]; - - if (p->fts_level == FTS_ROOTLEVEL) - (void)snprintf(name, sizeof(name), "%s", p->fts_name); - else - (void)snprintf(name, sizeof(name), - "%s/%s", p->fts_parent->fts_accpath, p->fts_name); - if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { - (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); - return; - } - path[lnklen] = '\0'; - (void)printf(" -> "); - if (f_octal || f_octal_escape) - (void)safe_print(path); - else if (f_nonprint) - (void)printescaped(path); - else - (void)printf("%s", path); -} diff --git a/bin/ls/util.c b/bin/ls/util.c deleted file mode 100644 index 61b0fda87..000000000 --- a/bin/ls/util.c +++ /dev/null @@ -1,168 +0,0 @@ -/* $NetBSD: util.c,v 1.34 2011/08/29 14:44:21 joerg Exp $ */ - -/* - * Copyright (c) 1989, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Michael Fischbein. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)util.c 8.5 (Berkeley) 4/28/95"; -#else -__RCSID("$NetBSD: util.c,v 1.34 2011/08/29 14:44:21 joerg Exp $"); -#endif -#endif /* not lint */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ls.h" -#include "extern.h" - -int -safe_print(const char *src) -{ - size_t len; - char *name; - int flags; - - flags = VIS_NL | VIS_OCTAL | VIS_WHITE; - if (f_octal_escape) - flags |= VIS_CSTYLE; - - len = strlen(src); - if (len != 0 && SIZE_T_MAX/len <= 4) { - errx(EXIT_FAILURE, "%s: name too long", src); - /* NOTREACHED */ - } - - name = (char *)malloc(4*len+1); - if (name != NULL) { - len = strvis(name, src, flags); - (void)printf("%s", name); - free(name); - return len; - } else - errx(EXIT_FAILURE, "out of memory!"); - /* NOTREACHED */ -} - -/* - * The reasons why we don't use putwchar(wc) here are: - * - If wc == L'\0', we need to restore the initial shift state, but - * the C language standard doesn't say that putwchar(L'\0') does. - * - It isn't portable to mix a wide-oriented function (i.e. getwchar) - * with byte-oriented functions (printf et al.) in same FILE. - */ -static int -printwc(wchar_t wc, mbstate_t *pst) -{ - size_t size; - char buf[MB_LEN_MAX]; - - size = wcrtomb(buf, wc, pst); - if (size == (size_t)-1) /* This shouldn't happen, but for sure */ - return 0; - if (wc == L'\0') { - /* The following condition must be always true, but for sure */ - if (size > 0 && buf[size - 1] == '\0') - --size; - } - if (size > 0) - fwrite(buf, 1, size, stdout); - return wc == L'\0' ? 0 : wcwidth(wc); -} - -int -printescaped(const char *src) -{ - int n = 0; - mbstate_t src_state, stdout_state; - /* The following +1 is to pass '\0' at the end of src to mbrtowc(). */ - const char *endptr = src + strlen(src) + 1; - - /* - * We have to reset src_state each time in this function, because - * the codeset of src pathname may not match with current locale. - * Note that if we pass NULL instead of src_state to mbrtowc(), - * there is no way to reset the state. - */ - memset(&src_state, 0, sizeof(src_state)); - memset(&stdout_state, 0, sizeof(stdout_state)); - while (src < endptr) { - wchar_t wc; - size_t rv, span = endptr - src; - -#if 0 - /* - * XXX - we should fix libc instead. - * Theoretically this should work, but our current - * implementation of iso2022 module doesn't actually work - * as expected, if there are redundant escape sequences - * which exceed 32 bytes. - */ - if (span > MB_CUR_MAX) - span = MB_CUR_MAX; -#endif - rv = mbrtowc(&wc, src, span, &src_state); - if (rv == 0) { /* assert(wc == L'\0'); */ - /* The following may output a shift sequence. */ - n += printwc(wc, &stdout_state); - break; - } - if (rv == (size_t)-1) { /* probably errno == EILSEQ */ - n += printwc(L'?', &stdout_state); - /* try to skip 1byte, because there is no better way */ - src++; - memset(&src_state, 0, sizeof(src_state)); - } else if (rv == (size_t)-2) { - if (span < MB_CUR_MAX) { /* incomplete char */ - n += printwc(L'?', &stdout_state); - break; - } - src += span; /* a redundant shift sequence? */ - } else { - n += printwc(iswprint(wc) ? wc : L'?', &stdout_state); - src += rv; - } - } - return n; -} diff --git a/bin/mv/Makefile b/bin/mv/Makefile deleted file mode 100644 index 73f27f680..000000000 --- a/bin/mv/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# $NetBSD: Makefile,v 1.9 2002/11/30 03:16:14 lukem Exp $ -# @(#)Makefile 8.2 (Berkeley) 4/2/94 - -PROG= mv - -.include diff --git a/bin/mv/mv.1 b/bin/mv/mv.1 deleted file mode 100644 index 3b6231538..000000000 --- a/bin/mv/mv.1 +++ /dev/null @@ -1,151 +0,0 @@ -.\" $NetBSD: mv.1,v 1.28 2016/08/10 18:08:14 sevan Exp $ -.\" -.\" Copyright (c) 1989, 1990, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Institute of Electrical and Electronics Engineers, Inc. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)mv.1 8.1 (Berkeley) 5/31/93 -.\" -.Dd August 10, 2016 -.Dt MV 1 -.Os -.Sh NAME -.Nm mv -.Nd move files -.Sh SYNOPSIS -.Nm -.Op Fl fiv -.Ar source target -.Nm -.Op Fl fiv -.Ar source ... directory -.Sh DESCRIPTION -In its first form, the -.Nm -utility renames the file named by the -.Ar source -operand to the destination path named by the -.Ar target -operand. -This form is assumed when the last operand does not name an already -existing directory. -.Pp -In its second form, -.Nm -moves each file named by a -.Ar source -operand to a destination file in the existing directory named by the -.Ar directory -operand. -The destination path for each operand is the pathname produced by the -concatenation of the last operand, a slash, and the final pathname -component of the named file. -.Pp -The following options are available: -.Bl -tag -width flag -.It Fl f -Do not prompt for confirmation before overwriting the destination -path. -.It Fl i -Causes -.Nm -to write a prompt to standard error before moving a file that would -overwrite an existing file. -If the response from the standard input begins with the character ``y'', -the move is attempted. -.It Fl v -Cause -.Nm -to be verbose, showing files as they are processed. -.El -.Pp -The last of any -.Fl f -or -.Fl i -options is the one which affects -.Nm Ns 's -behavior. -.Pp -It is an error for any of the -.Ar source -operands to specify a nonexistent file or directory. -.Pp -It is an error for the -.Ar source -operand to specify a directory if the -.Ar target -exists and is not a directory. -.Pp -If the destination path does not have a mode which permits writing, -.Nm -prompts the user for confirmation as specified for the -.Fl i -option. -.Pp -Should the -.Xr rename 2 -call fail because -.Ar source -and -.Ar target -are on different file systems, -.Nm -will remove the destination file, copy the source file to the -destination, and then remove the source. -The effect is roughly equivalent to: -.Bd -literal -offset indent -rm -f destination_path \*[Am]\*[Am] \e -cp -PRp source_file destination_path \*[Am]\*[Am] \e -rm -rf source_file -.Ed -.Sh EXIT STATUS -The -.Nm -utility exits 0 on success, and \*[Gt]0 if an error occurs. -.Sh SEE ALSO -.Xr cp 1 , -.Xr rename 2 , -.Xr symlink 7 -.Sh STANDARDS -The -.Nm -utility is expected to be -.St -p1003.2 -compatible. -.Pp -The -.Fl v -option is an extension to -.St -p1003.2 . -.Sh HISTORY -An -.Nm -utility appeared in -.At v1 . diff --git a/bin/mv/mv.c b/bin/mv/mv.c deleted file mode 100644 index 94d28059d..000000000 --- a/bin/mv/mv.c +++ /dev/null @@ -1,409 +0,0 @@ -/* $NetBSD: mv.c,v 1.44 2015/03/02 03:17:24 enami Exp $ */ - -/* - * Copyright (c) 1989, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ken Smith of The State University of New York at Buffalo. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)mv.c 8.2 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: mv.c,v 1.44 2015/03/02 03:17:24 enami Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pathnames.h" - -static int fflg, iflg, vflg; -static int stdin_ok; - -static int copy(char *, char *); -static int do_move(char *, char *); -static int fastcopy(char *, char *, struct stat *); -__dead static void usage(void); - -int -main(int argc, char *argv[]) -{ - int ch, len, rval; - char *p, *endp; - struct stat sb; - char path[MAXPATHLEN + 1]; - size_t baselen; - - setprogname(argv[0]); - (void)setlocale(LC_ALL, ""); - - while ((ch = getopt(argc, argv, "ifv")) != -1) - switch (ch) { - case 'i': - fflg = 0; - iflg = 1; - break; - case 'f': - iflg = 0; - fflg = 1; - break; - case 'v': - vflg = 1; - break; - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc < 2) - usage(); - - stdin_ok = isatty(STDIN_FILENO); - - /* - * If the stat on the target fails or the target isn't a directory, - * try the move. More than 2 arguments is an error in this case. - */ - if (stat(argv[argc - 1], &sb) || !S_ISDIR(sb.st_mode)) { - if (argc > 2) - usage(); - exit(do_move(argv[0], argv[1])); - } - - /* It's a directory, move each file into it. */ - baselen = strlcpy(path, argv[argc - 1], sizeof(path)); - if (baselen >= sizeof(path)) - errx(1, "%s: destination pathname too long", argv[argc - 1]); - endp = &path[baselen]; - if (!baselen || *(endp - 1) != '/') { - *endp++ = '/'; - ++baselen; - } - for (rval = 0; --argc; ++argv) { - p = *argv + strlen(*argv) - 1; - while (*p == '/' && p != *argv) - *p-- = '\0'; - if ((p = strrchr(*argv, '/')) == NULL) - p = *argv; - else - ++p; - - if ((baselen + (len = strlen(p))) >= MAXPATHLEN) { - warnx("%s: destination pathname too long", *argv); - rval = 1; - } else { - memmove(endp, p, len + 1); - if (do_move(*argv, path)) - rval = 1; - } - } - exit(rval); - /* NOTREACHED */ -} - -static int -do_move(char *from, char *to) -{ - struct stat sb; - char modep[15]; - - /* - * (1) If the destination path exists, the -f option is not specified - * and either of the following conditions are true: - * - * (a) The permissions of the destination path do not permit - * writing and the standard input is a terminal. - * (b) The -i option is specified. - * - * the mv utility shall write a prompt to standard error and - * read a line from standard input. If the response is not - * affirmative, mv shall do nothing more with the current - * source file... - */ - if (!fflg && !access(to, F_OK)) { - int ask = 1; - int ch; - - if (iflg) { - if (access(from, F_OK)) { - warn("rename %s", from); - return (1); - } - (void)fprintf(stderr, "overwrite %s? ", to); - } else if (stdin_ok && access(to, W_OK) && !stat(to, &sb)) { - if (access(from, F_OK)) { - warn("rename %s", from); - return (1); - } - strmode(sb.st_mode, modep); - (void)fprintf(stderr, "override %s%s%s/%s for %s? ", - modep + 1, modep[9] == ' ' ? "" : " ", - user_from_uid(sb.st_uid, 0), - group_from_gid(sb.st_gid, 0), to); - } else - ask = 0; - if (ask) { - if ((ch = getchar()) != EOF && ch != '\n') { - int ch2; - while ((ch2 = getchar()) != EOF && ch2 != '\n') - continue; - } - if (ch != 'y' && ch != 'Y') - return (0); - } - } - - /* - * (2) If rename() succeeds, mv shall do nothing more with the - * current source file. If it fails for any other reason than - * EXDEV, mv shall write a diagnostic message to the standard - * error and do nothing more with the current source file. - * - * (3) If the destination path exists, and it is a file of type - * directory and source_file is not a file of type directory, - * or it is a file not of type directory, and source file is - * a file of type directory, mv shall write a diagnostic - * message to standard error, and do nothing more with the - * current source file... - */ - if (!rename(from, to)) { - if (vflg) - printf("%s -> %s\n", from, to); - return (0); - } - - if (errno != EXDEV) { - warn("rename %s to %s", from, to); - return (1); - } - - /* - * (4) If the destination path exists, mv shall attempt to remove it. - * If this fails for any reason, mv shall write a diagnostic - * message to the standard error and do nothing more with the - * current source file... - */ - if (!lstat(to, &sb)) { - if ((S_ISDIR(sb.st_mode)) ? rmdir(to) : unlink(to)) { - warn("can't remove %s", to); - return (1); - } - } - - /* - * (5) The file hierarchy rooted in source_file shall be duplicated - * as a file hierarchy rooted in the destination path... - */ - if (lstat(from, &sb)) { - warn("%s", from); - return (1); - } - - return (S_ISREG(sb.st_mode) ? - fastcopy(from, to, &sb) : copy(from, to)); -} - -static int -fastcopy(char *from, char *to, struct stat *sbp) -{ -#if defined(__NetBSD__) - struct timespec ts[2]; -#else - struct timeval tval[2]; -#endif - static blksize_t blen; - static char *bp; - int nread, from_fd, to_fd; - - if ((from_fd = open(from, O_RDONLY, 0)) < 0) { - warn("%s", from); - return (1); - } - if ((to_fd = - open(to, O_CREAT | O_TRUNC | O_WRONLY, sbp->st_mode)) < 0) { - warn("%s", to); - (void)close(from_fd); - return (1); - } - if (!blen && !(bp = malloc(blen = sbp->st_blksize))) { - warn(NULL); - blen = 0; - (void)close(from_fd); - (void)close(to_fd); - return (1); - } - while ((nread = read(from_fd, bp, blen)) > 0) - if (write(to_fd, bp, nread) != nread) { - warn("%s", to); - goto err; - } - if (nread < 0) { - warn("%s", from); -err: if (unlink(to)) - warn("%s: remove", to); - (void)close(from_fd); - (void)close(to_fd); - return (1); - } - -#if !defined(__minix) - if (fcpxattr(from_fd, to_fd) == -1) - warn("%s: error copying extended attributes", to); -#endif /* !defined(__minix) */ - - (void)close(from_fd); -#ifdef BSD4_4 -#if defined(__NetBSD__) - ts[0] = sbp->st_atimespec; - ts[1] = sbp->st_mtimespec; -#else - TIMESPEC_TO_TIMEVAL(&tval[0], &sbp->st_atimespec); - TIMESPEC_TO_TIMEVAL(&tval[1], &sbp->st_mtimespec); -#endif -#else - tval[0].tv_sec = sbp->st_atime; - tval[1].tv_sec = sbp->st_mtime; - tval[0].tv_usec = 0; - tval[1].tv_usec = 0; -#endif -#ifdef __SVR4 - if (utimes(to, tval)) -#else -#if defined(__NetBSD__) - if (futimens(to_fd, ts)) -#else - if (futimes(to_fd, tval)) -#endif -#endif - warn("%s: set times", to); - if (fchown(to_fd, sbp->st_uid, sbp->st_gid)) { - if (errno != EPERM) - warn("%s: set owner/group", to); - sbp->st_mode &= ~(S_ISUID | S_ISGID); - } - if (fchmod(to_fd, sbp->st_mode)) - warn("%s: set mode", to); -#if !defined(__minix) - if (fchflags(to_fd, sbp->st_flags) && (errno != EOPNOTSUPP)) - warn("%s: set flags (was: 0%07o)", to, sbp->st_flags); -#endif /* !defined(__minix) */ - - if (close(to_fd)) { - warn("%s", to); - return (1); - } - - if (unlink(from)) { - warn("%s: remove", from); - return (1); - } - - if (vflg) - printf("%s -> %s\n", from, to); - - return (0); -} - -static int -copy(char *from, char *to) -{ - pid_t pid; - int status; - - if ((pid = vfork()) == 0) { - execl(_PATH_CP, "mv", vflg ? "-PRpv" : "-PRp", "--", from, to, NULL); - warn("%s", _PATH_CP); - _exit(1); - } - if (waitpid(pid, &status, 0) == -1) { - warn("%s: waitpid", _PATH_CP); - return (1); - } - if (!WIFEXITED(status)) { - warnx("%s: did not terminate normally", _PATH_CP); - return (1); - } - if (WEXITSTATUS(status)) { - warnx("%s: terminated with %d (non-zero) status", - _PATH_CP, WEXITSTATUS(status)); - return (1); - } - if (!(pid = vfork())) { - execl(_PATH_RM, "mv", "-rf", "--", from, NULL); - warn("%s", _PATH_RM); - _exit(1); - } - if (waitpid(pid, &status, 0) == -1) { - warn("%s: waitpid", _PATH_RM); - return (1); - } - if (!WIFEXITED(status)) { - warnx("%s: did not terminate normally", _PATH_RM); - return (1); - } - if (WEXITSTATUS(status)) { - warnx("%s: terminated with %d (non-zero) status", - _PATH_RM, WEXITSTATUS(status)); - return (1); - } - return (0); -} - -static void -usage(void) -{ - (void)fprintf(stderr, "usage: %s [-fiv] source target\n" - " %s [-fiv] source ... directory\n", getprogname(), - getprogname()); - exit(1); - /* NOTREACHED */ -} diff --git a/bin/mv/pathnames.h b/bin/mv/pathnames.h deleted file mode 100644 index a38e4e945..000000000 --- a/bin/mv/pathnames.h +++ /dev/null @@ -1,40 +0,0 @@ -/* $NetBSD: pathnames.h,v 1.8 2004/08/19 22:26:07 christos Exp $ */ - -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)pathnames.h 8.1 (Berkeley) 5/31/93 - */ - -#ifdef RESCUEDIR -#define _PATH_RM RESCUEDIR "/rm" -#define _PATH_CP RESCUEDIR "/cp" -#else -#define _PATH_RM "/bin/rm" -#define _PATH_CP "/bin/cp" -#endif diff --git a/bin/ps/Makefile b/bin/ps/Makefile deleted file mode 100644 index 0919b105e..000000000 --- a/bin/ps/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# $NetBSD: Makefile,v 1.29 2011/08/14 10:53:17 christos Exp $ -# @(#)Makefile 8.1 (Berkeley) 6/2/93 - -PROG= ps -SRCS= fmt.c keyword.c nlist.c print.c ps.c -DPADD= ${LIBM} ${LIBKVM} -LDADD= -lm -lkvm - -CWARNFLAGS+= -Wno-format-y2k -COPTS.print.c = -Wno-format-nonliteral - -.include diff --git a/bin/ps/extern.h b/bin/ps/extern.h deleted file mode 100644 index 6e4690ba8..000000000 --- a/bin/ps/extern.h +++ /dev/null @@ -1,99 +0,0 @@ -/* $NetBSD: extern.h,v 1.35 2014/04/20 22:48:59 dholland Exp $ */ - -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)extern.h 8.3 (Berkeley) 4/2/94 - */ - -/* - * We expect to be included by ps.h, which will already have - * defined the types we use. - */ - -extern double ccpu; -extern int eval, fscale, mempages, nlistread, rawcpu, maxslp, uspace; -extern int sumrusage, termwidth, totwidth; -extern int needenv, needcomm, commandonly; -extern uid_t myuid; -extern kvm_t *kd; -extern VAR var[]; -extern VARLIST displaylist; -extern VARLIST sortlist; - -void command(void *, VARENT *, enum mode); -void cpuid(void *, VARENT *, enum mode); -void cputime(void *, VARENT *, enum mode); -int donlist(void); -int donlist_sysctl(void); -void fmt_puts(char *, int *); -void fmt_putc(int, int *); -void elapsed(void *, VARENT *, enum mode); -double getpcpu(const struct kinfo_proc2 *); -double getpmem(const struct kinfo_proc2 *); -void gname(void *, VARENT *, enum mode); -void groups(void *, VARENT *, enum mode); -void groupnames(void *, VARENT *, enum mode); -void lcputime(void *, VARENT *, enum mode); -void logname(void *, VARENT *, enum mode); -void longtname(void *, VARENT *, enum mode); -void lname(void *, VARENT *, enum mode); -void lstarted(void *, VARENT *, enum mode); -void lstate(void *, VARENT *, enum mode); -void maxrss(void *, VARENT *, enum mode); -void nlisterr(struct nlist *); -void p_rssize(void *, VARENT *, enum mode); -void pagein(void *, VARENT *, enum mode); -void parsefmt(const char *); -void parsefmt_insert(const char *, VARENT **); -void parsesort(const char *); -VARENT * varlist_find(VARLIST *, const char *); -void emul(void *, VARENT *, enum mode); -void pcpu(void *, VARENT *, enum mode); -void pmem(void *, VARENT *, enum mode); -void pnice(void *, VARENT *, enum mode); -void pri(void *, VARENT *, enum mode); -void printheader(void); -void putimeval(void *, VARENT *, enum mode); -void pvar(void *, VARENT *, enum mode); -void rgname(void *, VARENT *, enum mode); -void rssize(void *, VARENT *, enum mode); -void runame(void *, VARENT *, enum mode); -void showkey(void); -void started(void *, VARENT *, enum mode); -void state(void *, VARENT *, enum mode); -void svgname(void *, VARENT *, enum mode); -void svuname(void *, VARENT *, enum mode); -void tdev(void *, VARENT *, enum mode); -void tname(void *, VARENT *, enum mode); -void tsize(void *, VARENT *, enum mode); -void ucomm(void *, VARENT *, enum mode); -void uname(void *, VARENT *, enum mode); -void uvar(void *, VARENT *, enum mode); -void vsize(void *, VARENT *, enum mode); -void wchan(void *, VARENT *, enum mode); diff --git a/bin/ps/fmt.c b/bin/ps/fmt.c deleted file mode 100644 index 489a0ec99..000000000 --- a/bin/ps/fmt.c +++ /dev/null @@ -1,60 +0,0 @@ -/* $NetBSD: fmt.c,v 1.21 2007/12/12 22:55:43 lukem Exp $ */ - -#include -__RCSID("$NetBSD: fmt.c,v 1.21 2007/12/12 22:55:43 lukem Exp $"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include "ps.h" - -void -fmt_puts(char *s, int *leftp) -{ - static char *v = 0; - static int maxlen = 0; - char *nv; - int len, nlen; - - if (*leftp == 0) - return; - len = strlen(s) * 4 + 1; - if (len > maxlen) { - if (maxlen == 0) - nlen = getpagesize(); - else - nlen = maxlen; - while (len > nlen) - nlen *= 2; - nv = realloc(v, nlen); - if (nv == 0) - return; - v = nv; - maxlen = nlen; - } - len = strvis(v, s, VIS_TAB | VIS_NL | VIS_CSTYLE); - if (*leftp != -1) { - if (len > *leftp) { - v[*leftp] = '\0'; - *leftp = 0; - } else - *leftp -= len; - } - (void)printf("%s", v); -} - -void -fmt_putc(int c, int *leftp) -{ - - if (*leftp == 0) - return; - if (*leftp != -1) - *leftp -= 1; - putchar(c); -} diff --git a/bin/ps/keyword.c b/bin/ps/keyword.c deleted file mode 100644 index d9833f494..000000000 --- a/bin/ps/keyword.c +++ /dev/null @@ -1,419 +0,0 @@ -/* $NetBSD: keyword.c,v 1.54 2014/01/15 08:07:53 mlelstv Exp $ */ - -/*- - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)keyword.c 8.5 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: keyword.c,v 1.54 2014/01/15 08:07:53 mlelstv Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ps.h" - -static VAR *findvar(const char *); -static int vcmp(const void *, const void *); - -#if 0 /* kernel doesn't calculate these */ - PUVAR("idrss", "IDRSS", 0, p_uru_idrss, UINT64, PRIu64), - PUVAR("isrss", "ISRSS", 0, p_uru_isrss, UINT64, PRId64), - PUVAR("ixrss", "IXRSS", 0, p_uru_ixrss, UINT64, PRId64), - PUVAR("maxrss", "MAXRSS", 0, p_uru_maxrss, UINT64, PRIu64), -#endif - -/* Compute offset in common structures. */ -#define POFF(x) offsetof(struct kinfo_proc2, x) -#define LOFF(x) offsetof(struct kinfo_lwp, x) - -#define UIDFMT "u" -#define UID(n1, n2, of) \ - { .name = n1, .header = n2, .flag = 0, .oproc = pvar, \ - .off = POFF(of), .type = UINT32, .fmt = UIDFMT } -#define GID(n1, n2, off) UID(n1, n2, off) - -#define PIDFMT "d" -#define PID(n1, n2, of) \ - { .name = n1, .header = n2, .flag = 0, .oproc = pvar, \ - .off = POFF(of), .type = INT32, .fmt = PIDFMT } - -#define LVAR(n1, n2, fl, of, ty, fm) \ - { .name = n1, .header = n2, .flag = (fl) | LWP, .oproc = pvar, \ - .off = LOFF(of), .type = ty, .fmt = fm } -#define PVAR(n1, n2, fl, of, ty, fm) \ - { .name = n1, .header = n2, .flag = (fl) | 0, .oproc = pvar, \ - .off = POFF(of), .type = ty, .fmt = fm } -#define PUVAR(n1, n2, fl, of, ty, fm) \ - { .name = n1, .header = n2, .flag = (fl) | UAREA, .oproc = pvar, \ - .off = POFF(of), .type = ty, .fmt = fm } -#define VAR3(n1, n2, fl) \ - { .name = n1, .header = n2, .flag = fl } -#define VAR4(n1, n2, fl, op) \ - { .name = n1, .header = n2, .flag = fl, .oproc = op, } -#define VAR6(n1, n2, fl, op, of, ty) \ - { .name = n1, .header = n2, .flag = fl, .oproc = op, \ - .off = of, .type = ty } - -/* NB: table must be sorted, in vi use: - * :/^VAR/,/end_sort/! sort -t\" +1 - * breaking long lines just makes the sort harder - * - * We support all the fields required by P1003.1-2004 (SUSv3), with - * the correct default headers, except for the "tty" field, where the - * standard says the header should be "TT", but we have "TTY". - */ -VAR var[] = { - VAR6("%cpu", "%CPU", 0, pcpu, 0, PCPU), - VAR6("%mem", "%MEM", 0, pmem, POFF(p_vm_rssize), INT32), - PVAR("acflag", "ACFLG", 0, p_acflag, USHORT, "x"), - VAR3("acflg", "acflag", ALIAS), - VAR3("args", "command", ALIAS), - VAR3("blocked", "sigmask", ALIAS), - VAR3("caught", "sigcatch", ALIAS), - VAR4("comm", "COMMAND", COMM|ARGV0|LJUST, command), - VAR4("command", "COMMAND", COMM|LJUST, command), - PVAR("cpu", "CPU", 0, p_estcpu, UINT, "u"), - VAR4("cpuid", "CPUID", LWP, cpuid), - VAR3("cputime", "time", ALIAS), - VAR6("ctime", "CTIME", 0, putimeval, POFF(p_uctime_sec), TIMEVAL), - GID("egid", "EGID", p_gid), - VAR4("egroup", "EGROUP", LJUST, gname), - VAR4("emul", "EMUL", LJUST, emul), - VAR6("etime", "ELAPSED", 0, elapsed, POFF(p_ustart_sec), TIMEVAL), - UID("euid", "EUID", p_uid), - VAR4("euser", "EUSER", LJUST, uname), - PVAR("f", "F", 0, p_flag, INT, "x"), - VAR3("flags", "f", ALIAS), - GID("gid", "GID", p_gid), - VAR4("group", "GROUP", LJUST, gname), - VAR4("groupnames", "GROUPNAMES", LJUST, groupnames), - VAR4("groups", "GROUPS", LJUST, groups), - /* holdcnt: unused, left for compat. */ - LVAR("holdcnt", "HOLDCNT", 0, l_holdcnt, INT, "d"), - VAR3("ignored", "sigignore", ALIAS), - PUVAR("inblk", "INBLK", 0, p_uru_inblock, UINT64, PRIu64), - VAR3("inblock", "inblk", ALIAS), - PVAR("jobc", "JOBC", 0, p_jobc, SHORT, "d"), - PVAR("ktrace", "KTRACE", 0, p_traceflag, INT, "x"), -/*XXX*/ PVAR("ktracep", "KTRACEP", 0, p_tracep, KPTR, PRIx64), - LVAR("laddr", "LADDR", 0, l_laddr, KPTR, PRIx64), - LVAR("lid", "LID", 0, l_lid, INT32, "d"), - VAR4("lim", "LIM", 0, maxrss), - VAR4("lname", "LNAME", LJUST|LWP, lname), - VAR4("login", "LOGIN", LJUST, logname), - VAR3("logname", "login", ALIAS), - VAR6("lstart", "STARTED", LJUST, lstarted, POFF(p_ustart_sec), UINT32), - VAR4("lstate", "STAT", LJUST|LWP, lstate), - VAR6("ltime", "LTIME", LWP, lcputime, 0, CPUTIME), - PUVAR("majflt", "MAJFLT", 0, p_uru_majflt, UINT64, PRIu64), - PUVAR("minflt", "MINFLT", 0, p_uru_minflt, UINT64, PRIu64), - PUVAR("msgrcv", "MSGRCV", 0, p_uru_msgrcv, UINT64, PRIu64), - PUVAR("msgsnd", "MSGSND", 0, p_uru_msgsnd, UINT64, PRIu64), - VAR3("ni", "nice", ALIAS), - VAR6("nice", "NI", 0, pnice, POFF(p_nice), UCHAR), - PUVAR("nivcsw", "NIVCSW", 0, p_uru_nivcsw, UINT64, PRIu64), - PVAR("nlwp", "NLWP", 0, p_nlwps, UINT64, PRId64), - VAR3("nsignals", "nsigs", ALIAS), - PUVAR("nsigs", "NSIGS", 0, p_uru_nsignals, UINT64, PRIu64), - /* nswap: unused, left for compat. */ - PUVAR("nswap", "NSWAP", 0, p_uru_nswap, UINT64, PRIu64), - PUVAR("nvcsw", "NVCSW", 0, p_uru_nvcsw, UINT64, PRIu64), -/*XXX*/ LVAR("nwchan", "WCHAN", 0, l_wchan, KPTR, PRIx64), - PUVAR("oublk", "OUBLK", 0, p_uru_oublock, UINT64, PRIu64), - VAR3("oublock", "oublk", ALIAS), -/*XXX*/ PVAR("p_ru", "P_RU", 0, p_ru, KPTR, PRIx64), -/*XXX*/ PVAR("paddr", "PADDR", 0, p_paddr, KPTR, PRIx64), - PUVAR("pagein", "PAGEIN", 0, p_uru_majflt, UINT64, PRIu64), - VAR3("pcpu", "%cpu", ALIAS), - VAR3("pending", "sig", ALIAS), - PID("pgid", "PGID", p__pgid), - PID("pid", "PID", p_pid), - VAR3("pmem", "%mem", ALIAS), - PID("ppid", "PPID", p_ppid), - VAR4("pri", "PRI", LWP, pri), - LVAR("re", "RE", INF127, l_swtime, UINT, "u"), - GID("rgid", "RGID", p_rgid), - VAR4("rgroup", "RGROUP", LJUST, rgname), -/*XXX*/ LVAR("rlink", "RLINK", 0, l_back, KPTR, PRIx64), - PVAR("rlwp", "RLWP", 0, p_nrlwps, UINT64, PRId64), - VAR6("rss", "RSS", 0, p_rssize, POFF(p_vm_rssize), INT32), - VAR3("rssize", "rsz", ALIAS), - VAR6("rsz", "RSZ", 0, rssize, POFF(p_vm_rssize), INT32), - UID("ruid", "RUID", p_ruid), - VAR4("ruser", "RUSER", LJUST, runame), - PVAR("sess", "SESS", 0, p_sess, KPTR24, PRIx64), - PID("sid", "SID", p_sid), - PVAR("sig", "PENDING", 0, p_siglist, SIGLIST, "s"), - PVAR("sigcatch", "CAUGHT", 0, p_sigcatch, SIGLIST, "s"), - PVAR("sigignore", "IGNORED", 0, p_sigignore, SIGLIST, "s"), - PVAR("sigmask", "BLOCKED", 0, p_sigmask, SIGLIST, "s"), - LVAR("sl", "SL", INF127, l_slptime, UINT, "u"), - VAR6("start", "STARTED", 0, started, POFF(p_ustart_sec), UINT32), - VAR3("stat", "state", ALIAS), - VAR4("state", "STAT", LJUST, state), - VAR6("stime", "STIME", 0, putimeval, POFF(p_ustime_sec), TIMEVAL), - GID("svgid", "SVGID", p_svgid), - VAR4("svgroup", "SVGROUP", LJUST, svgname), - UID("svuid", "SVUID", p_svuid), - VAR4("svuser", "SVUSER", LJUST, svuname), - /* "tdev" is UINT32, but we do this for sorting purposes */ - VAR6("tdev", "TDEV", 0, tdev, POFF(p_tdev), INT32), - VAR6("time", "TIME", 0, cputime, 0, CPUTIME), - PID("tpgid", "TPGID", p_tpgid), - PVAR("tsess", "TSESS", 0, p_tsess, KPTR, PRIx64), - VAR6("tsiz", "TSIZ", 0, tsize, POFF(p_vm_tsize), INT32), -#ifndef __minix - VAR6("tt", "TTY", LJUST, tname, POFF(p_tdev), INT32), -#else /* __minix */ - VAR6("tt", "TT", LJUST, tname, POFF(p_tdev), INT32), -#endif /* __minix */ - VAR6("tty", "TTY", LJUST, longtname, POFF(p_tdev), INT32), - LVAR("uaddr", "UADDR", 0, l_addr, KPTR, PRIx64), - VAR4("ucomm", "UCOMM", LJUST, ucomm), - UID("uid", "UID", p_uid), - LVAR("upr", "UPR", 0, l_usrpri, UCHAR, "u"), - VAR4("user", "USER", LJUST, uname), - VAR3("usrpri", "upr", ALIAS), - VAR6("utime", "UTIME", 0, putimeval, POFF(p_uutime_sec), TIMEVAL), - VAR3("vsize", "vsz", ALIAS), - VAR6("vsz", "VSZ", 0, vsize, 0, VSIZE), - VAR4("wchan", "WCHAN", LJUST|LWP, wchan), - PVAR("xstat", "XSTAT", 0, p_xstat, USHORT, "x"), -/* "zzzz" end_sort */ - { .name = "" }, -}; - -void -showkey(void) -{ - VAR *v; - int i; - const char *p; - const char *sep; - - i = 0; - sep = ""; - for (v = var; *(p = v->name); ++v) { - int len = strlen(p); - if (termwidth && (i += len + 1) > termwidth) { - i = len; - sep = "\n"; - } - (void)printf("%s%s", sep, p); - sep = " "; - } - (void)printf("\n"); -} - -/* - * Parse the string pp, and insert or append entries to the list - * referenced by listptr. If pos in non-null and *pos is non-null, then - * *pos specifies where to insert (instead of appending). If pos is - * non-null, then a new value is returned through *pos referring to the - * last item inserted. - */ -static void -parsevarlist(const char *pp, struct varlist *listptr, struct varent **pos) -{ - char *p, *sp, *equalsp; - - /* dup to avoid zapping arguments. We will free sp later. */ - p = sp = strdup(pp); - - /* - * Everything after the first '=' is part of a custom header. - * Temporarily replace it with '\0' to simplify other code. - */ - equalsp = strchr(p, '='); - if (equalsp) - *equalsp = '\0'; - -#define FMTSEP " \t,\n" - while (p && *p) { - char *cp; - VAR *v; - struct varent *vent; - - /* - * skip separators before the first keyword, and - * look for the separator after the keyword. - */ - for (cp = p; *cp != '\0'; cp++) { - p = strpbrk(cp, FMTSEP); - if (p != cp) - break; - } - if (*cp == '\0') - break; - /* - * Now cp points to the start of a keyword, - * and p is NULL or points past the end of the keyword. - * - * Terminate the keyword with '\0', or reinstate the - * '=' that was removed earlier, if appropriate. - */ - if (p) { - *p = '\0'; - p++; - } else if (equalsp) { - *equalsp = '='; - } - - /* - * If findvar() likes the keyword or keyword=header, - * add it to our list. If findvar() doesn't like it, - * it will print a warning, so we ignore it. - */ - if ((v = findvar(cp)) == NULL) - continue; - if ((vent = malloc(sizeof(struct varent))) == NULL) - err(1, NULL); - vent->var = v; - if (pos && *pos) - SIMPLEQ_INSERT_AFTER(listptr, *pos, vent, next); - else { - SIMPLEQ_INSERT_TAIL(listptr, vent, next); - } - if (pos) - *pos = vent; - } - free(sp); - if (SIMPLEQ_EMPTY(listptr)) - errx(1, "no valid keywords"); -} - -void -parsefmt(const char *p) -{ - - parsevarlist(p, &displaylist, NULL); -} - -void -parsefmt_insert(const char *p, struct varent **pos) -{ - - parsevarlist(p, &displaylist, pos); -} - -void -parsesort(const char *p) -{ - - parsevarlist(p, &sortlist, NULL); -} - -/* Search through a list for an entry with a specified name. */ -struct varent * -varlist_find(struct varlist *list, const char *name) -{ - struct varent *vent; - - SIMPLEQ_FOREACH(vent, list, next) { - if (strcmp(vent->var->name, name) == 0) - break; - } - return vent; -} - -static VAR * -findvar(const char *p) -{ - VAR *v; - char *hp; - - hp = strchr(p, '='); - if (hp) - *hp++ = '\0'; - - v = bsearch(p, var, sizeof(var)/sizeof(VAR) - 1, sizeof(VAR), vcmp); - if (v && v->flag & ALIAS) - v = findvar(v->header); - if (!v) { - warnx("%s: keyword not found", p); - eval = 1; - return NULL; - } - - if (v && hp) { - /* - * Override the header. - * - * We need to copy the entry first, and override the - * header in the copy, because the same field might be - * used multiple times with different headers. We also - * need to strdup the header. - */ - struct var *newvar; - char *newheader; - - if ((newvar = malloc(sizeof(struct var))) == NULL) - err(1, NULL); - if ((newheader = strdup(hp)) == NULL) - err(1, NULL); - memcpy(newvar, v, sizeof(struct var)); - newvar->header = newheader; - - /* - * According to P1003.1-2004, if the header text is null, - * such as -o user=, the field width will be at least as - * wide as the default header text. - */ - if (*hp == '\0') - newvar->width = strlen(v->header); - - v = newvar; - } - return v; -} - -static int -vcmp(const void *a, const void *b) -{ - return strcmp(a, ((const VAR *)b)->name); -} diff --git a/bin/ps/nlist.c b/bin/ps/nlist.c deleted file mode 100644 index 013785575..000000000 --- a/bin/ps/nlist.c +++ /dev/null @@ -1,207 +0,0 @@ -/* $NetBSD: nlist.c,v 1.26 2008/04/28 20:22:51 martin Exp $ */ - -/* - * Copyright (c) 2000 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Simon Burge. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)nlist.c 8.4 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: nlist.c,v 1.26 2008/04/28 20:22:51 martin Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ps.h" - -struct nlist psnl[] = { - { .n_name = "_fscale" }, -#define X_FSCALE 0 - { .n_name = "_ccpu" }, -#define X_CCPU 1 - { .n_name = "_physmem" }, -#define X_PHYSMEM 2 - { .n_name = "_maxslp" }, -#define X_MAXSLP 3 - { .n_name = NULL } -}; - -double ccpu; /* kernel _ccpu variable */ -int nlistread; /* if nlist already read. */ -int mempages; /* number of pages of phys. memory */ -int fscale; /* kernel _fscale variable */ -int maxslp; /* kernel _maxslp variable */ -int uspace; /* kernel USPACE value */ - -#define kread(x, v) \ - kvm_read(kd, psnl[x].n_value, (char *)&v, sizeof v) != sizeof(v) - -int -donlist(void) -{ - int rval; - fixpt_t xccpu; - - rval = 0; - nlistread = 1; - if (kvm_nlist(kd, psnl)) { - nlisterr(psnl); - eval = 1; - return (1); - } - if (kread(X_FSCALE, fscale)) { - warnx("fscale: %s", kvm_geterr(kd)); - eval = rval = 1; - } - if (kread(X_PHYSMEM, mempages)) { - warnx("avail_start: %s", kvm_geterr(kd)); - eval = rval = 1; - } - if (kread(X_CCPU, xccpu)) { - warnx("ccpu: %s", kvm_geterr(kd)); - eval = rval = 1; - } - if (kread(X_MAXSLP, maxslp)) { - warnx("maxslp: %s", kvm_geterr(kd)); - eval = rval = 1; - } - ccpu = (double)xccpu / fscale; - return (rval); -} - -int -donlist_sysctl(void) -{ - int mib[2]; - size_t size; - fixpt_t xccpu; - uint64_t memsize; - - nlistread = 1; - mib[0] = CTL_HW; - mib[1] = HW_PHYSMEM64; - size = sizeof(memsize); - if (sysctl(mib, 2, &memsize, &size, NULL, 0) == 0) - mempages = memsize / getpagesize(); - else - mempages = 0; - - mib[0] = CTL_KERN; - mib[1] = KERN_FSCALE; - size = sizeof(fscale); - if (sysctl(mib, 2, &fscale, &size, NULL, 0) == -1) - fscale = (1 << 8); /* XXX Hopefully reasonable default */ - - mib[0] = CTL_KERN; - mib[1] = KERN_CCPU; - size = sizeof(xccpu); - if (sysctl(mib, 2, &xccpu, &size, NULL, 0) == -1) - ccpu = exp(-1.0 / 20.0); /* XXX Hopefully reasonable default */ - else - ccpu = (double)xccpu / fscale; - - mib[0] = CTL_VM; - mib[1] = VM_MAXSLP; - size = sizeof(maxslp); - if (sysctl(mib, 2, &maxslp, &size, NULL, 0) == -1) -#ifdef MAXSLP - maxslp = MAXSLP; -#else - maxslp = 20; /* XXX Hopefully reasonable default */ -#endif - - mib[0] = CTL_VM; - mib[1] = VM_USPACE; - size = sizeof(uspace); - if (sysctl(mib, 2, &uspace, &size, NULL, 0) == -1) -#ifdef USPACE - uspace = USPACE; -#else - uspace = getpagesize(); /* XXX Hopefully reasonable default */ -#endif - - return 0; -} - -void -nlisterr(struct nlist nl[]) -{ - int i; - - (void)fprintf(stderr, "ps: nlist: can't find following symbols:"); - for (i = 0; nl[i].n_name != NULL; i++) - if (nl[i].n_value == 0) - (void)fprintf(stderr, " %s", nl[i].n_name); - (void)fprintf(stderr, "\n"); -} diff --git a/bin/ps/print.c b/bin/ps/print.c deleted file mode 100644 index 48c4ea1e1..000000000 --- a/bin/ps/print.c +++ /dev/null @@ -1,1483 +0,0 @@ -/* $NetBSD: print.c,v 1.123 2014/11/15 01:58:34 joerg Exp $ */ - -/* - * Copyright (c) 2000, 2007 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Simon Burge. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)print.c 8.6 (Berkeley) 4/16/94"; -#else -__RCSID("$NetBSD: print.c,v 1.123 2014/11/15 01:58:34 joerg Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ps.h" - -static char *cmdpart(char *); -static void printval(void *, VAR *, enum mode); -static int titlecmp(char *, char **); - -static void doubleprintorsetwidth(VAR *, double, int, enum mode); -static void intprintorsetwidth(VAR *, int, enum mode); -static void strprintorsetwidth(VAR *, const char *, enum mode); - -static time_t now; - -#define min(a,b) ((a) <= (b) ? (a) : (b)) - -static int -iwidth(u_int64_t v) -{ - u_int64_t nlim, lim; - int w = 1; - - for (lim = 10; v >= lim; lim = nlim) { - nlim = lim * 10; - w++; - if (nlim < lim) - break; - } - return w; -} - -static char * -cmdpart(char *arg0) -{ - char *cp; - - return ((cp = strrchr(arg0, '/')) != NULL ? cp + 1 : arg0); -} - -void -printheader(void) -{ - int len; - VAR *v; - struct varent *vent; - static int firsttime = 1; - static int noheader = 0; - - /* - * If all the columns have user-specified null headers, - * don't print the blank header line at all. - */ - if (firsttime) { - SIMPLEQ_FOREACH(vent, &displaylist, next) { - if (vent->var->header[0]) - break; - } - if (vent == NULL) { - noheader = 1; - firsttime = 0; - } - - } - if (noheader) - return; - - SIMPLEQ_FOREACH(vent, &displaylist, next) { - v = vent->var; - if (firsttime) { - len = strlen(v->header); - if (len > v->width) - v->width = len; - totwidth += v->width + 1; /* +1 for space */ - } - if (v->flag & LJUST) { - if (SIMPLEQ_NEXT(vent, next) == NULL) /* last one */ - (void)printf("%s", v->header); - else - (void)printf("%-*s", v->width, - v->header); - } else - (void)printf("%*s", v->width, v->header); - if (SIMPLEQ_NEXT(vent, next) != NULL) - (void)putchar(' '); - } - (void)putchar('\n'); - if (firsttime) { - firsttime = 0; - totwidth--; /* take off last space */ - } -} - -/* - * Return 1 if the command name in the argument vector (u-area) does - * not match the command name (p_comm) - */ -static int -titlecmp(char *name, char **argv) -{ - char *title; - int namelen; - - - /* no argument vector == no match; system processes/threads do that */ - if (argv == 0 || argv[0] == 0) - return (1); - - title = cmdpart(argv[0]); - - /* the basename matches */ - if (!strcmp(name, title)) - return (0); - - /* handle login shells, by skipping the leading - */ - if (title[0] == '-' && !strcmp(name, title + 1)) - return (0); - - namelen = strlen(name); - - /* handle daemons that report activity as daemonname: activity */ - if (argv[1] == 0 && - !strncmp(name, title, namelen) && - title[namelen + 0] == ':' && - title[namelen + 1] == ' ') - return (0); - - return (1); -} - -static void -doubleprintorsetwidth(VAR *v, double val, int prec, enum mode mode) -{ - int fmtlen; - - if (mode == WIDTHMODE) { - if (val < 0.0 && val < v->longestnd) { - fmtlen = (int)log10(-val) + prec + 2; - v->longestnd = val; - if (fmtlen > v->width) - v->width = fmtlen; - } else if (val > 0.0 && val > v->longestpd) { - fmtlen = (int)log10(val) + prec + 1; - v->longestpd = val; - if (fmtlen > v->width) - v->width = fmtlen; - } - } else { - (void)printf("%*.*f", v->width, prec, val); - } -} - -static void -intprintorsetwidth(VAR *v, int val, enum mode mode) -{ - int fmtlen; - - if (mode == WIDTHMODE) { - if (val < 0 && val < v->longestn) { - v->longestn = val; - fmtlen = iwidth(-val) + 1; - if (fmtlen > v->width) - v->width = fmtlen; - } else if (val > 0 && val > v->longestp) { - v->longestp = val; - fmtlen = iwidth(val); - if (fmtlen > v->width) - v->width = fmtlen; - } - } else - (void)printf("%*d", v->width, val); -} - -static void -strprintorsetwidth(VAR *v, const char *str, enum mode mode) -{ - int len; - - if (mode == WIDTHMODE) { - len = strlen(str); - if (len > v->width) - v->width = len; - } else { - if (v->flag & LJUST) - (void)printf("%-*.*s", v->width, v->width, str); - else - (void)printf("%*.*s", v->width, v->width, str); - } -} - -void -command(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *ki; - VAR *v; - int left; - char **argv, **p, *name; - - if (mode == WIDTHMODE) - return; - - ki = arg; - v = ve->var; - if (SIMPLEQ_NEXT(ve, next) != NULL || termwidth != UNLIMITED) { - if (SIMPLEQ_NEXT(ve, next) == NULL) { - left = termwidth - (totwidth - v->width); - if (left < 1) /* already wrapped, just use std width */ - left = v->width; - } else - left = v->width; - } else - left = -1; - if (needenv && kd) { - argv = kvm_getenvv2(kd, ki, termwidth); - if ((p = argv) != NULL) { - while (*p) { - fmt_puts(*p, &left); - p++; - fmt_putc(' ', &left); - } - } - } - if (needcomm) { - name = ki->p_comm; - if (!commandonly) { - argv = kvm_getargv2(kd, ki, termwidth); - if ((p = argv) != NULL) { - while (*p) { - fmt_puts(*p, &left); - p++; - fmt_putc(' ', &left); - if (v->flag & ARGV0) - break; - } - if (!(v->flag & ARGV0) && - titlecmp(name, argv)) { - /* - * append the real command name within - * parentheses, if the command name - * does not match the one in the - * argument vector - */ - fmt_putc('(', &left); - fmt_puts(name, &left); - fmt_putc(')', &left); - } - } else { - /* - * Commands that don't set an argv vector - * are printed with square brackets if they - * are system commands. Otherwise they are - * printed within parentheses. - */ - if (ki->p_flag & P_SYSTEM) { - fmt_putc('[', &left); - fmt_puts(name, &left); - fmt_putc(']', &left); - } else { - fmt_putc('(', &left); - fmt_puts(name, &left); - fmt_putc(')', &left); - } - } - } else { - fmt_puts(name, &left); - } - } - if (SIMPLEQ_NEXT(ve, next) != NULL && left > 0) - (void)printf("%*s", left, ""); -} - -void -groups(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *ki; - VAR *v; - int left, i; - char buf[16], *p; - - if (mode == WIDTHMODE) - return; - - ki = arg; - v = ve->var; - if (SIMPLEQ_NEXT(ve, next) != NULL || termwidth != UNLIMITED) { - if (SIMPLEQ_NEXT(ve, next) == NULL) { - left = termwidth - (totwidth - v->width); - if (left < 1) /* already wrapped, just use std width */ - left = v->width; - } else - left = v->width; - } else - left = -1; - - if (ki->p_ngroups == 0) - fmt_putc('-', &left); - - for (i = 0; i < ki->p_ngroups; i++) { - (void)snprintf(buf, sizeof(buf), "%d", ki->p_groups[i]); - if (i) - fmt_putc(' ', &left); - for (p = &buf[0]; *p; p++) - fmt_putc(*p, &left); - } - - if (SIMPLEQ_NEXT(ve, next) != NULL && left > 0) - (void)printf("%*s", left, ""); -} - -void -groupnames(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *ki; - VAR *v; - int left, i; - const char *p; - - if (mode == WIDTHMODE) - return; - - ki = arg; - v = ve->var; - if (SIMPLEQ_NEXT(ve, next) != NULL || termwidth != UNLIMITED) { - if (SIMPLEQ_NEXT(ve, next) == NULL) { - left = termwidth - (totwidth - v->width); - if (left < 1) /* already wrapped, just use std width */ - left = v->width; - } else - left = v->width; - } else - left = -1; - - if (ki->p_ngroups == 0) - fmt_putc('-', &left); - - for (i = 0; i < ki->p_ngroups; i++) { - if (i) - fmt_putc(' ', &left); - for (p = group_from_gid(ki->p_groups[i], 0); *p; p++) - fmt_putc(*p, &left); - } - - if (SIMPLEQ_NEXT(ve, next) != NULL && left > 0) - (void)printf("%*s", left, ""); -} - -void -ucomm(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - - k = arg; - v = ve->var; - strprintorsetwidth(v, k->p_comm, mode); -} - -void -emul(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - - k = arg; - v = ve->var; - strprintorsetwidth(v, k->p_ename, mode); -} - -void -logname(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - - k = arg; - v = ve->var; - strprintorsetwidth(v, k->p_login, mode); -} - -void -state(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - int flag, is_zombie; - char *cp; - VAR *v; - char buf[16]; - - k = arg; - is_zombie = 0; - v = ve->var; - flag = k->p_flag; - cp = buf; - - /* - * NOTE: There are historical letters, which are no longer used: - * - * - W: indicated that process is swapped out. - * - L: indicated non-zero l_holdcnt (i.e. that process was - * prevented from swapping-out. - * - * These letters should not be used for new states to avoid - * conflicts with old applications which might depend on them. - */ - switch (k->p_stat) { - - case LSSTOP: - *cp = 'T'; - break; - - case LSSLEEP: - if (flag & L_SINTR) /* interruptable (long) */ - *cp = (int)k->p_slptime >= maxslp ? 'I' : 'S'; - else - *cp = 'D'; - break; - - case LSRUN: - case LSIDL: - *cp = 'R'; - break; - - case LSONPROC: - *cp = 'O'; - break; - - case LSZOMB: - *cp = 'Z'; - is_zombie = 1; - break; - - case LSSUSPENDED: - *cp = 'U'; - break; - - default: - *cp = '?'; - } - cp++; - if (k->p_nice < NZERO) - *cp++ = '<'; - else if (k->p_nice > NZERO) - *cp++ = 'N'; - if (flag & P_TRACED) - *cp++ = 'X'; - if (flag & P_WEXIT && !is_zombie) - *cp++ = 'E'; - if (flag & P_PPWAIT) - *cp++ = 'V'; - if (flag & P_SYSTEM) - *cp++ = 'K'; - if (k->p_eflag & EPROC_SLEADER) - *cp++ = 's'; - if (flag & P_SA) - *cp++ = 'a'; - else if (k->p_nlwps > 1) - *cp++ = 'l'; - if ((flag & P_CONTROLT) && k->p__pgid == k->p_tpgid) - *cp++ = '+'; - *cp = '\0'; - strprintorsetwidth(v, buf, mode); -} - -void -lstate(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_lwp *k; - int flag; - char *cp; - VAR *v; - char buf[16]; - - k = arg; - v = ve->var; - flag = k->l_flag; - cp = buf; - - switch (k->l_stat) { - - case LSSTOP: - *cp = 'T'; - break; - - case LSSLEEP: - if (flag & L_SINTR) /* interruptible (long) */ - *cp = (int)k->l_slptime >= maxslp ? 'I' : 'S'; - else - *cp = 'D'; - break; - - case LSRUN: - case LSIDL: - *cp = 'R'; - break; - - case LSONPROC: - *cp = 'O'; - break; - - case LSZOMB: - case LSDEAD: - *cp = 'Z'; - break; - - case LSSUSPENDED: - *cp = 'U'; - break; - - default: - *cp = '?'; - } - cp++; - if (flag & L_SYSTEM) - *cp++ = 'K'; - if (flag & L_SA) - *cp++ = 'a'; - if (flag & L_DETACHED) - *cp++ = '-'; - *cp = '\0'; - strprintorsetwidth(v, buf, mode); -} - -void -pnice(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - - k = arg; - v = ve->var; - intprintorsetwidth(v, k->p_nice - NZERO, mode); -} - -void -pri(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_lwp *l; - VAR *v; - - l = arg; - v = ve->var; - intprintorsetwidth(v, l->l_priority, mode); -} - -void -uname(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - - k = arg; - v = ve->var; - strprintorsetwidth(v, user_from_uid(k->p_uid, 0), mode); -} - -void -runame(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - - k = arg; - v = ve->var; - strprintorsetwidth(v, user_from_uid(k->p_ruid, 0), mode); -} - -void -svuname(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - - k = arg; - v = ve->var; - strprintorsetwidth(v, user_from_uid(k->p_svuid, 0), mode); -} - -void -gname(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - - k = arg; - v = ve->var; - strprintorsetwidth(v, group_from_gid(k->p_gid, 0), mode); -} - -void -rgname(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - - k = arg; - v = ve->var; - strprintorsetwidth(v, group_from_gid(k->p_rgid, 0), mode); -} - -void -svgname(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - - k = arg; - v = ve->var; - strprintorsetwidth(v, group_from_gid(k->p_svgid, 0), mode); -} - -void -tdev(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - dev_t dev; - char buff[16]; - - k = arg; - v = ve->var; - dev = k->p_tdev; - if (dev == NODEV) { - if (mode == PRINTMODE) - (void)printf("%*s", v->width, "?"); - else - if (v->width < 2) - v->width = 2; - } else { - (void)snprintf(buff, sizeof(buff), - "%lld/%lld", (long long)major(dev), (long long)minor(dev)); - strprintorsetwidth(v, buff, mode); - } -} - -void -tname(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - dev_t dev; - const char *ttname; - int noctty; - - k = arg; - v = ve->var; - dev = k->p_tdev; - if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) { - if (mode == PRINTMODE) - (void)printf("%-*s", v->width, "?"); - else - if (v->width < 2) - v->width = 2; - } else { -#ifdef __minix - /* Actually shorten TTY names. "console" is *really* long. */ - if (strcmp(ttname, "console") == 0) - ttname = "co"; - else if (strncmp(ttname, "tty", 3) == 0 && ttname[3] != '\0') - ttname += 3; - else if (strncmp(ttname, "pts/", 4) == 0 && ttname[4] != '\0') - ttname += 4; /* this is what FreeBSD does */ -#endif /* __minix */ - noctty = !(k->p_eflag & EPROC_CTTY) ? 1 : 0; - if (mode == WIDTHMODE) { - int fmtlen; - - fmtlen = strlen(ttname) + noctty; - if (v->width < fmtlen) - v->width = fmtlen; - } else { - if (noctty) - (void)printf("%-*s-", v->width - 1, ttname); - else - (void)printf("%-*s", v->width, ttname); - } - } -} - -void -longtname(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - dev_t dev; - const char *ttname; - - k = arg; - v = ve->var; - dev = k->p_tdev; - if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) { - if (mode == PRINTMODE) - (void)printf("%-*s", v->width, "?"); - else - if (v->width < 2) - v->width = 2; - } else { - strprintorsetwidth(v, ttname, mode); - } -} - -void -started(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - time_t startt; - struct tm *tp; - char buf[100], *cp; - - k = arg; - v = ve->var; - if (!k->p_uvalid) { - if (mode == PRINTMODE) - (void)printf("%*s", v->width, "-"); - return; - } - - startt = k->p_ustart_sec; - tp = localtime(&startt); - if (now == 0) - (void)time(&now); - if (now - k->p_ustart_sec < SECSPERDAY) - /* I *hate* SCCS... */ - (void)strftime(buf, sizeof(buf) - 1, "%l:%" "M%p", tp); - else if (now - k->p_ustart_sec < DAYSPERWEEK * SECSPERDAY) - /* I *hate* SCCS... */ - (void)strftime(buf, sizeof(buf) - 1, "%a%" "I%p", tp); - else - (void)strftime(buf, sizeof(buf) - 1, "%e%b%y", tp); - /* %e and %l can start with a space. */ - cp = buf; - if (*cp == ' ') - cp++; - strprintorsetwidth(v, cp, mode); -} - -void -lstarted(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - time_t startt; - char buf[100]; - - k = arg; - v = ve->var; - if (!k->p_uvalid) { - /* - * Minimum width is less than header - we don't - * need to check it every time. - */ - if (mode == PRINTMODE) - (void)printf("%*s", v->width, "-"); - return; - } - startt = k->p_ustart_sec; - - /* assume all times are the same length */ - if (mode != WIDTHMODE || v->width == 0) { - (void)strftime(buf, sizeof(buf) -1, "%c", - localtime(&startt)); - strprintorsetwidth(v, buf, mode); - } -} - -void -elapsed(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - int32_t origseconds, secs, mins, hours, days; - int fmtlen, printed_something; - - k = arg; - v = ve->var; - if (k->p_uvalid == 0) { - origseconds = 0; - } else { - if (now == 0) - (void)time(&now); - origseconds = now - k->p_ustart_sec; - if (origseconds < 0) { - /* - * Don't try to be fancy if the machine's - * clock has been rewound to before the - * process "started". - */ - origseconds = 0; - } - } - - secs = origseconds; - mins = secs / SECSPERMIN; - secs %= SECSPERMIN; - hours = mins / MINSPERHOUR; - mins %= MINSPERHOUR; - days = hours / HOURSPERDAY; - hours %= HOURSPERDAY; - - if (mode == WIDTHMODE) { - if (origseconds == 0) - /* non-zero so fmtlen is calculated at least once */ - origseconds = 1; - - if (origseconds > v->longestp) { - v->longestp = origseconds; - - if (days > 0) { - /* +9 for "-hh:mm:ss" */ - fmtlen = iwidth(days) + 9; - } else if (hours > 0) { - /* +6 for "mm:ss" */ - fmtlen = iwidth(hours) + 6; - } else { - /* +3 for ":ss" */ - fmtlen = iwidth(mins) + 3; - } - - if (fmtlen > v->width) - v->width = fmtlen; - } - } else { - printed_something = 0; - fmtlen = v->width; - - if (days > 0) { - (void)printf("%*d", fmtlen - 9, days); - printed_something = 1; - } else if (fmtlen > 9) { - (void)printf("%*s", fmtlen - 9, ""); - } - if (fmtlen > 9) - fmtlen = 9; - - if (printed_something) { - (void)printf("-%.*d", fmtlen - 7, hours); - printed_something = 1; - } else if (hours > 0) { - (void)printf("%*d", fmtlen - 6, hours); - printed_something = 1; - } else if (fmtlen > 6) { - (void)printf("%*s", fmtlen - 6, ""); - } - if (fmtlen > 6) - fmtlen = 6; - - /* Don't need to set fmtlen or printed_something any more... */ - if (printed_something) { - (void)printf(":%.*d", fmtlen - 4, mins); - } else if (mins > 0) { - (void)printf("%*d", fmtlen - 3, mins); - } else if (fmtlen > 3) { - (void)printf("%*s", fmtlen - 3, "0"); - } - - (void)printf(":%.2d", secs); - } -} - -void -wchan(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_lwp *l; - VAR *v; - char *buf; - - l = arg; - v = ve->var; - if (l->l_wchan) { - if (l->l_wmesg[0]) { - strprintorsetwidth(v, l->l_wmesg, mode); - v->width = min(v->width, KI_WMESGLEN); - } else { - (void)asprintf(&buf, "%-*" PRIx64, v->width, - l->l_wchan); - if (buf == NULL) - err(1, "%s", ""); - strprintorsetwidth(v, buf, mode); - v->width = min(v->width, KI_WMESGLEN); - free(buf); - } - } else { - if (mode == PRINTMODE) - (void)printf("%-*s", v->width, "-"); - } -} - -#define pgtok(a) (((a)*(size_t)getpagesize())/1024) - -void -vsize(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - - k = arg; - v = ve->var; - intprintorsetwidth(v, pgtok(k->p_vm_msize), mode); -} - -void -rssize(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - - k = arg; - v = ve->var; - /* XXX don't have info about shared */ - intprintorsetwidth(v, pgtok(k->p_vm_rssize), mode); -} - -void -p_rssize(void *arg, VARENT *ve, enum mode mode) /* doesn't account for text */ -{ - struct kinfo_proc2 *k; - VAR *v; - - k = arg; - v = ve->var; - intprintorsetwidth(v, pgtok(k->p_vm_rssize), mode); -} - -void -cpuid(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_lwp *l; - VAR *v; - - l = arg; - v = ve->var; - intprintorsetwidth(v, l->l_cpuid, mode); -} - -static void -cputime1(int32_t secs, int32_t psecs, VAR *v, enum mode mode) -{ - int fmtlen; - - /* - * round and scale to 100's - */ - psecs = (psecs + 5000) / 10000; - secs += psecs / 100; - psecs = psecs % 100; - - if (mode == WIDTHMODE) { - /* - * Ugg, this is the only field where a value of 0 is longer - * than the column title. - * Use SECSPERMIN, because secs is divided by that when - * passed to iwidth(). - */ - if (secs == 0) - secs = SECSPERMIN; - - if (secs > v->longestp) { - v->longestp = secs; - /* "+6" for the ":%02ld.%02ld" in the printf() below */ - fmtlen = iwidth(secs / SECSPERMIN) + 6; - if (fmtlen > v->width) - v->width = fmtlen; - } - } else { - (void)printf("%*ld:%02ld.%02ld", v->width - 6, - (long)(secs / SECSPERMIN), (long)(secs % SECSPERMIN), - (long)psecs); - } -} - -void -cputime(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - int32_t secs; - int32_t psecs; /* "parts" of a second. first micro, then centi */ - - k = arg; - v = ve->var; - - /* - * This counts time spent handling interrupts. We could - * fix this, but it is not 100% trivial (and interrupt - * time fractions only work on the sparc anyway). XXX - */ - secs = k->p_rtime_sec; - psecs = k->p_rtime_usec; - if (sumrusage) { - secs += k->p_uctime_sec; - psecs += k->p_uctime_usec; - } - - cputime1(secs, psecs, v, mode); -} - -void -lcputime(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_lwp *l; - VAR *v; - int32_t secs; - int32_t psecs; /* "parts" of a second. first micro, then centi */ - - l = arg; - v = ve->var; - - secs = l->l_rtime_sec; - psecs = l->l_rtime_usec; - - cputime1(secs, psecs, v, mode); -} - -double -getpcpu(const struct kinfo_proc2 *k) -{ - static int failure; - - if (!nlistread) - failure = (kd) ? donlist() : 1; - if (failure) - return (0.0); - -#define fxtofl(fixpt) ((double)(fixpt) / fscale) - - if (k->p_swtime == 0 || k->p_realstat == SZOMB) - return (0.0); - if (rawcpu) - return (100.0 * fxtofl(k->p_pctcpu)); - return (100.0 * fxtofl(k->p_pctcpu) / - (1.0 - exp(k->p_swtime * log(ccpu)))); -} - -void -pcpu(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - double dbl; - - k = arg; - v = ve->var; - dbl = getpcpu(k); - doubleprintorsetwidth(v, dbl, (dbl >= 99.95) ? 0 : 1, mode); -} - -double -getpmem(const struct kinfo_proc2 *k) -{ - static int failure; - double fracmem; - int szptudot; - - if (!nlistread) - failure = (kd) ? donlist() : 1; - if (failure) - return (0.0); - - /* XXX want pmap ptpages, segtab, etc. (per architecture) */ - szptudot = uspace/getpagesize(); - /* XXX don't have info about shared */ - fracmem = ((float)k->p_vm_rssize + szptudot)/mempages; - return (100.0 * fracmem); -} - -void -pmem(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - - k = arg; - v = ve->var; - doubleprintorsetwidth(v, getpmem(k), 1, mode); -} - -void -pagein(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - - k = arg; - v = ve->var; - intprintorsetwidth(v, k->p_uvalid ? k->p_uru_majflt : 0, mode); -} - -void -maxrss(void *arg, VARENT *ve, enum mode mode) -{ - VAR *v; - - v = ve->var; - /* No need to check width! */ - if (mode == PRINTMODE) - (void)printf("%*s", v->width, "-"); -} - -void -tsize(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_proc2 *k; - VAR *v; - - k = arg; - v = ve->var; - intprintorsetwidth(v, pgtok(k->p_vm_tsize), mode); -} - -/* - * Generic output routines. Print fields from various prototype - * structures. - */ -static void -printval(void *bp, VAR *v, enum mode mode) -{ - static char ofmt[32] = "%"; - int width, vok, fmtlen; - const char *fcp; - char *cp; - int64_t val; - u_int64_t uval; - - val = 0; /* XXXGCC -Wuninitialized [hpcarm] */ - uval = 0; /* XXXGCC -Wuninitialized [hpcarm] */ - - /* - * Note that the "INF127" check is nonsensical for types - * that are or can be signed. - */ -#define GET(type) (*(type *)bp) -#define CHK_INF127(n) (((n) > 127) && (v->flag & INF127) ? 127 : (n)) - -#define VSIGN 1 -#define VUNSIGN 2 -#define VPTR 3 - - if (mode == WIDTHMODE) { - vok = 0; - switch (v->type) { - case CHAR: - val = GET(char); - vok = VSIGN; - break; - case UCHAR: - uval = CHK_INF127(GET(u_char)); - vok = VUNSIGN; - break; - case SHORT: - val = GET(short); - vok = VSIGN; - break; - case USHORT: - uval = CHK_INF127(GET(u_short)); - vok = VUNSIGN; - break; - case INT32: - val = GET(int32_t); - vok = VSIGN; - break; - case INT: - val = GET(int); - vok = VSIGN; - break; - case UINT: - case UINT32: - uval = CHK_INF127(GET(u_int)); - vok = VUNSIGN; - break; - case LONG: - val = GET(long); - vok = VSIGN; - break; - case ULONG: - uval = CHK_INF127(GET(u_long)); - vok = VUNSIGN; - break; - case KPTR: - uval = GET(u_int64_t); - vok = VPTR; - break; - case KPTR24: - uval = GET(u_int64_t); - uval &= 0xffffff; - vok = VPTR; - break; - case INT64: - val = GET(int64_t); - vok = VSIGN; - break; - case UINT64: - uval = CHK_INF127(GET(u_int64_t)); - vok = VUNSIGN; - break; - - case SIGLIST: - default: - /* nothing... */; - } - switch (vok) { - case VSIGN: - if (val < 0 && val < v->longestn) { - v->longestn = val; - fmtlen = iwidth(-val) + 1; - if (fmtlen > v->width) - v->width = fmtlen; - } else if (val > 0 && val > v->longestp) { - v->longestp = val; - fmtlen = iwidth(val); - if (fmtlen > v->width) - v->width = fmtlen; - } - return; - case VUNSIGN: - if (uval > v->longestu) { - v->longestu = uval; - v->width = iwidth(uval); - } - return; - case VPTR: - fmtlen = 0; - while (uval > 0) { - uval >>= 4; - fmtlen++; - } - if (fmtlen > v->width) - v->width = fmtlen; - return; - } - } - - width = v->width; - cp = ofmt + 1; - fcp = v->fmt; - if (v->flag & LJUST) - *cp++ = '-'; - *cp++ = '*'; - while ((*cp++ = *fcp++) != '\0') - continue; - - switch (v->type) { - case CHAR: - (void)printf(ofmt, width, GET(char)); - return; - case UCHAR: - (void)printf(ofmt, width, CHK_INF127(GET(u_char))); - return; - case SHORT: - (void)printf(ofmt, width, GET(short)); - return; - case USHORT: - (void)printf(ofmt, width, CHK_INF127(GET(u_short))); - return; - case INT: - (void)printf(ofmt, width, GET(int)); - return; - case UINT: - (void)printf(ofmt, width, CHK_INF127(GET(u_int))); - return; - case LONG: - (void)printf(ofmt, width, GET(long)); - return; - case ULONG: - (void)printf(ofmt, width, CHK_INF127(GET(u_long))); - return; - case KPTR: - (void)printf(ofmt, width, GET(u_int64_t)); - return; - case KPTR24: - (void)printf(ofmt, width, GET(u_int64_t) & 0xffffff); - return; - case INT32: - (void)printf(ofmt, width, GET(int32_t)); - return; - case UINT32: - (void)printf(ofmt, width, CHK_INF127(GET(u_int32_t))); - return; - case SIGLIST: - { - sigset_t *s = (sigset_t *)(void *)bp; - size_t i; -#define SIGSETSIZE (sizeof(s->__bits) / sizeof(s->__bits[0])) - char buf[SIGSETSIZE * 8 + 1]; - - for (i = 0; i < SIGSETSIZE; i++) - (void)snprintf(&buf[i * 8], 9, "%.8x", - s->__bits[(SIGSETSIZE - 1) - i]); - - /* Skip leading zeroes */ - for (i = 0; buf[i] == '0'; i++) - continue; - - if (buf[i] == '\0') - i--; - strprintorsetwidth(v, buf + i, mode); -#undef SIGSETSIZE - } - return; - case INT64: - (void)printf(ofmt, width, GET(int64_t)); - return; - case UINT64: - (void)printf(ofmt, width, CHK_INF127(GET(u_int64_t))); - return; - default: - errx(1, "unknown type %d", v->type); - } -#undef GET -#undef CHK_INF127 -} - -void -pvar(void *arg, VARENT *ve, enum mode mode) -{ - VAR *v; - - v = ve->var; - if (v->flag & UAREA && !((struct kinfo_proc2 *)arg)->p_uvalid) { - if (mode == PRINTMODE) - (void)printf("%*s", v->width, "-"); - return; - } - - (void)printval((char *)arg + v->off, v, mode); -} - -void -putimeval(void *arg, VARENT *ve, enum mode mode) -{ - VAR *v = ve->var; - struct kinfo_proc2 *k = arg; - ulong secs = *(uint32_t *)((char *)arg + v->off); - ulong usec = *(uint32_t *)((char *)arg + v->off + sizeof (uint32_t)); - int fmtlen; - - if (!k->p_uvalid) { - if (mode == PRINTMODE) - (void)printf("%*s", v->width, "-"); - return; - } - - if (mode == WIDTHMODE) { - if (secs == 0) - /* non-zero so fmtlen is calculated at least once */ - secs = 1; - if (secs > v->longestu) { - v->longestu = secs; - if (secs <= 999) - /* sss.ssssss */ - fmtlen = iwidth(secs) + 6 + 1; - else - /* hh:mm:ss.ss */ - fmtlen = iwidth((secs + 1) / SECSPERHOUR) - + 2 + 1 + 2 + 1 + 2 + 1; - if (fmtlen > v->width) - v->width = fmtlen; - } - return; - } - - if (secs < 999) - (void)printf( "%*lu.%.6lu", v->width - 6 - 1, secs, usec); - else { - uint h, m; - usec += 5000; - if (usec >= 1000000) { - usec -= 1000000; - secs++; - } - m = secs / SECSPERMIN; - secs -= m * SECSPERMIN; - h = m / MINSPERHOUR; - m -= h * MINSPERHOUR; - (void)printf( "%*u:%.2u:%.2lu.%.2lu", v->width - 9, h, m, secs, - usec / 10000u ); - } -} - -void -lname(void *arg, VARENT *ve, enum mode mode) -{ - struct kinfo_lwp *l; - VAR *v; - - l = arg; - v = ve->var; - if (l->l_name[0] != '\0') { - strprintorsetwidth(v, l->l_name, mode); - v->width = min(v->width, KI_LNAMELEN); - } else { - if (mode == PRINTMODE) - (void)printf("%-*s", v->width, "-"); - } -} diff --git a/bin/ps/ps.1 b/bin/ps/ps.1 deleted file mode 100644 index 46a6dbfed..000000000 --- a/bin/ps/ps.1 +++ /dev/null @@ -1,708 +0,0 @@ -.\" $NetBSD: ps.1,v 1.103 2014/01/15 09:24:31 wiz Exp $ -.\" -.\" Copyright (c) 1980, 1990, 1991, 1993, 1994 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)ps.1 8.3 (Berkeley) 4/18/94 -.\" -.Dd January 15, 2014 -.Dt PS 1 -.Os -.Sh NAME -.Nm ps -.Nd process status -.Sh SYNOPSIS -.Nm -.Op Fl AaCcehjlmrSsTuvwx -.Op Fl k Ar key -.Op Fl M Ar core -.Op Fl N Ar system -.Op Fl O Ar fmt -.Op Fl o Ar fmt -.Op Fl p Ar pid -.Op Fl t Ar tty -.Op Fl U Ar user -.Op Fl W Ar swap -.Nm -.Fl L -.Sh DESCRIPTION -.Nm -displays a header line followed by lines containing information about -running processes. -By default, the display includes only processes that have -controlling terminals and are owned by your uid. -The default sort order of controlling terminal and -(among processes with the same controlling terminal) process -.Tn ID -may be changed using the -.Fl k , Fl m , -or -.Fl r -options. -.Pp -The information displayed for each process -is selected based on a set of keywords (see the -.Fl L , -.Fl O , -and -.Fl o -options). -The default output format includes, for each process, the process' -.Tn ID , -controlling terminal, CPU time (including both user and system time), -state, and associated command. -.Pp -The options are as follows: -.Bl -tag -width XNXsystemXX -.It Fl A -Display information about all processes. -This is equivalent to -.Fl a Fl x . -.It Fl a -Display information about other users' processes as well as your own. -Note that this does not display information about processes -without controlling terminals. -.It Fl C -Change the way the CPU percentage is calculated by using a -.Dq raw -CPU calculation that ignores -.Dq resident -time (this normally has no effect). -.It Fl c -Do not display full command with arguments, but only the -executable name. -This may be somewhat confusing; for example, all -.Xr sh 1 -scripts will show as -.Dq sh . -.It Fl e -Display the environment as well. -The environment for other -users' processes can only be displayed by the super-user. -.It Fl h -Repeat the information header as often as necessary to guarantee one -header per page of information. -.It Fl j -Print information associated with the following keywords: -.Ar user , pid , ppid , pgid , sess , jobc , state , tt , time , -and -.Ar command . -.It Fl k Ar key -Sort the output using the space or comma separated list of keywords. -Multiple sort keys may be specified, using any of the -.Fl k , Fl m , -or -.Fl r -options. -The default sort order is equivalent to -.Fl k Ar tdev,pid . -.It Fl L -List the set of available keywords. -.It Fl l -Display information associated with the following keywords: -.Ar uid , pid , ppid , cpu , pri , nice , vsz , rss , wchan , state , -.Ar tt , time , -and -.Ar command . -.It Fl M Ar core -Extract values from the specified core file instead of the running system. -.It Fl m -Sort by memory usage. -This is equivalent to -.Fl k Ar vsz . -.It Fl N Ar system -Extract the name list from the specified system instead of the default, -.Dq Pa /netbsd . -Ignored unless -.Fl M -is specified. -.It Fl O Ar fmt -Display information associated with the space or comma separated list -of keywords specified. -The -.Fl O -option does not suppress the default display; -it inserts additional keywords just after the -.Ar pid -keyword in the default display, or after the -.Ar pid -keyword (if any) in a non-default display specified before the -first use of the -.Fl O -flag. -Keywords inserted by multiple -.Fl O -options will be adjacent. -.Pp -An equals sign -.Pq Dq \&= -followed by a customised header string may be appended to a keyword, -as described in more detail under the -.Fl o -option. -.It Fl o Ar fmt -Display information associated with the space or comma separated list -of keywords specified. -Use of the -.Fl o -option suppresses the set of keywords that would be displayed by default, -or appends to the set of keywords specified by other options. -.Pp -An equals sign -.Pq Dq \&= -followed by a customised header string may be appended to a keyword. -This causes the printed header to use the specified string instead of -the default header associated with the keyword. -.Pp -Everything after the first equals sign is part of the customised -header text, and this may include embedded spaces -.Pq Dq " " , -commas -.Pq Dq \&, , -or equals signs -.Pq Dq \&= . -To specify multiple keywords with customised headers, use multiple -.Fl o -or -.Fl O -options. -.Pp -If all the keywords to be displayed have customised headers, -and all the customised headers are entirely empty, -then the header line is not printed at all. -.It Fl p Ar pid -Display information associated with the specified process -.Tn ID . -.It Fl r -Sort by current CPU usage. -This is equivalent to -.Fl k Ar %cpu . -.It Fl S -Change the way the process time is calculated by summing all exited -children to their parent process. -.It Fl s -Display one line for each LWP, rather than one line for each process, -and display information associated with the following keywords: -.Ar uid , pid , ppid , cpu , lid , nlwp , pri , nice , vsz , rss , -.Ar wchan , lstate , tt , time , -and -.Ar command . -.It Fl T -Display information about processes attached to the device associated -with the standard input. -.It Fl t Ar tty -Display information about processes attached to the specified terminal -device. -Use a question mark -.Pq Dq \&? -for processes not attached to a -terminal device and a minus sign -.Pq Dq - -for processes that have -been revoked from their terminal device. -.It Fl U Ar user -Display processes belonging to the specified user, -given either as a user name or a uid. -.It Fl u -Display information associated with the following keywords: -.Ar user , pid , %cpu , %mem , vsz , rss , tt , state , start , time , -and -.Ar command . -The -.Fl u -option implies the -.Fl r -option. -.It Fl v -Display information associated with the following keywords: -.Ar pid , state , time , sl , re , pagein , vsz , rss , lim , tsiz , -.Ar %cpu , %mem , -and -.Ar command . -The -.Fl v -option implies the -.Fl m -option. -.It Fl W Ar swap -Extract swap information from the specified file instead of the default, -.Dq Pa /dev/drum . -Ignored unless -.Fl M -is specified. -.It Fl w -Use 132 columns to display information instead of the default, which -is your window size. -If the -.Fl w -option is specified more than once, -.Nm -will use as many columns as necessary without regard to your window size. -.It Fl x -Also display information about processes without controlling terminals. -.El -.Pp -A complete list of the available keywords are listed below. -Some of these keywords are further specified as follows: -.Bl -tag -width indent -.It Ar %cpu -The CPU utilization of the process; this is a decaying average over up to -a minute of previous (real) time. -Since the time base over which this is computed varies (since processes may -be very young) it is possible for the sum of all -.Tn %CPU -fields to exceed 100%. -.It Ar %mem -The percentage of real memory used by this process. -.It Ar flags -The flags (in hexadecimal) associated with the process as in -the include file -.In sys/proc.h : -.Bl -column P_NOCLDSTOP P_NOCLDSTOP compact -.It Dv "P_ADVLOCK" Ta No "0x00000001 process may hold a POSIX advisory lock" -.It Dv "P_CONTROLT" Ta No "0x00000002 process has a controlling terminal" -.It Dv "P_NOCLDSTOP" Ta No "0x00000008 no" Dv SIGCHLD No when children stop -.It Dv "P_PPWAIT" Ta No "0x00000010 parent is waiting for child to exec/exit" -.It Dv "P_PROFIL" Ta No "0x00000020 process has started profiling" -.It Dv "P_SELECT" Ta No "0x00000040 selecting; wakeup/waiting danger" -.It Dv "P_SINTR" Ta No "0x00000080 sleep is interruptible" -.It Dv "P_SUGID" Ta No "0x00000100 process had set id privileges since last exec" -.It Dv "P_SYSTEM" Ta No "0x00000200 system process: no sigs or stats" -.It Dv "P_TIMEOUT" Ta No "0x00000400 timing out during sleep" -.It Dv "P_TRACED" Ta No "0x00000800 process is being traced" -.It Dv "P_WAITED" Ta No "0x00001000 debugging process has waited for child" -.It Dv "P_WEXIT" Ta No "0x00002000 working on exiting" -.It Dv "P_EXEC" Ta No "0x00004000 process called" Xr execve 2 -.It Dv "P_OWEUPC" Ta No "0x00008000 owe process an addupc() call at next ast" -.\" the routine addupc is not documented in the man pages -.It Dv "P_FSTRACE" Ta No "0x00010000 tracing via file system" -.It Dv "P_NOCLDWAIT" Ta No "0x00020000 no zombies when children die" -.It Dv "P_32" Ta No "0x00040000 32-bit process (used on 64-bit kernels)" -.It Dv "P_BIGLOCK" Ta No "0x00080000 process needs kernel ``big lock'' to run" -.It Dv "P_INEXEC" Ta No "0x00100000 process is exec'ing and cannot be traced" -.El -.It Ar lim -The soft limit on memory used, specified via a call to -.Xr setrlimit 2 . -.It Ar lstart -The exact time the command started, using the -.Dq \&%c -format described in -.Xr strftime 3 . -.It Ar nice -The process scheduling increment (see -.Xr setpriority 2 ) . -.It Ar rss -the real memory (resident set) size of the process (in 1024 byte units). -.It Ar start -The time the command started. -If the command started less than 24 hours ago, the start time is -displayed using the -.Dq %l:%M%p -format described in -.Xr strftime 3 . -If the command started less than 7 days ago, the start time is -displayed using the -.Dq %a%p -format. -Otherwise, the start time is displayed using the -.Dq %e%b%y -format. -.It Ar state -The state is given by a sequence of letters, for example, -.Dq Tn RNs . -The first letter indicates the run state of the process: -.Pp -.Bl -tag -width indent -compact -.It D -Marks a process in device or other short term, uninterruptible wait. -.It I -Marks a process that is idle (sleeping interruptibly for longer than about -.Dv MAXSLP -(default 20) seconds). -.It O -Marks a process running on a processor. -.It R -Marks a runnable process, or one that is in the process of creation. -.It S -Marks a process that is sleeping interruptibly for less than about -.Dv MAXSLP -(default 20) seconds. -.It T -Marks a stopped process. -.It U -Marks a suspended process. -.It Z -Marks a dead process that has exited, but not been waited for (a -.Dq zombie ) . -.El -.Pp -Additional characters after these, if any, indicate additional state -information: -.Pp -.Bl -tag -width indent -compact -.It + -The process is in the foreground process group of its control terminal. -.It - -The LWP is detached (can't be waited for). -.It \*[Lt] -The process has raised -.Tn CPU -scheduling priority. -.It a -The process is using scheduler activations (deprecated). -.It E -The process is in the process of exiting. -.It K -The process is a kernel thread or system process. -.It l -The process has multiple LWPs. -.It N -The process is niced (has reduced -.Tn CPU -scheduling priority) (see -.Xr setpriority 2 ) . -.It s -The process is a session leader. -.It V -The process is suspended during a -.Xr vfork 2 . -.It X -The process is being traced or debugged. -.El -.It Ar tt -An abbreviation for the pathname of the controlling terminal, if any. -The abbreviation consists of the two letters following -.Dq Pa /dev/tty -or, for the console, -.Dq co . -This is followed by a -.Dq \&- -if the process can no longer reach that -controlling terminal (i.e., it has been revoked). -.It Ar wchan -The event (an address in the system) on which a process waits. -When printed numerically, the initial part of the address is -trimmed off and the result is printed in hex, for example, 0x80324000 prints -as 324000. -.El -.Pp -When printing using the -.Ar command -keyword, a process that has exited and has a parent that has not yet -waited for the process (in other words, a zombie) is listed as -.Dq Aq defunct , -and a process which is blocked while trying to exit is listed as -.Dq Aq exiting . -.Pp -.Nm -will try to locate the processes' argument vector from the user -area in order to print the command name and arguments. -This method is not reliable because a process is allowed to destroy this -information. -The -.Ar ucomm -(accounting) keyword will always contain the real command name as -contained in the process structure's -.Va p_comm -field. -.Pp -If the command vector cannot be located (usually because it has not -been set, as is the case of system processes and/or kernel threads) -the command name is printed within square brackets. -.Pp -To indicate that the argument vector has been tampered with, -.Nm -will append the real command name to the output within parentheses -if the basename of the first argument in the argument vector -does not match the contents of the real command name. -.Pp -In addition, -.Nm -checks for the following two situations and does not append the -real command name parenthesized: -.Bl -tag -width indent -.It -shellname -The login process traditionally adds a -.Sq - -in front of the shell name to indicate a login shell. -.Nm -will not append parenthesized the command name if it matches with -the name in the first argument of the argument vector, skipping -the leading -.Sq - . -.It daemonname: current-activity -Daemon processes frequently report their current activity by setting -their name to be like -.Dq daemonname: current-activity . -.Nm -will not append parenthesized the command name, if the string preceding the -.Sq \&: -in the first argument of the argument vector matches the command name. -.El -.Sh KEYWORDS -The following is a complete list of the available keywords and their -meanings. -Several of them have aliases (keywords which are synonyms). -.Pp -.Bl -tag -width groupnames -compact -.It Ar %cpu -percentage CPU usage (alias -.Ar pcpu ) -.It Ar %mem -percentage memory usage (alias -.Ar pmem ) -.It Ar acflag -accounting flag (alias -.Ar acflg ) -.It Ar comm -command (the argv[0] value) -.It Ar command -command and arguments (alias -.Ar args ) -.It Ar cpu -short-term CPU usage factor (for scheduling) -.It Ar cpuid -CPU number the current process or lwp is running on. -.It Ar ctime -accumulated CPU time of all children that have exited -.It Ar egid -effective group id -.It Ar egroup -group name (from egid) -.It Ar emul -emulation name -.It Ar etime -elapsed time since the process was started, in the form -.Li [[dd-]hh:]mm:ss -.It Ar euid -effective user id -.It Ar euser -user name (from euid) -.It Ar flags -the process flags, in hexadecimal (alias -.Ar f ) -.It Ar gid -effective group id -.It Ar group -group name (from gid) -.It Ar groupnames -group names (from group access list) -.It Ar groups -group access list -.It Ar inblk -total blocks read (alias -.Ar inblock ) -.It Ar jobc -job control count -.It Ar ktrace -tracing flags -.It Ar ktracep -tracing vnode -.It Ar laddr -kernel virtual address of the -.Tn "struct lwp" -belonging to the LWP. -.It Ar lid -ID of the LWP -.It Ar lim -memory use limit -.It Ar lname -descriptive name of the LWP -.It Ar logname -login name of user who started the process (alias -.Ar login ) -.It Ar lstart -time started -.It Ar lstate -symbolic LWP state -.It Ar ltime -CPU time of the LWP -.It Ar majflt -total page faults -.It Ar minflt -total page reclaims -.It Ar msgrcv -total messages received (reads from pipes/sockets) -.It Ar msgsnd -total messages sent (writes on pipes/sockets) -.It Ar nice -nice value (alias -.Ar ni ) -.It Ar nivcsw -total involuntary context switches -.It Ar nlwp -number of LWPs in the process -.It Ar nsigs -total signals taken (alias -.Ar nsignals ) -.It Ar nvcsw -total voluntary context switches -.It Ar nwchan -wait channel (as an address) -.It Ar oublk -total blocks written (alias -.Ar oublock ) -.It Ar p_ru -resource usage pointer (valid only for zombie) -.It Ar paddr -kernel virtual address of the -.Tn "struct proc" -belonging to the process. -.It Ar pagein -pageins (same as majflt) -.It Ar pgid -process group number -.It Ar pid -process -.Tn ID -.It Ar ppid -parent process -.Tn ID -.It Ar pri -scheduling priority -.It Ar re -core residency time (in seconds; 127 = infinity) -.It Ar rgid -real group -.Tn ID -.It Ar rlink -reverse link on run queue, or 0 -.It Ar rlwp -number of LWPs on a processor or run queue -.It Ar rss -resident set size -.It Ar rsz -resident set size + (text size / text use count) (alias -.Ar rssize ) -.It Ar ruid -real user -.Tn ID -.It Ar ruser -user name (from ruid) -.It Ar sess -session pointer -.It Ar sid -session -.Tn ID -.It Ar sig -pending signals (alias -.Ar pending ) -.It Ar sigcatch -caught signals (alias -.Ar caught ) -.It Ar sigignore -ignored signals (alias -.Ar ignored ) -.It Ar sigmask -blocked signals (alias -.Ar blocked ) -.It Ar sl -sleep time (in seconds; 127 = infinity) -.It Ar start -time started -.It Ar state -symbolic process state (alias -.Ar stat ) -.It Ar stime -accumulated system CPU time -.It Ar svgid -saved gid from a setgid executable -.It Ar svgroup -group name (from svgid) -.It Ar svuid -saved uid from a setuid executable -.It Ar svuser -user name (from svuid) -.It Ar tdev -control terminal device number -.It Ar time -accumulated CPU time, user + system (alias -.Ar cputime ) -.It Ar tpgid -control terminal process group -.Tn ID -.It Ar tsess -control terminal session pointer -.It Ar tsiz -text size (in Kbytes) -.It Ar tt -control terminal name (two letter abbreviation) -.It Ar tty -full name of control terminal -.It Ar uaddr -kernel virtual address of the -.Tn "struct user" -belonging to the LWP. -.It Ar ucomm -name to be used for accounting -.It Ar uid -effective user -.Tn ID -.It Ar upr -scheduling priority on return from system call (alias -.Ar usrpri ) -.It Ar user -user name (from uid) -.It Ar utime -accumulated user CPU time -.It Ar vsz -virtual size in Kbytes (alias -.Ar vsize ) -.It Ar wchan -wait channel (as a symbolic name) -.It Ar xstat -exit or stop status (valid only for stopped or zombie process) -.El -.Sh FILES -.Bl -tag -width /var/run/kvm.db -compact -.It Pa /dev -special files and device names -.It Pa /dev/drum -default swap device -.It Pa /var/run/dev.cdb -/dev name database -.It Pa /var/db/kvm.db -system name list database -.It Pa /netbsd -default system name list -.El -.Sh SEE ALSO -.Xr kill 1 , -.Xr pgrep 1 , -.Xr pkill 1 , -.Xr sh 1 , -.Xr w 1 , -.Xr kvm 3 , -.Xr strftime 3 , -.Xr dev_mkdb 8 , -.Xr pstat 8 -.Sh BUGS -Since -.Nm -cannot run faster than the system and is run as any other scheduled -process, the information it displays can never be exact. diff --git a/bin/ps/ps.c b/bin/ps/ps.c deleted file mode 100644 index 1e243ae02..000000000 --- a/bin/ps/ps.c +++ /dev/null @@ -1,783 +0,0 @@ -/* $NetBSD: ps.c,v 1.83 2015/06/16 22:31:08 christos Exp $ */ - -/* - * Copyright (c) 2000-2008 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Simon Burge. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1990, 1993, 1994\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)ps.c 8.4 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: ps.c,v 1.83 2015/06/16 22:31:08 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ps.h" - -/* - * ARGOPTS must contain all option characters that take arguments - * (except for 't'!) - it is used in kludge_oldps_options() - */ -#define GETOPTSTR "aAcCeghjk:LlM:mN:O:o:p:rSsTt:U:uvW:wx" -#define ARGOPTS "kMNOopUW" - -struct kinfo_proc2 *kinfo; -struct varlist displaylist = SIMPLEQ_HEAD_INITIALIZER(displaylist); -struct varlist sortlist = SIMPLEQ_HEAD_INITIALIZER(sortlist); - -int eval; /* exit value */ -int rawcpu; /* -C */ -int sumrusage; /* -S */ -int termwidth; /* width of screen (0 == infinity) */ -int totwidth; /* calculated width of requested variables */ - -int needcomm, needenv, commandonly; -uid_t myuid; - -static struct kinfo_lwp - *pick_representative_lwp(struct kinfo_proc2 *, - struct kinfo_lwp *, int); -static struct kinfo_proc2 - *getkinfo_kvm(kvm_t *, int, int, int *); -static char *kludge_oldps_options(char *); -static int pscomp(const void *, const void *); -static void scanvars(void); -__dead static void usage(void); -static int parsenum(const char *, const char *); -int main(int, char *[]); - -char dfmt[] = "pid tt state time command"; -char jfmt[] = "user pid ppid pgid sess jobc state tt time command"; -char lfmt[] = "uid pid ppid cpu pri nice vsz rss wchan state tt time command"; -char sfmt[] = "uid pid ppid cpu lid nlwp pri nice vsz rss wchan lstate tt " - "ltime command"; -char ufmt[] = "user pid %cpu %mem vsz rss tt state start time command"; -char vfmt[] = "pid state time sl re pagein vsz rss lim tsiz %cpu %mem command"; - -const char *default_fmt = dfmt; - -struct varent *Opos = NULL; /* -O flag inserts after this point */ - -kvm_t *kd; - -static long long -ttyname2dev(const char *ttname, int *xflg, int *what) -{ - struct stat sb; - const char *ttypath; - char pathbuf[MAXPATHLEN]; - - ttypath = NULL; - if (strcmp(ttname, "?") == 0) { - *xflg = 1; - return KERN_PROC_TTY_NODEV; - } - if (strcmp(ttname, "-") == 0) - return KERN_PROC_TTY_REVOKE; - - if (strcmp(ttname, "co") == 0) - ttypath = _PATH_CONSOLE; - else if (strncmp(ttname, "pts/", 4) == 0 || - strncmp(ttname, "tty", 3) == 0) { - (void)snprintf(pathbuf, - sizeof(pathbuf), "%s%s", _PATH_DEV, ttname); - ttypath = pathbuf; - } else if (*ttname != '/') { - (void)snprintf(pathbuf, - sizeof(pathbuf), "%s%s", _PATH_TTY, ttname); - ttypath = pathbuf; - } else - ttypath = ttname; - *what = KERN_PROC_TTY; - if (stat(ttypath, &sb) == -1) { - devmajor_t pts; - int serrno; - - serrno = errno; - pts = getdevmajor("pts", S_IFCHR); - if (pts != NODEVMAJOR && strncmp(ttname, "pts/", 4) == 0) { - int ptsminor = atoi(ttname + 4); - - snprintf(pathbuf, sizeof(pathbuf), "pts/%d", ptsminor); - if (strcmp(pathbuf, ttname) == 0 && ptsminor >= 0) - return makedev(pts, ptsminor); - } - errno = serrno; - err(1, "%s", ttypath); - } - if (!S_ISCHR(sb.st_mode)) - errx(1, "%s: not a terminal", ttypath); - return sb.st_rdev; -} - -int -main(int argc, char *argv[]) -{ - struct varent *vent; - struct winsize ws; - struct kinfo_lwp *kl, *l; - int ch, i, j, fmt, lineno, nentries, nlwps; - long long flag; - int prtheader, wflag, what, xflg, showlwps; - char *nlistf, *memf, *swapf, errbuf[_POSIX2_LINE_MAX]; - char *ttname; - - setprogname(argv[0]); - (void)setlocale(LC_ALL, ""); - - if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, (char *)&ws) == -1 && - ioctl(STDERR_FILENO, TIOCGWINSZ, (char *)&ws) == -1 && - ioctl(STDIN_FILENO, TIOCGWINSZ, (char *)&ws) == -1) || - ws.ws_col == 0) - termwidth = 79; - else - termwidth = ws.ws_col - 1; - - if (argc > 1) - argv[1] = kludge_oldps_options(argv[1]); - - fmt = prtheader = wflag = xflg = showlwps = 0; - what = KERN_PROC_UID; - flag = myuid = getuid(); - memf = nlistf = swapf = NULL; - - while ((ch = getopt(argc, argv, GETOPTSTR)) != -1) - switch((char)ch) { - case 'A': - /* "-A" shows all processes, like "-ax" */ - xflg = 1; - /*FALLTHROUGH*/ - case 'a': - what = KERN_PROC_ALL; - flag = 0; - break; - case 'c': - commandonly = 1; - break; - case 'e': /* XXX set ufmt */ - needenv = 1; - break; - case 'C': - rawcpu = 1; - break; - case 'g': - break; /* no-op */ - case 'h': - prtheader = ws.ws_row > 5 ? ws.ws_row : 22; - break; - case 'j': - parsefmt(jfmt); - fmt = 1; - jfmt[0] = '\0'; - break; - case 'k': - parsesort(optarg); - break; - case 'K': - break; /* no-op - was dontuseprocfs */ - case 'L': - showkey(); - exit(0); - /* NOTREACHED */ - case 'l': - parsefmt(lfmt); - fmt = 1; - lfmt[0] = '\0'; - break; - case 'M': - memf = optarg; - break; - case 'm': - parsesort("vsz"); - break; - case 'N': - nlistf = optarg; - break; - case 'O': - /* - * If this is not the first -O option, insert - * just after the previous one. - * - * If there is no format yet, start with the default - * format, and insert after the pid column. - * - * If there is already a format, insert after - * the pid column, or at the end if there's no - * pid column. - */ - if (!Opos) { - if (!fmt) - parsefmt(default_fmt); - Opos = varlist_find(&displaylist, "pid"); - } - parsefmt_insert(optarg, &Opos); - fmt = 1; - break; - case 'o': - parsefmt(optarg); - fmt = 1; - break; - case 'p': - what = KERN_PROC_PID; - flag = parsenum(optarg, "process id"); - xflg = 1; - break; - case 'r': - parsesort("%cpu"); - break; - case 'S': - sumrusage = 1; - break; - case 's': - /* -L was already taken... */ - showlwps = 1; - default_fmt = sfmt; - break; - case 'T': - if ((ttname = ttyname(STDIN_FILENO)) == NULL) - errx(1, "stdin: not a terminal"); - flag = ttyname2dev(ttname, &xflg, &what); - break; - case 't': - flag = ttyname2dev(optarg, &xflg, &what); - break; - case 'U': - if (*optarg != '\0') { - struct passwd *pw; - - what = KERN_PROC_UID; - pw = getpwnam(optarg); - if (pw == NULL) { - flag = parsenum(optarg, "user name"); - } else - flag = pw->pw_uid; - } - break; - case 'u': - parsefmt(ufmt); - parsesort("%cpu"); - fmt = 1; - ufmt[0] = '\0'; - break; - case 'v': - parsefmt(vfmt); - parsesort("vsz"); - fmt = 1; - vfmt[0] = '\0'; - break; - case 'W': - swapf = optarg; - break; - case 'w': - if (wflag) - termwidth = UNLIMITED; - else if (termwidth < 131) - termwidth = 131; - wflag++; - break; - case 'x': - xflg = 1; - break; - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - -#define BACKWARD_COMPATIBILITY -#ifdef BACKWARD_COMPATIBILITY - if (*argv) { - nlistf = *argv; - if (*++argv) { - memf = *argv; - if (*++argv) - swapf = *argv; - } - } -#endif - - if (memf == NULL) { - kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf); - donlist_sysctl(); - } else - kd = kvm_openfiles(nlistf, memf, swapf, O_RDONLY, errbuf); - - if (kd == 0) - errx(1, "%s", errbuf); - - if (!fmt) - parsefmt(default_fmt); - - /* Add default sort criteria */ - parsesort("tdev,pid"); - SIMPLEQ_FOREACH(vent, &sortlist, next) { - if (vent->var->flag & LWP || vent->var->type == UNSPECIFIED) - warnx("Cannot sort on %s, sort key ignored", - vent->var->name); - } - - /* - * scan requested variables, noting what structures are needed. - */ - scanvars(); - - /* - * select procs - */ - if (!(kinfo = getkinfo_kvm(kd, what, flag, &nentries))) - err(1, "%s", kvm_geterr(kd)); - if (nentries == 0) { - printheader(); - exit(1); - } - /* - * sort proc list - */ - qsort(kinfo, nentries, sizeof(struct kinfo_proc2), pscomp); - /* - * For each proc, call each variable output function in - * "setwidth" mode to determine the widest element of - * the column. - */ - - for (i = 0; i < nentries; i++) { - struct kinfo_proc2 *ki = &kinfo[i]; - - if (xflg == 0 && (ki->p_tdev == (uint32_t)NODEV || - (ki->p_flag & P_CONTROLT) == 0)) - continue; - - kl = kvm_getlwps(kd, ki->p_pid, ki->p_paddr, - sizeof(struct kinfo_lwp), &nlwps); - if (kl == 0) - nlwps = 0; - if (showlwps == 0) { - l = pick_representative_lwp(ki, kl, nlwps); - SIMPLEQ_FOREACH(vent, &displaylist, next) - OUTPUT(vent, ki, l, WIDTHMODE); - } else { - /* The printing is done with the loops - * reversed, but here we don't need that, - * and this improves the code locality a bit. - */ - SIMPLEQ_FOREACH(vent, &displaylist, next) - for (j = 0; j < nlwps; j++) - OUTPUT(vent, ki, &kl[j], WIDTHMODE); - } - } - /* - * Print header - AFTER determining process field widths. - * printheader() also adds up the total width of all - * fields the first time it's called. - */ - printheader(); - /* - * For each proc, call each variable output function in - * print mode. - */ - for (i = lineno = 0; i < nentries; i++) { - struct kinfo_proc2 *ki = &kinfo[i]; - - if (xflg == 0 && (ki->p_tdev == (uint32_t)NODEV || - (ki->p_flag & P_CONTROLT ) == 0)) - continue; - kl = kvm_getlwps(kd, ki->p_pid, (u_long)ki->p_paddr, - sizeof(struct kinfo_lwp), &nlwps); - if (kl == 0) - nlwps = 0; - if (showlwps == 0) { - l = pick_representative_lwp(ki, kl, nlwps); - SIMPLEQ_FOREACH(vent, &displaylist, next) { - OUTPUT(vent, ki, l, PRINTMODE); - if (SIMPLEQ_NEXT(vent, next) != NULL) - (void)putchar(' '); - } - (void)putchar('\n'); - if (prtheader && lineno++ == prtheader - 4) { - (void)putchar('\n'); - printheader(); - lineno = 0; - } - } else { - for (j = 0; j < nlwps; j++) { - SIMPLEQ_FOREACH(vent, &displaylist, next) { - OUTPUT(vent, ki, &kl[j], PRINTMODE); - if (SIMPLEQ_NEXT(vent, next) != NULL) - (void)putchar(' '); - } - (void)putchar('\n'); - if (prtheader && lineno++ == prtheader - 4) { - (void)putchar('\n'); - printheader(); - lineno = 0; - } - } - } - } - exit(eval); - /* NOTREACHED */ -} - -static struct kinfo_lwp * -pick_representative_lwp(struct kinfo_proc2 *ki, struct kinfo_lwp *kl, int nlwps) -{ - int i, onproc, running, sleeping, stopped, suspended; - static struct kinfo_lwp zero_lwp; - - if (kl == 0) - return &zero_lwp; - - /* Trivial case: only one LWP */ - if (nlwps == 1) - return kl; - - switch (ki->p_realstat) { - case SSTOP: - case SACTIVE: - /* Pick the most live LWP */ - onproc = running = sleeping = stopped = suspended = -1; - for (i = 0; i < nlwps; i++) { - switch (kl[i].l_stat) { - case LSONPROC: - onproc = i; - break; - case LSRUN: - running = i; - break; - case LSSLEEP: - sleeping = i; - break; - case LSSTOP: - stopped = i; - break; - case LSSUSPENDED: - suspended = i; - break; - } - } - if (onproc != -1) - return &kl[onproc]; - if (running != -1) - return &kl[running]; - if (sleeping != -1) - return &kl[sleeping]; - if (stopped != -1) - return &kl[stopped]; - if (suspended != -1) - return &kl[suspended]; - break; - case SZOMB: - /* First will do */ - return kl; - break; - } - /* Error condition! */ - warnx("Inconsistent LWP state for process %d", ki->p_pid); - return kl; -} - - -static struct kinfo_proc2 * -getkinfo_kvm(kvm_t *kdp, int what, int flag, int *nentriesp) -{ - - return (kvm_getproc2(kdp, what, flag, sizeof(struct kinfo_proc2), - nentriesp)); -} - -static void -scanvars(void) -{ - struct varent *vent; - VAR *v; - - SIMPLEQ_FOREACH(vent, &displaylist, next) { - v = vent->var; - if (v->flag & COMM) { - needcomm = 1; - break; - } - } -} - -static int -pscomp(const void *a, const void *b) -{ - const struct kinfo_proc2 *ka = (const struct kinfo_proc2 *)a; - const struct kinfo_proc2 *kb = (const struct kinfo_proc2 *)b; - - int i; - int64_t i64; - VAR *v; - struct varent *ve; - const sigset_t *sa, *sb; - -#define V_SIZE(k) ((k)->p_vm_msize) -#define RDIFF_N(t, n) \ - if (((const t *)((const char *)ka + v->off))[n] > ((const t *)((const char *)kb + v->off))[n]) \ - return 1; \ - if (((const t *)((const char *)ka + v->off))[n] < ((const t *)((const char *)kb + v->off))[n]) \ - return -1; - -#define RDIFF(type) RDIFF_N(type, 0); continue - - SIMPLEQ_FOREACH(ve, &sortlist, next) { - v = ve->var; - if (v->flag & LWP) - /* LWP structure not available (yet) */ - continue; - /* Sort on pvar() fields, + a few others */ - switch (v->type) { - case CHAR: - RDIFF(char); - case UCHAR: - RDIFF(u_char); - case SHORT: - RDIFF(short); - case USHORT: - RDIFF(ushort); - case INT: - RDIFF(int); - case UINT: - RDIFF(uint); - case LONG: - RDIFF(long); - case ULONG: - RDIFF(ulong); - case INT32: - RDIFF(int32_t); - case UINT32: - RDIFF(uint32_t); - case SIGLIST: - sa = (const void *)((const char *)a + v->off); - sb = (const void *)((const char *)b + v->off); - i = 0; - do { - if (sa->__bits[i] > sb->__bits[i]) - return 1; - if (sa->__bits[i] < sb->__bits[i]) - return -1; - i++; - } while (i < (int)__arraycount(sa->__bits)); - continue; - case INT64: - RDIFF(int64_t); - case KPTR: - case KPTR24: - case UINT64: - RDIFF(uint64_t); - case TIMEVAL: - /* compare xxx_sec then xxx_usec */ - RDIFF_N(uint32_t, 0); - RDIFF_N(uint32_t, 1); - continue; - case CPUTIME: - i64 = ka->p_rtime_sec * 1000000 + ka->p_rtime_usec; - i64 -= kb->p_rtime_sec * 1000000 + kb->p_rtime_usec; - if (sumrusage) { - i64 += ka->p_uctime_sec * 1000000 - + ka->p_uctime_usec; - i64 -= kb->p_uctime_sec * 1000000 - + kb->p_uctime_usec; - } - if (i64 != 0) - return i64 > 0 ? 1 : -1; - continue; - case PCPU: - i = getpcpu(kb) - getpcpu(ka); - if (i != 0) - return i; - continue; - case VSIZE: - i = V_SIZE(kb) - V_SIZE(ka); - if (i != 0) - return i; - continue; - - default: - /* Ignore everything else */ - break; - } - } - return 0; - -#undef VSIZE -} - -/* - * ICK (all for getopt), would rather hide the ugliness - * here than taint the main code. - * - * ps foo -> ps -foo - * ps 34 -> ps -p34 - * - * The old convention that 't' with no trailing tty arg means the user's - * tty, is only supported if argv[1] doesn't begin with a '-'. This same - * feature is available with the option 'T', which takes no argument. - */ -static char * -kludge_oldps_options(char *s) -{ - size_t len; - char *newopts, *ns, *cp; - - len = strlen(s); - if ((newopts = ns = malloc(len + 3)) == NULL) - err(1, NULL); - /* - * options begin with '-' - */ - if (*s != '-') - *ns++ = '-'; /* add option flag */ - /* - * gaze to end of argv[1] - */ - cp = s + len - 1; - /* - * if the last letter is a 't' flag and there are no other option - * characters that take arguments (eg U, p, o) in the option - * string and the option string doesn't start with a '-' then - * convert to 'T' (meaning *this* terminal, i.e. ttyname(0)). - */ - if (*cp == 't' && *s != '-' && strpbrk(s, ARGOPTS) == NULL) - *cp = 'T'; - else { - /* - * otherwise check for trailing number, which *may* be a - * pid. - */ - while (cp >= s && isdigit((unsigned char)*cp)) - --cp; - } - cp++; - memmove(ns, s, (size_t)(cp - s)); /* copy up to trailing number */ - ns += cp - s; - /* - * if there's a trailing number, and not a preceding 'p' (pid) or - * 't' (tty) flag, then assume it's a pid and insert a 'p' flag. - */ - if (isdigit((unsigned char)*cp) && - (cp == s || (cp[-1] != 'U' && cp[-1] != 't' && cp[-1] != 'p' && - cp[-1] != '/' && (cp - 1 == s || cp[-2] != 't')))) - *ns++ = 'p'; - /* and append the number */ - (void)strcpy(ns, cp); /* XXX strcpy is safe here */ - - return (newopts); -} - -static int -parsenum(const char *str, const char *msg) -{ - char *ep; - unsigned long ul; - - ul = strtoul(str, &ep, 0); - - if (*str == '\0' || *ep != '\0') - errx(1, "Invalid %s: `%s'", msg, str); - - if (ul > INT_MAX) - errx(1, "Out of range %s: `%s'", msg, str); - - return (int)ul; -} - -static void -usage(void) -{ - - (void)fprintf(stderr, - "usage:\t%s\n\t %s\n\t%s\n", - "ps [-AaCcehjlmrSsTuvwx] [-k key] [-M core] [-N system] [-O fmt]", - "[-o fmt] [-p pid] [-t tty] [-U user] [-W swap]", - "ps -L"); - exit(1); - /* NOTREACHED */ -} diff --git a/bin/ps/ps.h b/bin/ps/ps.h deleted file mode 100644 index 778b96bed..000000000 --- a/bin/ps/ps.h +++ /dev/null @@ -1,96 +0,0 @@ -/* $NetBSD: ps.h,v 1.27 2014/04/20 22:48:59 dholland Exp $ */ - -/*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ps.h 8.1 (Berkeley) 5/31/93 - */ - -#include - -#define UNLIMITED 0 /* unlimited terminal width */ - -enum mode { - PRINTMODE = 0, /* print values */ - WIDTHMODE = 1 /* determine width of column */ -}; - -enum type { - UNSPECIFIED, - CHAR, UCHAR, SHORT, USHORT, INT, UINT, LONG, ULONG, - KPTR, KPTR24, INT32, UINT32, SIGLIST, INT64, UINT64, - TIMEVAL, CPUTIME, PCPU, VSIZE -}; - -/* Variables. */ -typedef SIMPLEQ_HEAD(varlist, varent) VARLIST; - -typedef struct varent { - SIMPLEQ_ENTRY(varent) next; - struct var *var; -} VARENT; - -typedef struct var { - const char *name; /* name(s) of variable */ - const char *header; /* header, possibly changed from default */ -#define COMM 0x01 /* needs exec arguments and environment (XXX) */ -#define ARGV0 0x02 /* only print argv[0] */ -#define LJUST 0x04 /* left adjust on output (trailing blanks) */ -#define INF127 0x08 /* 127 = infinity: if > 127, print 127. */ -#define LWP 0x10 /* dispatch to kinfo_lwp routine */ -#define UAREA 0x20 /* need to check p_uvalid */ -#define ALIAS 0x40 /* entry is alias for 'header' */ - u_int flag; - /* output routine */ - void (*oproc)(void *, struct varent *, enum mode); - /* - * The following (optional) elements are hooks for passing information - * to the generic output routine: pvar (that which prints simple - * elements from struct kinfo_proc2). - */ - int off; /* offset in structure */ - enum type type; /* type of element */ - const char *fmt; /* printf format */ - - /* current longest element */ - int width; /* printing width */ - int64_t longestp; /* longest positive signed value */ - int64_t longestn; /* longest negative signed value */ - u_int64_t longestu; /* longest unsigned value */ - double longestpd; /* longest positive double */ - double longestnd; /* longest negative double */ -} VAR; - -#define OUTPUT(vent, ki, kl, mode) do { \ - if ((vent)->var->flag & LWP) \ - ((vent)->var->oproc)((void *)(kl), (vent), (mode)); \ - else \ - ((vent)->var->oproc)((void *)(ki), (vent), (mode)); \ - } while (/*CONSTCOND*/ 0) - -#include "extern.h" diff --git a/bin/rcmd/Makefile b/bin/rcmd/Makefile deleted file mode 100644 index 343d57b04..000000000 --- a/bin/rcmd/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# $NetBSD: Makefile,v 1.11 2007/05/28 12:06:17 tls Exp $ - -.include - -USE_FORT?=yes # setuid -# XXX Unsupported Kerberos options were removed from man page -# XXX Don't forget to update the man page if you fix Kerberos -PROG= rcmd -SRCS= rsh.c getport.c -CPPFLAGS+=-DIN_RCMD -BINOWN= root -BINMODE=4555 -.PATH: ${NETBSDSRCDIR}/usr.bin/rsh - -.include diff --git a/bin/rcmd/rcmd.1 b/bin/rcmd/rcmd.1 deleted file mode 100644 index 9d000d391..000000000 --- a/bin/rcmd/rcmd.1 +++ /dev/null @@ -1,199 +0,0 @@ -.\" $NetBSD: rcmd.1,v 1.21 2011/05/31 11:31:10 wiz Exp $ -.\" -.\" Copyright (c) 1997 Matthew R. Green. -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" Copyright (c) 1983, 1990 The Regents of the University of California. -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" from: @(#)rsh.1 6.10 (Berkeley) 7/24/91 -.\" from: NetBSD: rsh.1,v 1.3 1997/01/09 20:21:14 tls Exp -.\" -.Dd May 31, 2011 -.Dt RCMD 1 -.Os -.Sh NAME -.Nm rcmd -.Nd backend driver for -.Xr rcmd 3 -.Sh SYNOPSIS -.Nm -.Op Fl 46dn -.Op Fl l Ar username -.Op Fl p Ar port -.Op Fl u Ar localusername -.Ar host -.Ar command -.Sh DESCRIPTION -.Nm -executes -.Ar command -on -.Ar host . -.Pp -.Nm -copies its standard input to the remote command, the standard -output of the remote command to its standard output, and the -standard error of the remote command to its standard error. -Interrupt, quit and terminate signals are propagated to the remote -command; -.Nm -normally terminates when the remote command does. -The options are as follows: -.Bl -tag -width flag -.It Fl 4 -Use IPv4 addresses only. -.It Fl 6 -Use IPv6 addresses only. -.It Fl d -The -.Fl d -option turns on socket debugging (using -.Xr setsockopt 2 ) -on the -.Tn TCP -sockets used for communication with the remote host. -.It Fl l -By default, the remote username is the same as the local username. -The -.Fl l -option allows the remote name to be specified. -Another possible way to specify the remote username -is the notation -.Ar user@host . -.It Fl n -The -.Fl n -option redirects input from the special device -.Pa /dev/null -(see the -.Sx BUGS -section of this manual page). -.It Fl p Ar port -Uses the given -.Pa port -instead of the one assigned to the service -.Dq shell . -May be given either as symbolic name or as number. -.It Fl u -The -.Fl u -option allows the local username to be specified. -Only the superuser is allowed to use this option. -.El -.Pp -Shell metacharacters which are not quoted are interpreted on local machine, -while quoted metacharacters are interpreted on the remote machine. -For example, the command -.Pp -.Dl rcmd otherhost cat remotefile \*[Gt]\*[Gt] localfile -.Pp -appends the remote file -.Ar remotefile -to the local file -.Ar localfile , -while -.Pp -.Dl rcmd otherhost cat remotefile \&"\*[Gt]\*[Gt]\&" other_remotefile -.Pp -appends -.Ar remotefile -to -.Ar other_remotefile . -.Sh FILES -.Bl -tag -width /etc/hosts -compact -.It Pa /etc/hosts -.El -.Sh SEE ALSO -.Xr rsh 1 , -.Xr rcmd 3 , -.Xr environ 7 -.Sh HISTORY -The -.Nm -command appeared in -.Nx 1.3 -and is primarily derived from -.Xr rsh 1 . -Its purpose was to create a backend driver for -.Xr rcmd 3 -that would allow the users of -.Xr rcmd 3 -to no longer require super-user privileges. -.Sh BUGS -If you are using -.Xr csh 1 -and put a -.Nm -in the background without redirecting its input away from the terminal, -it will block even if no reads are posted by the remote command. -If no input is desired you should redirect the input of -.Nm -to -.Pa /dev/null -using the -.Fl n -option. -.Pp -You cannot use -.Nm rcmd -to run an interactive command (like -.Xr rogue 6 -or -.Xr vi 1 ) . -Use -.Xr rlogin 1 -instead. -.Pp -The stop signal, -.Dv SIGSTOP , -will stop the local -.Nm -process only. -This is arguably wrong, but currently hard to fix for reasons -too complicated to explain here. diff --git a/bin/rcp/Makefile b/bin/rcp/Makefile deleted file mode 100644 index 2eaa7a112..000000000 --- a/bin/rcp/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# $NetBSD: Makefile,v 1.25 2009/02/14 08:31:13 lukem Exp $ -# @(#)Makefile 8.1 (Berkeley) 7/19/93 - -WARNS=3 - -.include - -PROG= rcp -SRCS= rcp.c util.c - -.include diff --git a/bin/rcp/extern.h b/bin/rcp/extern.h deleted file mode 100644 index cc89bacc6..000000000 --- a/bin/rcp/extern.h +++ /dev/null @@ -1,49 +0,0 @@ -/* $NetBSD: extern.h,v 1.6 2005/03/11 02:55:23 ginsbach Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)extern.h 8.1 (Berkeley) 5/31/93 - */ - -typedef struct { - int cnt; - char *buf; -} BUF; - -extern int iamremote; - -BUF *allocbuf(BUF *, int, int); -char *colon(char *); -void lostconn(int); -void nospace(void); -int okname(char *); -void run_err(const char *, ...); -int susystem(char *); -char *unbracket(char *); -void verifydir(char *); diff --git a/bin/rcp/pathnames.h b/bin/rcp/pathnames.h deleted file mode 100644 index dd88d6655..000000000 --- a/bin/rcp/pathnames.h +++ /dev/null @@ -1,42 +0,0 @@ -/* $NetBSD: pathnames.h,v 1.7 2004/08/19 23:05:00 christos Exp $ */ - -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)pathnames.h 8.1 (Berkeley) 5/31/93 - */ - -#include - -#ifdef RESCUEDIR -#define _PATH_CP RESCUEDIR "/cp" -#define _PATH_RSH RESCUEDIR "/rsh" -#else -#define _PATH_CP "/bin/cp" -#define _PATH_RSH "/usr/bin/rsh" -#endif diff --git a/bin/rcp/rcp.1 b/bin/rcp/rcp.1 deleted file mode 100644 index 792c86e6b..000000000 --- a/bin/rcp/rcp.1 +++ /dev/null @@ -1,172 +0,0 @@ -.\" $NetBSD: rcp.1,v 1.22 2012/03/22 07:58:17 wiz Exp $ -.\" -.\" Copyright (c) 1983, 1990, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)rcp.1 8.1 (Berkeley) 5/31/93 -.\" -.Dd March 8, 2005 -.Dt RCP 1 -.Os -.Sh NAME -.Nm rcp -.Nd remote file copy -.Sh SYNOPSIS -.Nm -.Op Fl 46p -.Ar file1 file2 -.Nm -.Op Fl 46pr -.Ar file ... -.Ar directory -.Sh DESCRIPTION -.Nm -copies files between machines. -Each -.Ar file -or -.Ar directory -argument is either a remote file name of the -form -.Dq rname@rhost:path , -or a local file name (containing no -.Sq \&: -(colon) characters, -or a -.Sq / -(slash) before any -.Sq \&: -(colon) characters). -.Pp -The -.Ar rhost -can be an IPv4 or an IPv6 address string. -Since IPv6 addresses already contain -.Sq \&: -(colon) characters, -an IPv6 address string must be enclosed between -.Sq \&[ -(left square bracket) and -.Sq \&] -(right square bracket) characters. -Otherwise, the first occurrence of a -.Sq \&: -(colon) character would be -interpreted as the separator between the -.Ar rhost -and the -.Ar path . -For example, -.Pp -.Dl [2001:DB8::800:200C:417A]:tmp/file -.Pp -Options: -.Bl -tag -width flag -.It Fl 4 -Use IPv4 addresses only. -.It Fl 6 -Use IPv6 addresses only. -.It Fl p -The -.Fl p -option causes -.Nm -to attempt to preserve (duplicate) in its copies the modification -times and modes of the source files, ignoring the -.Ar umask . -By default, the mode and owner of -.Ar file2 -are preserved if it already existed; otherwise the mode of the source file -modified by the -.Xr umask 2 -on the destination host is used. -.It Fl r -If any of the source files are directories, -.Nm -copies each subtree rooted at that name; in this case -the destination must be a directory. -.El -.Pp -If -.Ar path -is not a full path name, it is interpreted relative to -the login directory of the specified user -.Ar ruser -on -.Ar rhost , -or your current user name if no other remote user name is specified. -A -.Ar path -on a remote host may be quoted (using \e, ", or \(aa) -so that the metacharacters are interpreted remotely. -.Pp -.Nm -does not prompt for passwords; it performs remote execution -via -.Xr rsh 1 , -and requires the same authorization. -.Pp -.Nm -handles third party copies, where neither source nor target files -are on the current machine. -.Sh SEE ALSO -.Xr cp 1 , -.Xr ftp 1 , -.Xr rcmd 1 , -.Xr rlogin 1 , -.Xr rsh 1 , -.Xr rcmd 3 , -.Xr hosts.equiv 5 , -.Xr rhosts 5 , -.Xr environ 7 -.Sh HISTORY -The -.Nm -utility appeared in -.Bx 4.2 . -The version of -.Nm -described here -has been reimplemented with Kerberos in -.Bx 4.3 Reno . -.Sh BUGS -Doesn't detect all cases where the target of a copy might -be a file in cases where only a directory should be legal. -.Pp -Is confused by any output generated by commands in a -.Pa \&.login , -.Pa \&.profile , -or -.Pa \&.cshrc -file on the remote host. -.Pp -The destination user and hostname may have to be specified as -.Dq rhost.rname -when the destination machine is running the -.Bx 4.2 -version of -.Nm . diff --git a/bin/rcp/rcp.c b/bin/rcp/rcp.c deleted file mode 100644 index 84d562027..000000000 --- a/bin/rcp/rcp.c +++ /dev/null @@ -1,813 +0,0 @@ -/* $NetBSD: rcp.c,v 1.49 2012/05/07 15:22:54 chs Exp $ */ - -/* - * Copyright (c) 1983, 1990, 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1983, 1990, 1992, 1993\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)rcp.c 8.2 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: rcp.c,v 1.49 2012/05/07 15:22:54 chs Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pathnames.h" -#include "extern.h" - -#define OPTIONS "46dfprt" - -struct passwd *pwd; -char *pwname; -u_short port; -uid_t userid; -int errs, rem; -int pflag, iamremote, iamrecursive, targetshouldbedirectory; -int family = AF_UNSPEC; -static char dot[] = "."; - -#define CMDNEEDS 64 -char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ - -int response(void); -void rsource(char *, struct stat *); -void sink(int, char *[]); -void source(int, char *[]); -void tolocal(int, char *[]); -void toremote(char *, int, char *[]); -void usage(void); - -int -main(int argc, char *argv[]) -{ - struct servent *sp; - int ch, fflag, tflag; - char *targ; - const char *shell; - - setprogname(argv[0]); - (void)setlocale(LC_ALL, ""); - - fflag = tflag = 0; - while ((ch = getopt(argc, argv, OPTIONS)) != -1) - switch(ch) { /* User-visible flags. */ - case '4': - family = AF_INET; - break; - case '6': - family = AF_INET6; - break; - case 'K': - break; - case 'p': - pflag = 1; - break; - case 'r': - iamrecursive = 1; - break; - /* Server options. */ - case 'd': - targetshouldbedirectory = 1; - break; - case 'f': /* "from" */ - iamremote = 1; - fflag = 1; - break; - case 't': /* "to" */ - iamremote = 1; - tflag = 1; - break; - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - sp = getservbyname(shell = "shell", "tcp"); - if (sp == NULL) - errx(1, "%s/tcp: unknown service", shell); - port = sp->s_port; - - if ((pwd = getpwuid(userid = getuid())) == NULL) - errx(1, "unknown user %d", (int)userid); - - if ((pwname = strdup(pwd->pw_name)) == NULL) - err(1, NULL); - - rem = STDIN_FILENO; /* XXX */ - - if (fflag) { /* Follow "protocol", send data. */ - (void)response(); - source(argc, argv); - exit(errs); - } - - if (tflag) { /* Receive data. */ - sink(argc, argv); - exit(errs); - } - - if (argc < 2) - usage(); - if (argc > 2) - targetshouldbedirectory = 1; - - rem = -1; - /* Command to be executed on remote system using "rsh". */ - (void)snprintf(cmd, sizeof(cmd), "rcp%s%s%s", - iamrecursive ? " -r" : "", pflag ? " -p" : "", - targetshouldbedirectory ? " -d" : ""); - - (void)signal(SIGPIPE, lostconn); - - if ((targ = colon(argv[argc - 1])) != NULL)/* Dest is remote host. */ - toremote(targ, argc, argv); - else { - tolocal(argc, argv); /* Dest is local host. */ - if (targetshouldbedirectory) - verifydir(argv[argc - 1]); - } - exit(errs); - /* NOTREACHED */ -} - -void -toremote(char *targ, int argc, char *argv[]) -{ - int i; - size_t len; - char *bp, *host, *src, *suser, *thost, *tuser; - - *targ++ = 0; - if (*targ == 0) - targ = dot; - - if ((thost = strchr(argv[argc - 1], '@')) != NULL) { - /* user@host */ - *thost++ = 0; - tuser = argv[argc - 1]; - if (*tuser == '\0') - tuser = NULL; - else if (!okname(tuser)) - exit(1); - } else { - thost = argv[argc - 1]; - tuser = NULL; - } - thost = unbracket(thost); - - for (i = 0; i < argc - 1; i++) { - src = colon(argv[i]); - if (src) { /* remote to remote */ - *src++ = 0; - if (*src == 0) - src = dot; - host = strchr(argv[i], '@'); - len = strlen(_PATH_RSH) + strlen(argv[i]) + - strlen(src) + (tuser ? strlen(tuser) : 0) + - strlen(thost) + strlen(targ) + CMDNEEDS + 20; - if (!(bp = malloc(len))) - err(1, NULL); - if (host) { - *host++ = 0; - host = unbracket(host); - suser = argv[i]; - if (*suser == '\0') - suser = pwname; - else if (!okname(suser)) { - (void)free(bp); - continue; - } - (void)snprintf(bp, len, - "%s %s -l %s -n %s %s '%s%s%s:%s'", - _PATH_RSH, host, suser, cmd, src, - tuser ? tuser : "", tuser ? "@" : "", - thost, targ); - } else { - host = unbracket(argv[i]); - (void)snprintf(bp, len, - "exec %s %s -n %s %s '%s%s%s:%s'", - _PATH_RSH, argv[i], cmd, src, - tuser ? tuser : "", tuser ? "@" : "", - thost, targ); - } - (void)susystem(bp); - (void)free(bp); - } else { /* local to remote */ - if (rem == -1) { - len = strlen(targ) + CMDNEEDS + 20; - if (!(bp = malloc(len))) - err(1, NULL); - (void)snprintf(bp, len, "%s -t %s", cmd, targ); - host = thost; - rem = rcmd_af(&host, port, pwname, - tuser ? tuser : pwname, - bp, NULL, family); - if (rem < 0) - exit(1); - if (response() < 0) - exit(1); - (void)free(bp); - } - source(1, argv+i); - } - } -} - -void -tolocal(int argc, char *argv[]) -{ - int i; - size_t len; - char *bp, *host, *src, *suser; - - for (i = 0; i < argc - 1; i++) { - if (!(src = colon(argv[i]))) { /* Local to local. */ - len = strlen(_PATH_CP) + strlen(argv[i]) + - strlen(argv[argc - 1]) + 20; - if (!(bp = malloc(len))) - err(1, NULL); - (void)snprintf(bp, len, "exec %s%s%s %s %s", _PATH_CP, - iamrecursive ? " -r" : "", pflag ? " -p" : "", - argv[i], argv[argc - 1]); - if (susystem(bp)) - ++errs; - (void)free(bp); - continue; - } - *src++ = 0; - if (*src == 0) - src = dot; - if ((host = strchr(argv[i], '@')) == NULL) { - host = argv[i]; - suser = pwname; - } else { - *host++ = 0; - suser = argv[i]; - if (*suser == '\0') - suser = pwname; - else if (!okname(suser)) - continue; - } - host = unbracket(host); - len = strlen(src) + CMDNEEDS + 20; - if ((bp = malloc(len)) == NULL) - err(1, NULL); - (void)snprintf(bp, len, "%s -f %s", cmd, src); - rem = - rcmd_af(&host, port, pwname, suser, bp, NULL, family); - (void)free(bp); - if (rem < 0) { - ++errs; - continue; - } - sink(1, argv + argc - 1); - (void)close(rem); - rem = -1; - } -} - -void -source(int argc, char *argv[]) -{ - struct stat stb; - static BUF buffer; - BUF *bp; - off_t i; - off_t amt; - int fd, haderr, indx, result; - char *last, *name, buf[BUFSIZ]; - - for (indx = 0; indx < argc; ++indx) { - name = argv[indx]; - if ((fd = open(name, O_RDONLY, 0)) < 0) - goto syserr; - if (fstat(fd, &stb)) { -syserr: run_err("%s: %s", name, strerror(errno)); - goto next; - } - switch (stb.st_mode & S_IFMT) { - case S_IFREG: - break; - case S_IFDIR: - if (iamrecursive) { - rsource(name, &stb); - goto next; - } - /* FALLTHROUGH */ - default: - run_err("%s: not a regular file", name); - goto next; - } - if ((last = strrchr(name, '/')) == NULL) - last = name; - else - ++last; - if (pflag) { - /* - * Make it compatible with possible future - * versions expecting microseconds. - */ - (void)snprintf(buf, sizeof(buf), "T%lld %ld %lld %ld\n", - (long long)stb.st_mtimespec.tv_sec, - (long)stb.st_mtimespec.tv_nsec / 1000, - (long long)stb.st_atimespec.tv_sec, - (long)stb.st_atimespec.tv_nsec / 1000); - (void)write(rem, buf, strlen(buf)); - if (response() < 0) - goto next; - } -#define RCPMODEMASK (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO) - (void)snprintf(buf, sizeof(buf), "C%04o %lld %s\n", - stb.st_mode & RCPMODEMASK, (long long)stb.st_size, last); - (void)write(rem, buf, strlen(buf)); - if (response() < 0) - goto next; - if ((bp = allocbuf(&buffer, fd, BUFSIZ)) == NULL) { -next: (void)close(fd); - continue; - } - - /* Keep writing after an error so that we stay sync'd up. */ - haderr = 0; - for (i = 0; i < stb.st_size; i += bp->cnt) { - amt = bp->cnt; - if (i + amt > stb.st_size) - amt = stb.st_size - i; - if (!haderr) { - result = read(fd, bp->buf, (size_t)amt); - if (result != amt) - haderr = result >= 0 ? EIO : errno; - } - if (haderr) - (void)write(rem, bp->buf, (size_t)amt); - else { - result = write(rem, bp->buf, (size_t)amt); - if (result != amt) - haderr = result >= 0 ? EIO : errno; - } - } - if (close(fd) && !haderr) - haderr = errno; - if (!haderr) - (void)write(rem, "", 1); - else - run_err("%s: %s", name, strerror(haderr)); - (void)response(); - } -} - -void -rsource(char *name, struct stat *statp) -{ - DIR *dirp; - struct dirent *dp; - char *last, *vect[1], path[MAXPATHLEN]; - - if (!(dirp = opendir(name))) { - run_err("%s: %s", name, strerror(errno)); - return; - } - last = strrchr(name, '/'); - if (last == 0) - last = name; - else - last++; - if (pflag) { - (void)snprintf(path, sizeof(path), "T%lld %ld %lld %ld\n", - (long long)statp->st_mtimespec.tv_sec, - (long)statp->st_mtimespec.tv_nsec / 1000, - (long long)statp->st_atimespec.tv_sec, - (long)statp->st_atimespec.tv_nsec / 1000); - (void)write(rem, path, strlen(path)); - if (response() < 0) { - (void)closedir(dirp); - return; - } - } - (void)snprintf(path, sizeof(path), - "D%04o %d %s\n", statp->st_mode & RCPMODEMASK, 0, last); - (void)write(rem, path, strlen(path)); - if (response() < 0) { - (void)closedir(dirp); - return; - } - while ((dp = readdir(dirp)) != NULL) { - if (dp->d_ino == 0) - continue; - if (!strcmp(dp->d_name, dot) || !strcmp(dp->d_name, "..")) - continue; - if (strlen(name) + 1 + strlen(dp->d_name) >= MAXPATHLEN - 1) { - run_err("%s/%s: name too long", name, dp->d_name); - continue; - } - (void)snprintf(path, sizeof(path), "%s/%s", name, dp->d_name); - vect[0] = path; - source(1, vect); - } - (void)closedir(dirp); - (void)write(rem, "E\n", 2); - (void)response(); -} - -void -sink(int argc, char *argv[]) -{ - static BUF buffer; - struct stat stb; - struct timeval tv[2]; - enum { YES, NO, DISPLAYED } wrerr; - BUF *bp; - ssize_t j; - off_t i; - off_t amt; - off_t count; - int exists, first, ofd; - mode_t mask; - mode_t mode; - mode_t omode; - int setimes, targisdir; - int wrerrno = 0; /* pacify gcc */ - char ch, *cp, *np, *targ, *vect[1], buf[BUFSIZ]; - const char *why; - off_t size; - char *namebuf = NULL; - size_t cursize = 0; - -#define atime tv[0] -#define mtime tv[1] -#define SCREWUP(str) { why = str; goto screwup; } - - setimes = targisdir = 0; - mask = umask(0); - if (!pflag) - (void)umask(mask); - if (argc != 1) { - run_err("ambiguous target"); - exit(1); - } - targ = *argv; - if (targetshouldbedirectory) - verifydir(targ); - (void)write(rem, "", 1); - if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) - targisdir = 1; - for (first = 1;; first = 0) { - cp = buf; - if (read(rem, cp, 1) <= 0) - goto out; - if (*cp++ == '\n') - SCREWUP("unexpected "); - do { - if (read(rem, &ch, sizeof(ch)) != sizeof(ch)) - SCREWUP("lost connection"); - *cp++ = ch; - } while (cp < &buf[BUFSIZ - 1] && ch != '\n'); - *cp = 0; - - if (buf[0] == '\01' || buf[0] == '\02') { - if (iamremote == 0) - (void)write(STDERR_FILENO, - buf + 1, strlen(buf + 1)); - if (buf[0] == '\02') - exit(1); - ++errs; - continue; - } - if (buf[0] == 'E') { - (void)write(rem, "", 1); - goto out; - } - - if (ch == '\n') - *--cp = 0; - -#define getnum(t) (t) = 0; while (isdigit((unsigned char)*cp)) (t) = (t) * 10 + (*cp++ - '0'); - cp = buf; - if (*cp == 'T') { - setimes++; - cp++; - getnum(mtime.tv_sec); - if (*cp++ != ' ') - SCREWUP("mtime.sec not delimited"); - getnum(mtime.tv_usec); - if (*cp++ != ' ') - SCREWUP("mtime.usec not delimited"); - getnum(atime.tv_sec); - if (*cp++ != ' ') - SCREWUP("atime.sec not delimited"); - getnum(atime.tv_usec); - if (*cp++ != '\0') - SCREWUP("atime.usec not delimited"); - (void)write(rem, "", 1); - continue; - } - if (*cp != 'C' && *cp != 'D') { - /* - * Check for the case "rcp remote:foo\* local:bar". - * In this case, the line "No match." can be returned - * by the shell before the rcp command on the remote is - * executed so the ^Aerror_message convention isn't - * followed. - */ - if (first) { - run_err("%s", cp); - exit(1); - } - SCREWUP("expected control record"); - } - mode = 0; - for (++cp; cp < buf + 5; cp++) { - if (*cp < '0' || *cp > '7') - SCREWUP("bad mode"); - mode = (mode << 3) | (*cp - '0'); - } - if (*cp++ != ' ') - SCREWUP("mode not delimited"); - - for (size = 0; isdigit((unsigned char)*cp);) - size = size * 10 + (*cp++ - '0'); - if (*cp++ != ' ') - SCREWUP("size not delimited"); - if (targisdir) { - char *newnamebuf; - size_t need; - - need = strlen(targ) + strlen(cp) + 2; - if (need > cursize) { - need += 256; - newnamebuf = realloc(namebuf, need); - if (newnamebuf != NULL) { - namebuf = newnamebuf; - cursize = need; - } else { - run_err("%s", strerror(errno)); - exit(1); - } - } - (void)snprintf(namebuf, cursize, "%s%s%s", targ, - *targ ? "/" : "", cp); - np = namebuf; - } else - np = targ; - exists = stat(np, &stb) == 0; - if (buf[0] == 'D') { - int mod_flag = pflag; - if (exists) { - if (!S_ISDIR(stb.st_mode)) { - errno = ENOTDIR; - goto bad; - } - if (pflag) - (void)chmod(np, mode); - } else { - /* Handle copying from a read-only directory */ - mod_flag = 1; - if (mkdir(np, mode | S_IRWXU) < 0) - goto bad; - } - vect[0] = np; - sink(1, vect); - if (setimes) { - setimes = 0; - if (utimes(np, tv) < 0) - run_err("%s: set times: %s", - np, strerror(errno)); - } - if (mod_flag) - (void)chmod(np, mode); - continue; - } - omode = mode; - mode |= S_IWRITE; - if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { -bad: run_err("%s: %s", np, strerror(errno)); - continue; - } - (void)write(rem, "", 1); - if ((bp = allocbuf(&buffer, ofd, BUFSIZ)) == NULL) { - (void)close(ofd); - continue; - } - cp = bp->buf; - wrerr = NO; - count = 0; - for (i = 0; i < size; i += BUFSIZ) { - amt = BUFSIZ; - if (i + amt > size) - amt = size - i; - count += amt; - do { - j = read(rem, cp, (size_t)amt); - if (j == -1) { - run_err("%s", j ? strerror(errno) : - "dropped connection"); - exit(1); - } - amt -= j; - cp += j; - } while (amt > 0); - if (count == bp->cnt) { - /* Keep reading so we stay sync'd up. */ - if (wrerr == NO) { - j = write(ofd, bp->buf, (size_t)count); - if (j != count) { - wrerr = YES; - wrerrno = j >= 0 ? EIO : errno; - } - } - count = 0; - cp = bp->buf; - } - } - if (count != 0 && wrerr == NO && - (j = write(ofd, bp->buf, (size_t)count)) != count) { - wrerr = YES; - wrerrno = j >= 0 ? EIO : errno; - } - if (ftruncate(ofd, size)) { - run_err("%s: truncate: %s", np, strerror(errno)); - wrerr = DISPLAYED; - } - if (pflag) { - if (exists || omode != mode) - if (fchmod(ofd, omode)) - run_err("%s: set mode: %s", - np, strerror(errno)); - } else { - if (!exists && omode != mode) - if (fchmod(ofd, omode & ~mask)) - run_err("%s: set mode: %s", - np, strerror(errno)); - } -#ifndef __SVR4 - if (setimes && wrerr == NO) { - setimes = 0; - if (futimes(ofd, tv) < 0) { - run_err("%s: set times: %s", - np, strerror(errno)); - wrerr = DISPLAYED; - } - } -#endif - (void)close(ofd); -#ifdef __SVR4 - if (setimes && wrerr == NO) { - setimes = 0; - if (utimes(np, tv) < 0) { - run_err("%s: set times: %s", - np, strerror(errno)); - wrerr = DISPLAYED; - } - } -#endif - (void)response(); - switch(wrerr) { - case YES: - run_err("%s: write: %s", np, strerror(wrerrno)); - break; - case NO: - (void)write(rem, "", 1); - break; - case DISPLAYED: - break; - } - } - -out: - if (namebuf) { - free(namebuf); - } - return; - -screwup: - run_err("protocol error: %s", why); - exit(1); - /* NOTREACHED */ -} - - -int -response(void) -{ - char ch, *cp, resp, rbuf[BUFSIZ]; - - if (read(rem, &resp, sizeof(resp)) != sizeof(resp)) - lostconn(0); - - cp = rbuf; - switch(resp) { - case 0: /* ok */ - return (0); - default: - *cp++ = resp; - /* FALLTHROUGH */ - case 1: /* error, followed by error msg */ - case 2: /* fatal error, "" */ - do { - if (read(rem, &ch, sizeof(ch)) != sizeof(ch)) - lostconn(0); - *cp++ = ch; - } while (cp < &rbuf[BUFSIZ] && ch != '\n'); - - if (!iamremote) - (void)write(STDERR_FILENO, rbuf, (size_t)(cp - rbuf)); - ++errs; - if (resp == 1) - return (-1); - exit(1); - } - /* NOTREACHED */ -} - -void -usage(void) -{ - (void)fprintf(stderr, - "usage: rcp [-46p] f1 f2; or: rcp [-46pr] f1 ... fn directory\n"); - exit(1); - /* NOTREACHED */ -} - -#include - - -void -run_err(const char *fmt, ...) -{ - static FILE *fp; - va_list ap; - - ++errs; - if (fp == NULL && !(fp = fdopen(rem, "w"))) - return; - - va_start(ap, fmt); - - (void)fprintf(fp, "%c", 0x01); - (void)fprintf(fp, "rcp: "); - (void)vfprintf(fp, fmt, ap); - (void)fprintf(fp, "\n"); - (void)fflush(fp); - va_end(ap); - - if (!iamremote) { - va_start(ap, fmt); - vwarnx(fmt, ap); - va_end(ap); - } -} diff --git a/bin/rcp/util.c b/bin/rcp/util.c deleted file mode 100644 index e53aec93e..000000000 --- a/bin/rcp/util.c +++ /dev/null @@ -1,184 +0,0 @@ -/* $NetBSD: util.c,v 1.11 2006/12/15 22:45:34 christos Exp $ */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)util.c 8.2 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: util.c,v 1.11 2006/12/15 22:45:34 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "extern.h" - -char * -colon(char *cp) -{ - if (*cp == ':') /* Leading colon is part of file name. */ - return (0); - - for (; *cp; ++cp) { - if (*cp == ':') - return (cp); - if (*cp == '/') - return (0); - } - return (0); -} - -char * -unbracket(char *cp) -{ - char *ep; - - if (*cp == '[') { - ep = cp + (strlen(cp) - 1); - if (*ep == ']') { - *ep = '\0'; - ++cp; - } - } - return (cp); -} - -void -verifydir(char *cp) -{ - struct stat stb; - - if (!stat(cp, &stb)) { - if (S_ISDIR(stb.st_mode)) - return; - errno = ENOTDIR; - } - run_err("%s: %s", cp, strerror(errno)); - exit(1); - /* NOTREACHED */ -} - -int -okname(char *cp0) -{ - int c; - char *cp; - - cp = cp0; - do { - c = *cp; - if (c & 0200) - goto bad; - if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-') - goto bad; - } while (*++cp); - return (1); - -bad: warnx("%s: invalid user name", cp0); - return (0); -} - -int -susystem(char *s) -{ - sig_t istat, qstat; - int status; - pid_t pid; - - pid = vfork(); - switch (pid) { - case -1: - return (127); - - case 0: - (void)execl(_PATH_BSHELL, "sh", "-c", s, NULL); - _exit(127); - /* NOTREACHED */ - } - istat = signal(SIGINT, SIG_IGN); - qstat = signal(SIGQUIT, SIG_IGN); - if (waitpid(pid, &status, 0) < 0) - status = -1; - (void)signal(SIGINT, istat); - (void)signal(SIGQUIT, qstat); - return (status); -} - -BUF * -allocbuf(BUF *bp, int fd, int blksize) -{ - struct stat stb; - size_t size; - char *nbuf; - - if (fstat(fd, &stb) < 0) { - run_err("fstat: %s", strerror(errno)); - return (0); - } - size = roundup(stb.st_blksize, blksize); - if (size == 0) - size = blksize; - if (bp->cnt >= size) - return (bp); - if ((nbuf = realloc(bp->buf, size)) == NULL) { - free(bp->buf); - bp->buf = NULL; - bp->cnt = 0; - run_err("%s", strerror(errno)); - return (0); - } - bp->buf = nbuf; - bp->cnt = size; - return (bp); -} - -void -/*ARGSUSED*/ -lostconn(int signo __unused) -{ - if (!iamremote) - warnx("lost connection"); - exit(1); - /* NOTREACHED */ -} diff --git a/bin/rm/Makefile b/bin/rm/Makefile deleted file mode 100644 index 85e9917cd..000000000 --- a/bin/rm/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# $NetBSD: Makefile,v 1.9 1997/07/20 22:37:50 christos Exp $ -# @(#)Makefile 8.1 (Berkeley) 5/31/93 - -PROG= rm - -.include diff --git a/bin/rm/rm.1 b/bin/rm/rm.1 deleted file mode 100644 index 061676cfa..000000000 --- a/bin/rm/rm.1 +++ /dev/null @@ -1,215 +0,0 @@ -.\" $NetBSD: rm.1,v 1.28 2016/08/12 02:26:42 sevan Exp $ -.\" -.\" Copyright (c) 1990, 1993, 1994, 2003 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Institute of Electrical and Electronics Engineers, Inc. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)rm.1 8.5 (Berkeley) 12/5/94 -.\" -.Dd August 12, 2016 -.Dt RM 1 -.Os -.Sh NAME -.Nm rm -.Nd remove directory entries -.Sh SYNOPSIS -.Nm -.Op Fl f | Fl i -.Op Fl dPRrvWx -.Ar -.Sh DESCRIPTION -The -.Nm -utility attempts to remove the non-directory type files specified on the -command line. -If the permissions of the file do not permit writing, and the standard -input device is a terminal, the user is prompted (on the standard error -output) for confirmation. -.Pp -The options are as follows: -.Bl -tag -width flag -.It Fl d -Attempt to remove directories as well as other types of files. -.It Fl f -Attempt to remove the files without prompting for confirmation, -regardless of the file's permissions. -If the file does not exist, do not display a diagnostic message or modify -the exit status to reflect an error. -The -.Fl f -option overrides any previous -.Fl i -options. -.It Fl i -Request confirmation before attempting to remove each file, regardless of -the file's permissions, or whether or not the standard input device is a -terminal. -The -.Fl i -option overrides any previous -.Fl f -options. -.It Fl P -Overwrite regular files before deleting them. -Files are overwritten three times, first with the byte pattern 0xff, -then 0x00, and then with random data, before they are deleted. -Some care is taken to ensure that the data are actually written to -disk, but this cannot be guaranteed, even on traditional filesystems; -on log-structured filesystems or if any block-journaling scheme is -in use, this option is completely useless. -If the file cannot be -overwritten, it will not be removed. -.It Fl R -Attempt to remove the file hierarchy rooted in each file argument. -The -.Fl R -option implies the -.Fl d -option. -If the -.Fl i -option is specified, the user is prompted for confirmation before -each directory's contents are processed (as well as before the attempt -is made to remove the directory). -If the user does not respond affirmatively, the file hierarchy rooted in -that directory is skipped. -.It Fl r -Equivalent to -.Fl R . -.It Fl v -Cause -.Nm -to be verbose, showing files as they are processed. -.It Fl W -Attempts to undelete the named files. -Currently, this option can only be used to recover -files covered by whiteouts. -.It Fl x -When removing a hierarchy, do not cross mount points. -.El -.Pp -The -.Nm -utility removes symbolic links, not the files referenced by the links. -.Pp -It is an error to attempt to remove the files ``.'' and ``..''. -.Sh EXIT STATUS -The -.Nm -utility exits 0 if all of the named files or file hierarchies were removed, -or if the -.Fl f -option was specified and all of the existing files or file hierarchies were -removed. -If an error occurs, -.Nm -exits with a value \*[Gt]0. -.Sh EXAMPLES -.Nm -uses -.Xr getopt 3 -standard argument processing. -Removing filenames that begin with a dash -.Pq e.g., Ar -file -in the current directory which might otherwise be taken as option flags to -.Nm -can be accomplished as follows: -.Pp -.Ic "rm -- -file" -.Pp -or -.Pp -.Ic "rm ./-file" -.Sh COMPATIBILITY -The -.Nm -utility differs from historical implementations in that the -.Fl f -option only masks attempts to remove non-existent files instead of -masking a large variety of errors. -.Pp -Also, historical -.Bx -implementations prompted on the standard output, -not the standard error output. -.Sh SEE ALSO -.Xr rmdir 1 , -.Xr undelete 2 , -.Xr unlink 2 , -.Xr fts 3 , -.Xr getopt 3 , -.Xr symlink 7 -.Sh STANDARDS -The -.Nm -utility is expected to be -.St -p1003.2 -compatible. -The -.Fl v -and -.Fl x -options are extensions. -.Pp -The -.Fl P -option attempts to conform to U.S. DoD 5220-22.M, "National Industrial -Security Program Operating Manual" ("NISPOM") as updated by Change -2 and the July 23, 2003 "Clearing \*[Am] Sanitization Matrix". -However, unlike earlier revisions of NISPOM, the 2003 matrix imposes -requirements which make it clear that the standard does not and -can not apply to the erasure of individual files, in particular -requirements relating to spare sector management for an entire -magnetic disk. -.Em Because these requirements are not met, the -.Fl P -.Em option does not conform to the standard . -.Sh HISTORY -An -.Nm -utility appeared in -.At v1 . -.Sh BUGS -The -.Fl P -option assumes that the underlying file system is a fixed-block file -system. -FFS is a fixed-block file system, LFS is not. -In addition, only regular files are overwritten, other types of files -are not. -Recent research indicates that as many as 35 overwrite passes with -carefully chosen data patterns may be necessary to actually prevent -recovery of data from a magnetic disk. -Thus the -.Fl P -option is likely both insufficient for its design purpose and far -too costly for default operation. -However, it will at least prevent the recovery of data from FFS -volumes with -.Xr fsdb 8 . diff --git a/bin/rm/rm.c b/bin/rm/rm.c deleted file mode 100644 index 93882acc6..000000000 --- a/bin/rm/rm.c +++ /dev/null @@ -1,635 +0,0 @@ -/* $NetBSD: rm.c,v 1.53 2013/04/26 18:43:22 christos Exp $ */ - -/*- - * Copyright (c) 1990, 1993, 1994, 2003 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1990, 1993, 1994\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)rm.c 8.8 (Berkeley) 4/27/95"; -#else -__RCSID("$NetBSD: rm.c,v 1.53 2013/04/26 18:43:22 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int dflag, eval, fflag, iflag, Pflag, stdin_ok, vflag, Wflag; -static int xflag; -static sig_atomic_t pinfo; - -static int check(char *, char *, struct stat *); -static void checkdot(char **); -static void progress(int); -static void rm_file(char **); -static int rm_overwrite(char *, struct stat *); -static void rm_tree(char **); -__dead static void usage(void); - -#if defined(__minix) -# ifndef O_SYNC -# define O_SYNC 0 -# endif -# ifndef O_RSYNC -# define O_RSYNC 0 -# endif -#endif /* defined(__minix) */ - -/* - * For the sake of the `-f' flag, check whether an error number indicates the - * failure of an operation due to an non-existent file, either per se (ENOENT) - * or because its filename argument was illegal (ENAMETOOLONG, ENOTDIR). - */ -#define NONEXISTENT(x) \ - ((x) == ENOENT || (x) == ENAMETOOLONG || (x) == ENOTDIR) - -/* - * rm -- - * This rm is different from historic rm's, but is expected to match - * POSIX 1003.2 behavior. The most visible difference is that -f - * has two specific effects now, ignore non-existent files and force - * file removal. - */ -int -main(int argc, char *argv[]) -{ - int ch, rflag; - - setprogname(argv[0]); - (void)setlocale(LC_ALL, ""); - - Pflag = rflag = xflag = 0; - while ((ch = getopt(argc, argv, "dfiPRrvWx")) != -1) - switch (ch) { - case 'd': - dflag = 1; - break; - case 'f': - fflag = 1; - iflag = 0; - break; - case 'i': - fflag = 0; - iflag = 1; - break; - case 'P': - Pflag = 1; - break; - case 'R': - case 'r': /* Compatibility. */ - rflag = 1; - break; - case 'v': - vflag = 1; - break; - case 'x': - xflag = 1; - break; - case 'W': - Wflag = 1; - break; - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc < 1) { - if (fflag) - return 0; - usage(); - } - - (void)signal(SIGINFO, progress); - - checkdot(argv); - - if (*argv) { - stdin_ok = isatty(STDIN_FILENO); - - if (rflag) - rm_tree(argv); - else - rm_file(argv); - } - - exit(eval); - /* NOTREACHED */ -} - -static void -rm_tree(char **argv) -{ - FTS *fts; - FTSENT *p; - int flags, needstat, rval; - - /* - * Remove a file hierarchy. If forcing removal (-f), or interactive - * (-i) or can't ask anyway (stdin_ok), don't stat the file. - */ - needstat = !fflag && !iflag && stdin_ok; - - /* - * If the -i option is specified, the user can skip on the pre-order - * visit. The fts_number field flags skipped directories. - */ -#define SKIPPED 1 - - flags = FTS_PHYSICAL; - if (!needstat) - flags |= FTS_NOSTAT; -#if !defined(__minix) - if (Wflag) - flags |= FTS_WHITEOUT; -#endif /* !defined(__minix) */ - if (xflag) - flags |= FTS_XDEV; - if ((fts = fts_open(argv, flags, NULL)) == NULL) - err(1, "fts_open failed"); - while ((p = fts_read(fts)) != NULL) { - - switch (p->fts_info) { - case FTS_DNR: - if (!fflag || p->fts_errno != ENOENT) { - warnx("%s: %s", p->fts_path, - strerror(p->fts_errno)); - eval = 1; - } - continue; - case FTS_ERR: - errx(EXIT_FAILURE, "%s: %s", p->fts_path, - strerror(p->fts_errno)); - /* NOTREACHED */ - case FTS_NS: - /* - * FTS_NS: assume that if can't stat the file, it - * can't be unlinked. - */ - if (fflag && NONEXISTENT(p->fts_errno)) - continue; - if (needstat) { - warnx("%s: %s", p->fts_path, - strerror(p->fts_errno)); - eval = 1; - continue; - } - break; - case FTS_D: - /* Pre-order: give user chance to skip. */ - if (!fflag && !check(p->fts_path, p->fts_accpath, - p->fts_statp)) { - (void)fts_set(fts, p, FTS_SKIP); - p->fts_number = SKIPPED; - } - continue; - case FTS_DP: - /* Post-order: see if user skipped. */ - if (p->fts_number == SKIPPED) - continue; - break; - default: - if (!fflag && - !check(p->fts_path, p->fts_accpath, p->fts_statp)) - continue; - } - - rval = 0; - /* - * If we can't read or search the directory, may still be - * able to remove it. Don't print out the un{read,search}able - * message unless the remove fails. - */ - switch (p->fts_info) { - case FTS_DP: - case FTS_DNR: - rval = rmdir(p->fts_accpath); - if (rval != 0 && fflag && errno == ENOENT) - continue; - break; - -#if !defined(__minix) - case FTS_W: - rval = undelete(p->fts_accpath); - if (rval != 0 && fflag && errno == ENOENT) - continue; - break; -#endif /* !defined(__minix) */ - - default: - if (Pflag) { - if (rm_overwrite(p->fts_accpath, NULL)) - continue; - } - rval = unlink(p->fts_accpath); - if (rval != 0 && fflag && NONEXISTENT(errno)) - continue; - break; - } - if (rval != 0) { - warn("%s", p->fts_path); - eval = 1; - } else if (vflag || pinfo) { - pinfo = 0; - (void)printf("%s\n", p->fts_path); - } - } - if (errno) - err(1, "fts_read"); - fts_close(fts); -} - -static void -rm_file(char **argv) -{ - struct stat sb; - int rval; - char *f; - - /* - * Remove a file. POSIX 1003.2 states that, by default, attempting - * to remove a directory is an error, so must always stat the file. - */ - while ((f = *argv++) != NULL) { - /* Assume if can't stat the file, can't unlink it. */ - if (lstat(f, &sb)) { - if (Wflag) { -#if defined(__minix) - sb.st_mode = S_IWUSR|S_IRUSR; -#else - sb.st_mode = S_IFWHT|S_IWUSR|S_IRUSR; -#endif /* defined(__minix) */ - } else { - if (!fflag || !NONEXISTENT(errno)) { - warn("%s", f); - eval = 1; - } - continue; - } - } else if (Wflag) { - warnx("%s: %s", f, strerror(EEXIST)); - eval = 1; - continue; - } - - if (S_ISDIR(sb.st_mode) && !dflag) { - warnx("%s: is a directory", f); - eval = 1; - continue; - } -#if !defined(__minix) - if (!fflag && !S_ISWHT(sb.st_mode) && !check(f, f, &sb)) -#else - if (!fflag && !check(f, f, &sb)) -#endif /* !defined(__minix) */ - continue; -#if !defined(__minix) - if (S_ISWHT(sb.st_mode)) - rval = undelete(f); - else -#endif /* !defined(__minix) */ - if (S_ISDIR(sb.st_mode)) - rval = rmdir(f); - else { - if (Pflag) { - if (rm_overwrite(f, &sb)) - continue; - } - rval = unlink(f); - } - if (rval && (!fflag || !NONEXISTENT(errno))) { - warn("%s", f); - eval = 1; - } - if (vflag && rval == 0) - (void)printf("%s\n", f); - } -} - -/* - * rm_overwrite -- - * Overwrite the file 3 times with varying bit patterns. - * - * This is an expensive way to keep people from recovering files from your - * non-snapshotted FFS filesystems using fsdb(8). Really. No more. Only - * regular files are deleted, directories (and therefore names) will remain. - * Also, this assumes a fixed-block file system (like FFS, or a V7 or a - * System V file system). In a logging file system, you'll have to have - * kernel support. - * - * A note on standards: U.S. DoD 5220.22-M "National Industrial Security - * Program Operating Manual" ("NISPOM") is often cited as a reference - * for clearing and sanitizing magnetic media. In fact, a matrix of - * "clearing" and "sanitization" methods for various media was given in - * Chapter 8 of the original 1995 version of NISPOM. However, that - * matrix was *removed from the document* when Chapter 8 was rewritten - * in Change 2 to the document in 2001. Recently, the Defense Security - * Service has made a revised clearing and sanitization matrix available - * in Microsoft Word format on the DSS web site. The standardization - * status of this matrix is unclear. Furthermore, one must be very - * careful when referring to this matrix: it is intended for the "clearing" - * prior to reuse or "sanitization" prior to disposal of *entire media*, - * not individual files and the only non-physically-destructive method of - * "sanitization" that is permitted for magnetic disks of any kind is - * specifically noted to be prohibited for media that have contained - * Top Secret data. - * - * It is impossible to actually conform to the exact procedure given in - * the matrix if one is overwriting a file, not an entire disk, because - * the procedure requires examination and comparison of the disk's defect - * lists. Any program that claims to securely erase *files* while - * conforming to the standard, then, is not correct. We do as much of - * what the standard requires as can actually be done when erasing a - * file, rather than an entire disk; but that does not make us conformant. - * - * Furthermore, the presence of track caches, disk and controller write - * caches, and so forth make it extremely difficult to ensure that data - * have actually been written to the disk, particularly when one tries - * to repeatedly overwrite the same sectors in quick succession. We call - * fsync(), but controllers with nonvolatile cache, as well as IDE disks - * that just plain lie about the stable storage of data, will defeat this. - * - * Finally, widely respected research suggests that the given procedure - * is nowhere near sufficient to prevent the recovery of data using special - * forensic equipment and techniques that are well-known. This is - * presumably one reason that the matrix requires physical media destruction, - * rather than any technique of the sort attempted here, for secret data. - * - * Caveat Emptor. - * - * rm_overwrite will return 0 on success. - */ - -static int -rm_overwrite(char *file, struct stat *sbp) -{ - struct stat sb, sb2; - int fd, randint; - char randchar; - - fd = -1; - if (sbp == NULL) { - if (lstat(file, &sb)) - goto err; - sbp = &sb; - } - if (!S_ISREG(sbp->st_mode)) - return 0; - - /* flags to try to defeat hidden caching by forcing seeks */ - if ((fd = open(file, O_RDWR|O_SYNC|O_RSYNC|O_NOFOLLOW, 0)) == -1) - goto err; - - if (fstat(fd, &sb2)) { - goto err; - } - - if (sb2.st_dev != sbp->st_dev || sb2.st_ino != sbp->st_ino || - !S_ISREG(sb2.st_mode)) { - errno = EPERM; - goto err; - } - -#define RAND_BYTES 1 -#define THIS_BYTE 0 - -#define WRITE_PASS(mode, byte) do { \ - off_t len; \ - size_t wlen, i; \ - char buf[8 * 1024]; \ - \ - if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET)) \ - goto err; \ - \ - if (mode == THIS_BYTE) \ - memset(buf, byte, sizeof(buf)); \ - for (len = sbp->st_size; len > 0; len -= wlen) { \ - if (mode == RAND_BYTES) { \ - for (i = 0; i < sizeof(buf); \ - i+= sizeof(u_int32_t)) \ - *(int *)(buf + i) = arc4random(); \ - } \ - wlen = len < (off_t)sizeof(buf) ? (size_t)len : sizeof(buf); \ - if ((size_t)write(fd, buf, wlen) != wlen) \ - goto err; \ - } \ - sync(); /* another poke at hidden caches */ \ -} while (/* CONSTCOND */ 0) - -#define READ_PASS(byte) do { \ - off_t len; \ - size_t rlen; \ - char pattern[8 * 1024]; \ - char buf[8 * 1024]; \ - \ - if (fsync(fd) || lseek(fd, (off_t)0, SEEK_SET)) \ - goto err; \ - \ - memset(pattern, byte, sizeof(pattern)); \ - for(len = sbp->st_size; len > 0; len -= rlen) { \ - rlen = len < (off_t)sizeof(buf) ? (size_t)len : sizeof(buf); \ - if((size_t)read(fd, buf, rlen) != rlen) \ - goto err; \ - if(memcmp(buf, pattern, rlen)) \ - goto err; \ - } \ - sync(); /* another poke at hidden caches */ \ -} while (/* CONSTCOND */ 0) - - /* - * DSS sanitization matrix "clear" for magnetic disks: - * option 'c' "Overwrite all addressable locations with a single - * character." - */ - randint = arc4random(); - randchar = *(char *)&randint; - WRITE_PASS(THIS_BYTE, randchar); - - /* - * DSS sanitization matrix "sanitize" for magnetic disks: - * option 'd', sub 2 "Overwrite all addressable locations with a - * character, then its complement. Verify "complement" character - * was written successfully to all addressable locations, then - * overwrite all addressable locations with random characters; or - * verify third overwrite of random characters." The rest of the - * text in d-sub-2 specifies requirements for overwriting spared - * sectors; we cannot conform to it when erasing only a file, thus - * we do not conform to the standard. - */ - - /* 1. "a character" */ - WRITE_PASS(THIS_BYTE, 0xff); - - /* 2. "its complement" */ - WRITE_PASS(THIS_BYTE, 0x00); - - /* 3. "Verify 'complement' character" */ - READ_PASS(0x00); - - /* 4. "overwrite all addressable locations with random characters" */ - - WRITE_PASS(RAND_BYTES, 0x00); - - /* - * As the file might be huge, and we note that this revision of - * the matrix says "random characters", not "a random character" - * as the original did, we do not verify the random-character - * write; the "or" in the standard allows this. - */ - - if (close(fd) == -1) { - fd = -1; - goto err; - } - - return 0; - -err: eval = 1; - warn("%s", file); - if (fd != -1) - close(fd); - return 1; -} - -static int -check(char *path, char *name, struct stat *sp) -{ - int ch, first; - char modep[15]; - - /* Check -i first. */ - if (iflag) - (void)fprintf(stderr, "remove '%s'? ", path); - else { - /* - * If it's not a symbolic link and it's unwritable and we're - * talking to a terminal, ask. Symbolic links are excluded - * because their permissions are meaningless. Check stdin_ok - * first because we may not have stat'ed the file. - */ - if (!stdin_ok || S_ISLNK(sp->st_mode) || - !(access(name, W_OK) && (errno != ETXTBSY))) - return (1); - strmode(sp->st_mode, modep); - if (Pflag) { - warnx( - "%s: -P was specified but file could not" - " be overwritten", path); - return 0; - } - (void)fprintf(stderr, "override %s%s%s:%s for '%s'? ", - modep + 1, modep[9] == ' ' ? "" : " ", - user_from_uid(sp->st_uid, 0), - group_from_gid(sp->st_gid, 0), path); - } - (void)fflush(stderr); - - first = ch = getchar(); - while (ch != '\n' && ch != EOF) - ch = getchar(); - return (first == 'y' || first == 'Y'); -} - -/* - * POSIX.2 requires that if "." or ".." are specified as the basename - * portion of an operand, a diagnostic message be written to standard - * error and nothing more be done with such operands. - * - * Since POSIX.2 defines basename as the final portion of a path after - * trailing slashes have been removed, we'll remove them here. - */ -#define ISDOT(a) ((a)[0] == '.' && (!(a)[1] || ((a)[1] == '.' && !(a)[2]))) -static void -checkdot(char **argv) -{ - char *p, **save, **t; - int complained; - - complained = 0; - for (t = argv; *t;) { - /* strip trailing slashes */ - p = strrchr(*t, '\0'); - while (--p > *t && *p == '/') - *p = '\0'; - - /* extract basename */ - if ((p = strrchr(*t, '/')) != NULL) - ++p; - else - p = *t; - - if (ISDOT(p)) { - if (!complained++) - warnx("\".\" and \"..\" may not be removed"); - eval = 1; - for (save = t; (t[0] = t[1]) != NULL; ++t) - continue; - t = save; - } else - ++t; - } -} - -static void -usage(void) -{ - - (void)fprintf(stderr, "usage: %s [-f|-i] [-dPRrvWx] file ...\n", - getprogname()); - exit(1); - /* NOTREACHED */ -} - -static void -progress(int sig __unused) -{ - - pinfo++; -} diff --git a/bin/rmdir/Makefile b/bin/rmdir/Makefile deleted file mode 100644 index 73dcabea2..000000000 --- a/bin/rmdir/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# $NetBSD: Makefile,v 1.8 1997/07/20 22:37:52 christos Exp $ -# @(#)Makefile 8.1 (Berkeley) 5/31/93 - -PROG= rmdir - -.include diff --git a/bin/rmdir/rmdir.1 b/bin/rmdir/rmdir.1 deleted file mode 100644 index 490828a68..000000000 --- a/bin/rmdir/rmdir.1 +++ /dev/null @@ -1,95 +0,0 @@ -.\" $NetBSD: rmdir.1,v 1.16 2016/08/12 02:30:37 sevan Exp $ -.\" -.\" Copyright (c) 1990, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Institute of Electrical and Electronics Engineers, Inc. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)rmdir.1 8.1 (Berkeley) 5/31/93 -.\" -.Dd August 12, 2016 -.Dt RMDIR 1 -.Os -.Sh NAME -.Nm rmdir -.Nd remove directories -.Sh SYNOPSIS -.Nm -.Op Fl p -.Ar directory ... -.Sh DESCRIPTION -The rmdir utility removes the directory entry specified by -each -.Ar directory -argument, provided it is empty. -.Pp -Arguments are processed in the order given. -In order to remove both a parent directory and a subdirectory -of that parent, the subdirectory -must be specified first so the parent directory -is empty when -.Nm -tries to remove it. -.Pp -The following option is available: -.Bl -tag -width Ds -.It Fl p -Each -.Ar directory -argument is treated as a pathname of which all -components will be removed, if they are empty, -starting with the last most component. -(See -.Xr rm 1 -for fully non-discriminant recursive removal.) -.El -.Sh EXIT STATUS -The -.Nm -utility exits with one of the following values: -.Bl -tag -width Ds -.It Li \&0 -Each directory entry specified by a dir operand -referred to an empty directory and was removed -successfully. -.It Li \&\*[Gt]\&0 -An error occurred. -.El -.Sh SEE ALSO -.Xr rm 1 -.Sh STANDARDS -The -.Nm -utility is expected to be -.St -p1003.2 -compatible. -.Sh HISTORY -An -.Nm -utility appeared in -.At v1 . diff --git a/bin/rmdir/rmdir.c b/bin/rmdir/rmdir.c deleted file mode 100644 index ab884b2dd..000000000 --- a/bin/rmdir/rmdir.c +++ /dev/null @@ -1,125 +0,0 @@ -/* $NetBSD: rmdir.c,v 1.26.36.1 2017/08/14 23:54:30 snj Exp $ */ - -/*- - * Copyright (c) 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1992, 1993, 1994\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)rmdir.c 8.3 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: rmdir.c,v 1.26.36.1 2017/08/14 23:54:30 snj Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include -#include -#include -#include -#include - -static int rm_path(char *); -__dead static void usage(void); - -int -main(int argc, char *argv[]) -{ - int ch, errors, pflag; - - setprogname(argv[0]); - (void)setlocale(LC_ALL, ""); - - pflag = 0; - while ((ch = getopt(argc, argv, "p")) != -1) - switch(ch) { - case 'p': - pflag = 1; - break; - case '?': - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc == 0) - usage(); - - for (errors = 0; *argv; argv++) { - /* We rely on the kernel to ignore trailing '/' characters. */ - if (rmdir(*argv) < 0) { - warn("%s", *argv); - errors = 1; - } else if (pflag) - errors |= rm_path(*argv); - } - - exit(errors); - /* NOTREACHED */ -} - -static int -rm_path(char *path) -{ - char *p; - - while ((p = strrchr(path, '/')) != NULL) { - *p = 0; - if (p[1] == 0) - /* Ignore trailing '/' on deleted name */ - continue; - - if (*path == 0) - /* At top level (root) directory */ - break; - - if (rmdir(path) < 0) { - warn("%s", path); - return (1); - } - } - - return (0); -} - -static void -usage(void) -{ - (void)fprintf(stderr, "usage: %s [-p] directory ...\n", getprogname()); - exit(1); - /* NOTREACHED */ -} diff --git a/bin/sh/Makefile b/bin/sh/Makefile deleted file mode 100644 index e4470d3a3..000000000 --- a/bin/sh/Makefile +++ /dev/null @@ -1,91 +0,0 @@ -# $NetBSD: Makefile,v 1.101 2015/05/10 20:30:54 joerg Exp $ -# @(#)Makefile 8.4 (Berkeley) 5/5/95 - -.include - -YHEADER=1 -PROG= sh -SHSRCS= alias.c cd.c echo.c error.c eval.c exec.c expand.c \ - histedit.c input.c jobs.c mail.c main.c memalloc.c miscbltin.c \ - mystring.c options.c parser.c redir.c show.c trap.c output.c var.c \ - test.c kill.c syntax.c -GENSRCS=arith.c arith_lex.c builtins.c init.c nodes.c -GENHDRS=arith.h builtins.h nodes.h token.h -SRCS= ${SHSRCS} ${GENSRCS} - -DPSRCS+=${GENHDRS} - -LDADD+= -ll -ledit -lterminfo -DPADD+= ${LIBL} ${LIBEDIT} ${LIBTERMINFO} - -LFLAGS= -8 # 8-bit lex scanner for arithmetic - -# Environment for scripts executed during build. -SCRIPT_ENV= \ - AWK=${TOOL_AWK:Q} \ - SED=${TOOL_SED:Q} - -# The .depend file can get references to these temporary files -.OPTIONAL: lex.yy.c y.tab.c - -.ifdef CRUNCHEDPROG -LFLAGS+=-L -YFLAGS+=-l -.endif - -CPPFLAGS+=-DSHELL -I. -I${.CURDIR} -#XXX: For testing only. -#CPPFLAGS+=-DDEBUG=2 -#COPTS+=-g -#CFLAGS+=-funsigned-char -#TARGET_CHARFLAG?= -DTARGET_CHAR="unsigned char" -funsigned-char - -.ifdef SMALLPROG -CPPFLAGS+=-DSMALL -.endif -.ifdef TINYPROG -CPPFLAGS+=-DTINY -.else -SRCS+=printf.c -.endif - -.PATH: ${.CURDIR}/bltin ${NETBSDSRCDIR}/bin/test \ - ${NETBSDSRCDIR}/usr.bin/printf \ - ${NETBSDSRCDIR}/bin/kill - -CLEANFILES+= ${GENSRCS} ${GENHDRS} y.tab.h -CLEANFILES+= trace - -token.h: mktokens - ${_MKTARGET_CREATE} - ${SCRIPT_ENV} ${HOST_SH} ${.ALLSRC} - -.ORDER: builtins.h builtins.c -builtins.h builtins.c: mkbuiltins shell.h builtins.def - ${_MKTARGET_CREATE} - ${SCRIPT_ENV} ${HOST_SH} ${.ALLSRC} ${.OBJDIR} - [ -f builtins.h ] - -init.c: mkinit.sh ${SHSRCS} - ${_MKTARGET_CREATE} - ${SCRIPT_ENV} ${HOST_SH} ${.ALLSRC} - -.ORDER: nodes.h nodes.c -nodes.c nodes.h: mknodes.sh nodetypes nodes.c.pat - ${_MKTARGET_CREATE} - ${SCRIPT_ENV} ${HOST_SH} ${.ALLSRC} ${.OBJDIR} - [ -f nodes.h ] - -.if ${USETOOLS} == "yes" -NBCOMPATLIB= -L${TOOLDIR}/lib -lnbcompat -.endif - -.if !defined(__MINIX) -SUBDIR+=USD.doc -.endif # !defined(__MINIX) - -COPTS.printf.c = -Wno-format-nonliteral -COPTS.jobs.c = -Wno-format-nonliteral - -.include -.include diff --git a/bin/sh/TOUR b/bin/sh/TOUR deleted file mode 100644 index 681f9866d..000000000 --- a/bin/sh/TOUR +++ /dev/null @@ -1,357 +0,0 @@ -# $NetBSD: TOUR,v 1.10 2008/11/15 17:01:38 snj Exp $ -# @(#)TOUR 8.1 (Berkeley) 5/31/93 - -NOTE -- This is the original TOUR paper distributed with ash and -does not represent the current state of the shell. It is provided anyway -since it provides helpful information for how the shell is structured, -but be warned that things have changed -- the current shell is -still under development. - -================================================================ - - A Tour through Ash - - Copyright 1989 by Kenneth Almquist. - - -DIRECTORIES: The subdirectory bltin contains commands which can -be compiled stand-alone. The rest of the source is in the main -ash directory. - -SOURCE CODE GENERATORS: Files whose names begin with "mk" are -programs that generate source code. A complete list of these -programs is: - - program input files generates - ------- ------------ --------- - mkbuiltins builtins builtins.h builtins.c - mkinit *.c init.c - mknodes nodetypes nodes.h nodes.c - mksignames - signames.h signames.c - mksyntax - syntax.h syntax.c - mktokens - token.h - bltin/mkexpr unary_op binary_op operators.h operators.c - -There are undoubtedly too many of these. Mkinit searches all the -C source files for entries looking like: - - INIT { - x = 1; /* executed during initialization */ - } - - RESET { - x = 2; /* executed when the shell does a longjmp - back to the main command loop */ - } - - SHELLPROC { - x = 3; /* executed when the shell runs a shell procedure */ - } - -It pulls this code out into routines which are when particular -events occur. The intent is to improve modularity by isolating -the information about which modules need to be explicitly -initialized/reset within the modules themselves. - -Mkinit recognizes several constructs for placing declarations in -the init.c file. - INCLUDE "file.h" -includes a file. The storage class MKINIT makes a declaration -available in the init.c file, for example: - MKINIT int funcnest; /* depth of function calls */ -MKINIT alone on a line introduces a structure or union declara- -tion: - MKINIT - struct redirtab { - short renamed[10]; - }; -Preprocessor #define statements are copied to init.c without any -special action to request this. - -INDENTATION: The ash source is indented in multiples of six -spaces. The only study that I have heard of on the subject con- -cluded that the optimal amount to indent is in the range of four -to six spaces. I use six spaces since it is not too big a jump -from the widely used eight spaces. If you really hate six space -indentation, use the adjind (source included) program to change -it to something else. - -EXCEPTIONS: Code for dealing with exceptions appears in -exceptions.c. The C language doesn't include exception handling, -so I implement it using setjmp and longjmp. The global variable -exception contains the type of exception. EXERROR is raised by -calling error. EXINT is an interrupt. EXSHELLPROC is an excep- -tion which is raised when a shell procedure is invoked. The pur- -pose of EXSHELLPROC is to perform the cleanup actions associated -with other exceptions. After these cleanup actions, the shell -can interpret a shell procedure itself without exec'ing a new -copy of the shell. - -INTERRUPTS: In an interactive shell, an interrupt will cause an -EXINT exception to return to the main command loop. (Exception: -EXINT is not raised if the user traps interrupts using the trap -command.) The INTOFF and INTON macros (defined in exception.h) -provide uninterruptible critical sections. Between the execution -of INTOFF and the execution of INTON, interrupt signals will be -held for later delivery. INTOFF and INTON can be nested. - -MEMALLOC.C: Memalloc.c defines versions of malloc and realloc -which call error when there is no memory left. It also defines a -stack oriented memory allocation scheme. Allocating off a stack -is probably more efficient than allocation using malloc, but the -big advantage is that when an exception occurs all we have to do -to free up the memory in use at the time of the exception is to -restore the stack pointer. The stack is implemented using a -linked list of blocks. - -STPUTC: If the stack were contiguous, it would be easy to store -strings on the stack without knowing in advance how long the -string was going to be: - p = stackptr; - *p++ = c; /* repeated as many times as needed */ - stackptr = p; -The following three macros (defined in memalloc.h) perform these -operations, but grow the stack if you run off the end: - STARTSTACKSTR(p); - STPUTC(c, p); /* repeated as many times as needed */ - grabstackstr(p); - -We now start a top-down look at the code: - -MAIN.C: The main routine performs some initialization, executes -the user's profile if necessary, and calls cmdloop. Cmdloop is -repeatedly parses and executes commands. - -OPTIONS.C: This file contains the option processing code. It is -called from main to parse the shell arguments when the shell is -invoked, and it also contains the set builtin. The -i and -j op- -tions (the latter turns on job control) require changes in signal -handling. The routines setjobctl (in jobs.c) and setinteractive -(in trap.c) are called to handle changes to these options. - -PARSING: The parser code is all in parser.c. A recursive des- -cent parser is used. Syntax tables (generated by mksyntax) are -used to classify characters during lexical analysis. There are -three tables: one for normal use, one for use when inside single -quotes, and one for use when inside double quotes. The tables -are machine dependent because they are indexed by character vari- -ables and the range of a char varies from machine to machine. - -PARSE OUTPUT: The output of the parser consists of a tree of -nodes. The various types of nodes are defined in the file node- -types. - -Nodes of type NARG are used to represent both words and the con- -tents of here documents. An early version of ash kept the con- -tents of here documents in temporary files, but keeping here do- -cuments in memory typically results in significantly better per- -formance. It would have been nice to make it an option to use -temporary files for here documents, for the benefit of small -machines, but the code to keep track of when to delete the tem- -porary files was complex and I never fixed all the bugs in it. -(AT&T has been maintaining the Bourne shell for more than ten -years, and to the best of my knowledge they still haven't gotten -it to handle temporary files correctly in obscure cases.) - -The text field of a NARG structure points to the text of the -word. The text consists of ordinary characters and a number of -special codes defined in parser.h. The special codes are: - - CTLVAR Variable substitution - CTLENDVAR End of variable substitution - CTLBACKQ Command substitution - CTLBACKQ|CTLQUOTE Command substitution inside double quotes - CTLESC Escape next character - -A variable substitution contains the following elements: - - CTLVAR type name '=' [ alternative-text CTLENDVAR ] - -The type field is a single character specifying the type of sub- -stitution. The possible types are: - - VSNORMAL $var - VSMINUS ${var-text} - VSMINUS|VSNUL ${var:-text} - VSPLUS ${var+text} - VSPLUS|VSNUL ${var:+text} - VSQUESTION ${var?text} - VSQUESTION|VSNUL ${var:?text} - VSASSIGN ${var=text} - VSASSIGN|VSNUL ${var=text} - -In addition, the type field will have the VSQUOTE flag set if the -variable is enclosed in double quotes. The name of the variable -comes next, terminated by an equals sign. If the type is not -VSNORMAL, then the text field in the substitution follows, ter- -minated by a CTLENDVAR byte. - -Commands in back quotes are parsed and stored in a linked list. -The locations of these commands in the string are indicated by -CTLBACKQ and CTLBACKQ+CTLQUOTE characters, depending upon whether -the back quotes were enclosed in double quotes. - -The character CTLESC escapes the next character, so that in case -any of the CTL characters mentioned above appear in the input, -they can be passed through transparently. CTLESC is also used to -escape '*', '?', '[', and '!' characters which were quoted by the -user and thus should not be used for file name generation. - -CTLESC characters have proved to be particularly tricky to get -right. In the case of here documents which are not subject to -variable and command substitution, the parser doesn't insert any -CTLESC characters to begin with (so the contents of the text -field can be written without any processing). Other here docu- -ments, and words which are not subject to splitting and file name -generation, have the CTLESC characters removed during the vari- -able and command substitution phase. Words which are subject -splitting and file name generation have the CTLESC characters re- -moved as part of the file name phase. - -EXECUTION: Command execution is handled by the following files: - eval.c The top level routines. - redir.c Code to handle redirection of input and output. - jobs.c Code to handle forking, waiting, and job control. - exec.c Code to to path searches and the actual exec sys call. - expand.c Code to evaluate arguments. - var.c Maintains the variable symbol table. Called from expand.c. - -EVAL.C: Evaltree recursively executes a parse tree. The exit -status is returned in the global variable exitstatus. The alter- -native entry evalbackcmd is called to evaluate commands in back -quotes. It saves the result in memory if the command is a buil- -tin; otherwise it forks off a child to execute the command and -connects the standard output of the child to a pipe. - -JOBS.C: To create a process, you call makejob to return a job -structure, and then call forkshell (passing the job structure as -an argument) to create the process. Waitforjob waits for a job -to complete. These routines take care of process groups if job -control is defined. - -REDIR.C: Ash allows file descriptors to be redirected and then -restored without forking off a child process. This is accom- -plished by duplicating the original file descriptors. The redir- -tab structure records where the file descriptors have been dupli- -cated to. - -EXEC.C: The routine find_command locates a command, and enters -the command in the hash table if it is not already there. The -third argument specifies whether it is to print an error message -if the command is not found. (When a pipeline is set up, -find_command is called for all the commands in the pipeline be- -fore any forking is done, so to get the commands into the hash -table of the parent process. But to make command hashing as -transparent as possible, we silently ignore errors at that point -and only print error messages if the command cannot be found -later.) - -The routine shellexec is the interface to the exec system call. - -EXPAND.C: Arguments are processed in three passes. The first -(performed by the routine argstr) performs variable and command -substitution. The second (ifsbreakup) performs word splitting -and the third (expandmeta) performs file name generation. If the -"/u" directory is simulated, then when "/u/username" is replaced -by the user's home directory, the flag "didudir" is set. This -tells the cd command that it should print out the directory name, -just as it would if the "/u" directory were implemented using -symbolic links. - -VAR.C: Variables are stored in a hash table. Probably we should -switch to extensible hashing. The variable name is stored in the -same string as the value (using the format "name=value") so that -no string copying is needed to create the environment of a com- -mand. Variables which the shell references internally are preal- -located so that the shell can reference the values of these vari- -ables without doing a lookup. - -When a program is run, the code in eval.c sticks any environment -variables which precede the command (as in "PATH=xxx command") in -the variable table as the simplest way to strip duplicates, and -then calls "environment" to get the value of the environment. -There are two consequences of this. First, if an assignment to -PATH precedes the command, the value of PATH before the assign- -ment must be remembered and passed to shellexec. Second, if the -program turns out to be a shell procedure, the strings from the -environment variables which preceded the command must be pulled -out of the table and replaced with strings obtained from malloc, -since the former will automatically be freed when the stack (see -the entry on memalloc.c) is emptied. - -BUILTIN COMMANDS: The procedures for handling these are scat- -tered throughout the code, depending on which location appears -most appropriate. They can be recognized because their names al- -ways end in "cmd". The mapping from names to procedures is -specified in the file builtins, which is processed by the mkbuil- -tins command. - -A builtin command is invoked with argc and argv set up like a -normal program. A builtin command is allowed to overwrite its -arguments. Builtin routines can call nextopt to do option pars- -ing. This is kind of like getopt, but you don't pass argc and -argv to it. Builtin routines can also call error. This routine -normally terminates the shell (or returns to the main command -loop if the shell is interactive), but when called from a builtin -command it causes the builtin command to terminate with an exit -status of 2. - -The directory bltins contains commands which can be compiled in- -dependently but can also be built into the shell for efficiency -reasons. The makefile in this directory compiles these programs -in the normal fashion (so that they can be run regardless of -whether the invoker is ash), but also creates a library named -bltinlib.a which can be linked with ash. The header file bltin.h -takes care of most of the differences between the ash and the -stand-alone environment. The user should call the main routine -"main", and #define main to be the name of the routine to use -when the program is linked into ash. This #define should appear -before bltin.h is included; bltin.h will #undef main if the pro- -gram is to be compiled stand-alone. - -CD.C: This file defines the cd and pwd builtins. The pwd com- -mand runs /bin/pwd the first time it is invoked (unless the user -has already done a cd to an absolute pathname), but then -remembers the current directory and updates it when the cd com- -mand is run, so subsequent pwd commands run very fast. The main -complication in the cd command is in the docd command, which -resolves symbolic links into actual names and informs the user -where the user ended up if he crossed a symbolic link. - -SIGNALS: Trap.c implements the trap command. The routine set- -signal figures out what action should be taken when a signal is -received and invokes the signal system call to set the signal ac- -tion appropriately. When a signal that a user has set a trap for -is caught, the routine "onsig" sets a flag. The routine dotrap -is called at appropriate points to actually handle the signal. -When an interrupt is caught and no trap has been set for that -signal, the routine "onint" in error.c is called. - -OUTPUT: Ash uses its own output routines. There are three out- -put structures allocated. "Output" represents the standard out- -put, "errout" the standard error, and "memout" contains output -which is to be stored in memory. This last is used when a buil- -tin command appears in backquotes, to allow its output to be col- -lected without doing any I/O through the UNIX operating system. -The variables out1 and out2 normally point to output and errout, -respectively, but they are set to point to memout when appropri- -ate inside backquotes. - -INPUT: The basic input routine is pgetc, which reads from the -current input file. There is a stack of input files; the current -input file is the top file on this stack. The code allows the -input to come from a string rather than a file. (This is for the --c option and the "." and eval builtin commands.) The global -variable plinno is saved and restored when files are pushed and -popped from the stack. The parser routines store the number of -the current line in this variable. - -DEBUGGING: If DEBUG is defined in shell.h, then the shell will -write debugging information to the file $HOME/trace. Most of -this is done using the TRACE macro, which takes a set of printf -arguments inside two sets of parenthesis. Example: -"TRACE(("n=%d0, n))". The double parenthesis are necessary be- -cause the preprocessor can't handle functions with a variable -number of arguments. Defining DEBUG also causes the shell to -generate a core dump if it is sent a quit signal. The tracing -code is in show.c. diff --git a/bin/sh/USD.doc/Makefile b/bin/sh/USD.doc/Makefile deleted file mode 100644 index 55b7203f0..000000000 --- a/bin/sh/USD.doc/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# $NetBSD: Makefile,v 1.4 2014/07/05 19:23:00 dholland Exp $ -# @(#)Makefile 8.1 (Berkeley) 8/14/93 - -SECTION=reference/ref1 -ARTICLE=sh -SRCS= referargs t.mac t1 t2 t3 t4 -MACROS=-ms -ROFF_REFER=yes -#REFER_ARGS=-e -p Rv7man -EXTRAHTMLFILES=sh1.png sh2.png sh3.png sh4.png sh5.png - -.include diff --git a/bin/sh/USD.doc/referargs b/bin/sh/USD.doc/referargs deleted file mode 100644 index 3bb6284e0..000000000 --- a/bin/sh/USD.doc/referargs +++ /dev/null @@ -1,8 +0,0 @@ -.\" $NetBSD: referargs,v 1.1 2014/07/05 19:22:02 dholland Exp $ -.\" -.\" Arguments for refer; these were previously passed on the refer(1) -.\" command line: -e -p Rv7man -.R1 -accumulate -database Rv7man -.R2 diff --git a/bin/sh/USD.doc/t.mac b/bin/sh/USD.doc/t.mac deleted file mode 100644 index 9bf65c8fe..000000000 --- a/bin/sh/USD.doc/t.mac +++ /dev/null @@ -1,69 +0,0 @@ -.\" $NetBSD: t.mac,v 1.2 2010/08/22 02:19:07 perry Exp $ -.\" -.\" Copyright (C) Caldera International Inc. 2001-2002. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions are -.\" met: -.\" -.\" Redistributions of source code and documentation must retain the above -.\" copyright notice, this list of conditions and the following -.\" disclaimer. -.\" -.\" Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" -.\" This product includes software developed or owned by Caldera -.\" International, Inc. Neither the name of Caldera International, Inc. -.\" nor the names of other contributors may be used to endorse or promote -.\" products derived from this software without specific prior written -.\" permission. -.\" -.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA -.\" INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -.\" DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE -.\" FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -.\" OR OTHERWISE) RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" @(#)t.mac 8.1 (Berkeley) 8/14/93 -.\" -.ds ZZ \fB.\|.\|.\fP -.ds ST \v'.3m'\s+2*\s0\v'-.3m' -.ds DO \h'\w'do 'u' -.ds Ca \h'\w'case 'u' -.ds WH \h'\w'while 'u' -.ds VT \|\fB\(or\fP\| -.ds TH \h'\w'then 'u' -.ds DC \*(DO\*(Ca -.ds AP >\h'-.2m'> -.ds HE <\h'-.2m'< -. \" macros for algol 68c reference manual -.ds DA 1977 November 1 -.ds md \v'.25m' -.ds mu \v'-.25m' -.ds U \*(mu\s-3 -.ds V \s0\*(md -.ds L \*(md\s-3 -.ds M \s0\*(mu -.ds S \s-1 -.ds T \s0 -. \" small 1 -.ds O \*S1\*T -.ds h \| -.ds s \|\| -. \" ellipsis -.ds e .\|.\|. -. \" subscripts -.ds 1 \*(md\s-41\s0\*(mu -.ds 2 \*(md\s-42\s0\*(mu diff --git a/bin/sh/USD.doc/t1 b/bin/sh/USD.doc/t1 deleted file mode 100644 index 075511fe8..000000000 --- a/bin/sh/USD.doc/t1 +++ /dev/null @@ -1,553 +0,0 @@ -.\" $NetBSD: t1,v 1.3 2010/08/22 02:19:07 perry Exp $ -.\" -.\" Copyright (C) Caldera International Inc. 2001-2002. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions are -.\" met: -.\" -.\" Redistributions of source code and documentation must retain the above -.\" copyright notice, this list of conditions and the following -.\" disclaimer. -.\" -.\" Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" All advertising materials mentioning features or use of this software -.\" must display the following acknowledgment: -.\" -.\" This product includes software developed or owned by Caldera -.\" International, Inc. Neither the name of Caldera International, Inc. -.\" nor the names of other contributors may be used to endorse or promote -.\" products derived from this software without specific prior written -.\" permission. -.\" -.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA -.\" INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -.\" DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE -.\" FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -.\" OR OTHERWISE) RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" @(#)t1 8.1 (Berkeley) 8/14/93 -.\" -.EH 'USD:3-%''An Introduction to the UNIX Shell' -.OH 'An Introduction to the UNIX Shell''USD:3-%' -.\".RP -.TL -An Introduction to the UNIX Shell -.AU -S. R. Bourne -.AI -Murray Hill, NJ -.AU -(Updated for 4.3BSD by Mark Seiden) -.AU -(Further updated by Perry E. Metzger)\(dg -.AB -.FS -\(dg This paper was updated in 2010 to reflect most features of modern -POSIX shells, which all follow the design of S.R. Bourne's original v7 -Unix shell. -Among these are ash, bash, ksh and others. -Typically one of these will be installed as /bin/sh on a modern system. -It does not describe the behavior of the c shell (csh). -If it's the c shell (csh) you're interested in, a good place to -begin is William Joy's paper "An Introduction to the C shell" (USD:4). -.FE -.LP -The -.ul -shell -is a command programming language that provides an interface -to the -.UX -operating system. -Its features include -control-flow primitives, parameter passing, variables and -string substitution. -Constructs such as -.ul -while, if then else, case -and -.ul -for -are available. -Two-way communication is possible between the -.ul -shell -and commands. -String-valued parameters, typically file names or flags, may be -passed to a command. -A return code is set by commands that may be used to determine control-flow, -and the standard output from a command may be used -as shell input. -.LP -The -.ul -shell -can modify the environment -in which commands run. -Input and output can be redirected -to files, and processes that communicate through `pipes' -can be invoked. -Commands are found by -searching directories -in the file system in a -sequence that can be defined by the user. -Commands can be read either from the terminal or from a file, -which allows command procedures to be -stored for later use. -.AE -.ds ST \v'.3m'\s+2*\s0\v'-.3m' -.SH -1.0\ Introduction -.LP -The shell is both a command language -and a programming language -that provides an interface to the UNIX -operating system. -This memorandum describes, with -examples, the UNIX shell. -The first section covers most of the -everyday requirements -of terminal users. -Some familiarity with UNIX -is an advantage when reading this section; -see, for example, -"UNIX for beginners". -.[ -unix beginn kernigh 1978 -.] -Section 2 describes those features -of the shell primarily intended -for use within shell procedures. -These include the control-flow -primitives and string-valued variables -provided by the shell. -A knowledge of a programming language -would be a help when reading this section. -The last section describes the more -advanced features of the shell. -References of the form "see \fIpipe\fP (2)" -are to a section of the UNIX manual. -.[ -seventh 1978 ritchie thompson -.] -.SH -1.1\ Simple\ commands -.LP -Simple commands consist of one or more words -separated by blanks. -The first word is the name of the command -to be executed; any remaining words -are passed as arguments to the command. -For example, -.DS - who -.DE -is a command that prints the names -of users logged in. -The command -.DS - ls \(mil -.DE -prints a list of files in the current -directory. -The argument \fI\(mil\fP tells \fIls\fP -to print status information, size and -the creation date for each file. -.SH -1.2\ Input\ output\ redirection -.LP -Most commands produce output on the standard output -that is initially connected to the terminal. -This output may be sent to a file -by writing, for example, -.DS - ls \(mil >file -.DE -The notation \fI>file\fP -is interpreted by the shell and is not passed -as an argument to \fIls.\fP -If \fIfile\fP does not exist then the -shell creates it; -otherwise the original contents of -\fIfile\fP are replaced with the output -from \fIls.\fP -Output may be appended to a file -using the notation -.DS - ls \(mil \*(APfile -.DE -In this case \fIfile\fP is also created if it does not already -exist. -.LP -The standard input of a command may be taken -from a file instead of the terminal by -writing, for example, -.DS - wc \|. -.\" For example -.\" .DS -.\" command some args >out 2>errors -.\" .DE -.\" will redirect standard output to the file `out' but standard error -.\" (and thus all error messages) to `errors'. -.\" The notation 2>&1 sets standard error pointing to the same -.\" place as standard out. -.\" Thus: -.\" .DS -.\" command some args 2>&1 >everything -.\" .DE -.\" will put both standard out and standard error into the file `everything'. -.\" See section 3.7 below for more details. -.SH -1.3\ Pipelines\ and\ filters -.LP -The standard output of one command may be -connected to the standard input of another -by writing -the `pipe' operator, -indicated by \*(VT, -as in, -.DS - ls \(mil \*(VT wc -.DE -Two commands connected in this way constitute -a \fIpipeline\fP and -the overall effect is the same as -.DS - ls \(mil >file; wc \*(ST ? \*(VT &\|,\fR -are called metacharacters. -A complete list of metacharacters is given -in appendix B. -Any character preceded by a \fB\\\fR is \fIquoted\fP -and loses its special meaning, if any. -The \fB\\\fP is elided so that -.DS - echo \\? -.DE -will echo a single \fB?\|,\fP -and -.DS - echo \\\\ -.DE -will echo a single \fB\\\|.\fR -To allow long strings to be continued over -more than one line -the sequence \fB\\newline\fP -is ignored. -.LP -\fB\\\fP is convenient for quoting -single characters. -When more than one character needs -quoting the above mechanism is clumsy and -error prone. -A string of characters may be quoted -by enclosing the string between single quotes. -For example, -.DS - echo xx\'\*(ST\*(ST\*(ST\*(ST\'xx -.DE -will echo -.DS - xx\*(ST\*(ST\*(ST\*(STxx -.DE -The quoted string may not contain -a single quote -but may contain newlines, which are preserved. -This quoting mechanism is the most -simple and is recommended -for casual use. -.LP -A third quoting mechanism using double quotes -is also available -that prevents interpretation of some but not all -metacharacters. -Discussion of the -details is deferred -to section 3.5\|. -.SH -1.7\ Prompting -.LP -When the shell is used from a terminal it will -issue a prompt before reading a command. -By default this prompt is `\fB$\ \fR'\|. -It may be changed by saying, -for example, -.DS - \s-1PS1\s0="yesdear$ " -.DE -that sets the prompt to be the string \fIyesdear$\|.\fP -If a newline is typed and further input is needed -then the shell will issue the prompt `\fB>\ \fR'\|. -Sometimes this can be caused by mistyping -a quote mark. -If it is unexpected then entering the interrupt character -(typically \s-1CONTROL-C\s0) -will return the shell to read another command. -This prompt may be changed by saying, for example, -.DS - \s-1PS2\s0=more -.DE -Entering the interrupt character may also be used to terminate most -programs running as the current foreground job. -.LP -(\s-1PS1\s0 and \s-1PS2\s0 are \fIshell variables\fP, which will be -described in section 2.4 below.) -.SH -1.8\ The\ shell\ and\ login -.LP -Following \fIlogin\fP(1) -the shell is called to read and execute -commands typed at the terminal. -If the user's login directory -contains the file \fB.profile\fP -then it is assumed to contain commands -and is read by the shell before reading -any commands from the terminal. -.LP -(Most versions of the shell also specify a file that is read and -executed on start-up whether or not the shell is invoked by login. -The \s-1ENV\s0 shell variable, described in section 2.4 below, can be -used to override the name of this file. -See the shell manual page for further information.) -.SH -1.9\ Summary -.sp -.RS -.IP \(bu -\fBls\fP -.br -Print the names of files in the current directory. -.IP \(bu -\fBls >file\fP -.br -Put the output from \fIls\fP into \fIfile.\fP -.IP \(bu -\fBls \*(VT wc \(mil\fR -.br -Print the number of files in the current directory. -.IP \(bu -\fBls \*(VT grep old\fR -.br -Print those file names containing the string \fIold.\fP -.IP \(bu -\fBls \*(VT grep old \*(VT wc \(mil\fR -.br -Print the number of files whose name contains the string \fIold.\fP -.IP \(bu -\fBcc pgm.c &\fR -.br -Run \fIcc\fP in the background. -.RE diff --git a/bin/sh/USD.doc/t2 b/bin/sh/USD.doc/t2 deleted file mode 100644 index d49747e90..000000000 --- a/bin/sh/USD.doc/t2 +++ /dev/null @@ -1,971 +0,0 @@ -.\" $NetBSD: t2,v 1.3 2010/08/22 02:19:07 perry Exp $ -.\" -.\" Copyright (C) Caldera International Inc. 2001-2002. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions are -.\" met: -.\" -.\" Redistributions of source code and documentation must retain the above -.\" copyright notice, this list of conditions and the following -.\" disclaimer. -.\" -.\" Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" All advertising materials mentioning features or use of this software -.\" must display the following acknowledgment: -.\" -.\" This product includes software developed or owned by Caldera -.\" International, Inc. Neither the name of Caldera International, Inc. -.\" nor the names of other contributors may be used to endorse or promote -.\" products derived from this software without specific prior written -.\" permission. -.\" -.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA -.\" INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -.\" DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE -.\" FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -.\" OR OTHERWISE) RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" @(#)t2 8.1 (Berkeley) 6/8/93 -.\" -.SH -2.0\ Shell\ scripts -.LP -The shell may be used to read and execute commands -contained in a file. -For example, -.DS - sh file [ args \*(ZZ ] -.DE -calls the shell to read commands from \fIfile.\fP -Such a file is called a \fIshell script.\fP -Arguments may be supplied with the call -and are referred to in \fIfile\fP -using the positional parameters -\fB$1, $2, \*(ZZ\|.\fR -.LP -For example, if the file \fIwg\fP contains -.DS - who \*(VT grep $1 -.DE -then -.DS - sh wg fred -.DE -is equivalent to -.DS - who \*(VT grep fred -.DE -.LP -UNIX files have three independent attributes, -\fIread,\fP \fIwrite\fP and \fIexecute.\fP -The UNIX command \fIchmod\fP(1) may be used -to make a file executable. -For example, -.DS - chmod +x wg -.DE -will ensure that the file \fIwg\fP has execute status. -Following this, the command -.DS - wg fred -.DE -is equivalent to -.DS - sh wg fred -.DE -This allows shell scripts and other programs -to be used interchangeably. -In either case a new process is created to -run the command. -.LP -The `\fB#\fP' character is used as a comment character by the shell. -All characters following the `#' on a line are ignored. -.LP -A typical modern system has several different shells, some with differing -command syntax, and it is desirable to specify which one should be -invoked when an executable script is invoked. -If the special comment -.DS - #!/\fIpath\fP/\fIto\fP/\fIinterpreter\fP -.DE -appears as the first line in a script, it is used to specify the -absolute pathname of the shell (or other interpreter) that should be -used to execute the file. -(Without such a line, \fB/bin/sh\fP is assumed.) -It is best if a script explicitly states -what shell it is intended for in this manner. -.LP -As well as providing names for the positional -parameters, -the number of positional parameters to a script -is available as \fB$#\|.\fP -The name of the file being executed -is available as \fB$0\|.\fP -.LP -A special shell parameter \fB$\*(ST\fP -is used to substitute for all positional parameters -except \fB$0\|.\fP -A typical use of this is to provide -some default arguments, -as in, -.DS - nroff \(miT450 \(mims $\*(ST -.DE -which simply prepends some arguments -to those already given. -(The variable \fB$@\fP also expands to ``all positional -parameters'', but is subtly different when expanded inside quotes. -See section 3.5, below.) -.SH -2.1\ Control\ flow\ -\ for -.LP -A frequent use of shell scripts is to loop -through the arguments (\fB$1, $2, \*(ZZ\fR) -executing commands once for each argument. -An example of such a script is -\fItel\fP that searches the file -\fB/usr/share/telnos\fR -that contains lines of the form -.DS - \*(ZZ - fred mh0123 - bert mh0789 - \*(ZZ -.DE -The text of \fItel\fP is -.DS - #!/bin/sh - - for i - do - grep $i /usr/share/telnos - done -.DE -The command -.DS - tel fred -.DE -prints those lines in \fB/usr/share/telnos\fR -that contain the string \fIfred\|.\fP -.DS - tel fred bert -.DE -prints those lines containing \fIfred\fP -followed by those for \fIbert.\fP -.LP -The \fBfor\fP loop notation is recognized by the shell -and has the general form -.DS - \fBfor\fR \fIname\fR \fBin\fR \fIw1 w2 \*(ZZ\fR - \fBdo\fR \fIcommand-list\fR - \fBdone\fR -.DE -A \fIcommand-list\fP is a sequence of one or more -simple commands separated or terminated by a newline or semicolon. -Furthermore, reserved words -like \fBdo\fP and \fBdone\fP are only -recognized following a newline or -semicolon. -\fIname\fP is a shell variable that is set -to the words \fIw1 w2 \*(ZZ\fR in turn each time the \fIcommand-list\fP -following \fBdo\fP -is executed. -If \fBin\fR \fIw1 w2 \*(ZZ\fR -is omitted then the loop -is executed once for each positional parameter; -that is, \fBin\fR \fI$\*(ST\fR is assumed. -.LP -Another example of the use of the \fBfor\fP -loop is the \fIcreate\fP command -whose text is -.DS - for i do >$i; done -.DE -The command -.DS - create alpha beta -.DE -ensures that two empty files -\fIalpha\fP and \fIbeta\fP exist -and are empty. -The notation \fI>file\fP may be used on its -own to create or clear the contents of a file. -Notice also that a semicolon (or newline) is required before \fBdone.\fP -.SH -2.2\ Control\ flow\ -\ case -.LP -A multiple way branch is provided for by the -\fBcase\fP notation. -For example, -.DS - case $# in - \*(Ca1) cat \*(AP$1 ;; - \*(Ca2) cat \*(AP$2 <$1 ;; - \*(Ca\*(ST) echo \'usage: append [ from ] to\' ;; - esac -.DE -is an \fIappend\fP command. -When called -with one argument as -.DS - append file -.DE -\fB$#\fP is the string \fI1\fP and -the standard input is copied onto the -end of \fIfile\fP -using the \fIcat\fP command. -.DS - append file1 file2 -.DE -appends the contents of \fIfile1\fP -onto \fIfile2.\fP -If the number of arguments supplied to -\fIappend\fP is other than 1 or 2 -then a message is printed indicating -proper usage. -.LP -The general form of the \fBcase\fP command -is -.DS - \fBcase \fIword \fBin - \*(Ca\fIpattern\|\fB)\ \fIcommand-list\fB\|;; - \*(Ca\*(ZZ - \fBesac\fR -.DE -The shell attempts to match -\fIword\fR with each \fIpattern,\fR -in the order in which the patterns -appear. -If a match is found the -associated \fIcommand-list\fP is -executed and execution -of the \fBcase\fP is complete. -Since \*(ST is the pattern that matches any -string it can be used for the default case. -.LP -A word of caution: -no check is made to ensure that only -one pattern matches -the case argument. -The first match found defines the set of commands -to be executed. -In the example below the commands following -the second \*(ST will never be executed. -.DS - case $# in - \*(Ca\*(ST) \*(ZZ ;; - \*(Ca\*(ST) \*(ZZ ;; - esac -.DE -.LP -Another example of the use of the \fBcase\fP -construction is to distinguish -between different forms -of an argument. -The following example is a fragment of a \fIcc\fP command. -.DS - for i - do case $i in - \*(DC\(mi[ocs]) \*(ZZ ;; - \*(DC\(mi\*(ST) echo "unknown flag $i" ;; - \*(DC\*(ST.c) /lib/c0 $i \*(ZZ ;; - \*(DC\*(ST) echo "unexpected argument $i" ;; - \*(DOesac - done -.DE -.LP -To allow the same commands to be associated -with more than one pattern -the \fBcase\fP command provides -for alternative patterns -separated by a \*(VT\|. -For example, -.DS - case $i in - \*(Ca\(mix\*(VT\(miy) \*(ZZ - esac -.DE -is equivalent to -.DS - case $i in - \*(Ca\(mi[xy]) \*(ZZ - esac -.DE -.LP -The usual quoting conventions apply -so that -.DS - case $i in - \*(Ca\\?) \*(ZZ -.DE -will match the character \fB?\|.\fP -.SH -2.3\ Here\ documents -.LP -The shell script \fItel\fP -in section 2.1 uses the file \fB/usr/share/telnos\fR -to supply the data -for \fIgrep.\fP -An alternative is to include this -data -within the shell script as a \fIhere\fP document, as in, -.DS - for i - do grep $i \*(HE! - \*(DO\*(ZZ - \*(DOfred mh0123 - \*(DObert mh0789 - \*(DO\*(ZZ - ! - done -.DE -In this example -the shell takes the lines between \fB\*(HE!\fR and \fB!\fR -as the standard input for \fIgrep.\fP -The string \fB!\fR is arbitrary, the document -being terminated by a line that consists -of the string following \*(HE\|. -.LP -Parameters are substituted in the document -before it is made available to \fIgrep\fP -as illustrated by the following script -called \fIedg\|.\fP -.DS - ed $3 \*(HE% - g/$1/s//$2/g - w - % -.DE -The call -.DS - edg string1 string2 file -.DE -is then equivalent to the command -.DS - ed file \*(HE% - g/string1/s//string2/g - w - % -.DE -and changes all occurrences of \fIstring1\fP -in \fIfile\fP to \fIstring2\|.\fP -Substitution can be prevented using \\ -to quote the special character \fB$\fP -as in -.DS - ed $3 \*(HE+ - 1,\\$s/$1/$2/g - w - + -.DE -(This version of \fIedg\fP is equivalent to -the first except that \fIed\fP will print -a \fB?\fR if there are no occurrences of -the string \fB$1\|.\fP) -Substitution within a \fIhere\fP document -may be prevented entirely by quoting -the terminating string, -for example, -.DS - grep $i \*(HE'end' - \*(ZZ - end -.DE -The document is presented -without modification to \fIgrep.\fP -If parameter substitution is not required -in a \fIhere\fP document this latter form -is more efficient. -.SH -2.4\ Shell\ variables\(dg -.LP -.FS -Also known as \fIenvironment variables\fB, see \fIenvironment\fB(7). -.FE -The shell -provides string-valued variables. -Variable names begin with a letter -and consist of letters, digits and -underscores. -Variables may be given values by writing, for example, -.DS - user=fred\ box=m000\ acct=mh0000 -.DE -which assigns values to the variables -\fBuser, box\fP and \fBacct.\fP -A variable may be set to the null string -by saying, for example, -.DS - null= -.DE -The value of a variable is substituted -by preceding its name with \fB$\|\fP; -for example, -.DS - echo $user -.DE -will echo \fIfred.\fP -.LP -Variables may be used interactively -to provide abbreviations for frequently -used strings. -For example, -.DS - b=/usr/fred/bin - mv pgm $b -.DE -will move the file \fIpgm\fP -from the current directory to the directory \fB/usr/fred/bin\|.\fR -A more general notation is available for parameter -(or variable) -substitution, as in, -.DS - echo ${user} -.DE -which is equivalent to -.DS - echo $user -.DE -and is used when the parameter name is -followed by a letter or digit. -For example, -.DS - tmp=/tmp/ps - ps a >${tmp}a -.DE -will direct the output of \fIps\fR -to the file \fB/tmp/psa,\fR -whereas, -.DS - ps a >$tmpa -.DE -would cause the value of the variable \fBtmpa\fP -to be substituted. -.LP -Except for \fB$?\fP the following -are set initially by the shell. -\fB$?\fP is set after executing each command. -.RS -.IP \fB$?\fP 8 -The exit status (return code) -of the last command executed -as a decimal string. -Most commands return a zero exit status -if they complete successfully, -otherwise a non-zero exit status is returned. -Testing the value of return codes is dealt with -later under \fBif\fP and \fBwhile\fP commands. -.IP \fB$#\fP 8 -The number of positional parameters -(in decimal). -Used, for example, in the \fIappend\fP command -to check the number of parameters. -.IP \fB$$\fP 8 -The process number of this shell (in decimal). -Since process numbers are unique among -all existing processes, this string is -frequently used to generate -unique -temporary file names. -For example, -.DS - ps a >/tmp/ps$$ - \*(ZZ - rm /tmp/ps$$ -.DE -.IP \fB$\|!\fP 8 -The process number of the last process -run in the background (in decimal). -.IP \fB$\(mi\fP 8 -The current shell flags, such as -\fB\(mix\fR and \fB\(miv\|.\fR -.RE -.LP -Some variables have a special meaning to the -shell and should be avoided for general -use. -.RS -.IP \fB$\s-1MAIL\s0\fP 8 -When used interactively -the shell looks at the file -specified by this variable -before it issues a prompt. -If the specified file has been modified -since it -was last looked at the shell -prints the message -\fIyou have mail\fP before prompting -for the next command. -This variable is typically set -in the file \fB.profile,\fP -in the user's login directory. -For example, -.DS - \s-1MAIL\s0=/usr/spool/mail/fred -.DE -.IP \fB$\s-1HOME\s0\fP 8 -The default argument -for the \fIcd\fP command. -The current directory is used to resolve -file name references that do not begin with -a \fB/\|,\fR -and is changed using the \fIcd\fP command. -For example, -.DS - cd /usr/fred/bin -.DE -makes the current directory \fB/usr/fred/bin\|.\fR -.DS - cat wn -.DE -will print on the terminal the file \fIwn\fP -in this directory. -The command -\fIcd\fP with no argument -is equivalent to -.DS - cd $\s-1HOME\s0 -.DE -This variable is also typically set in the -the user's login profile. -.IP \fB$\s-1PWD\s0\fP 8 -The current working directory. Set by the \fIcd\fB command. -.IP \fB$\s-1PATH\s0\fP 8 -A list of directories that contain commands (the \fIsearch path\fR\|). -Each time a command is executed by the shell -a list of directories is searched -for an executable file. -.ne 5 -If \fB$\s-1PATH\s0\fP is not set -then the current directory, -\fB/bin\fP, and \fB/usr/bin\fP are searched by default. -.ne 5 -Otherwise \fB$\s-1PATH\s0\fP consists of directory -names separated by \fB:\|.\fP -For example, -.DS - \s-1PATH\s0=\fB:\fP/usr/fred/bin\fB:\fP/bin\fB:\fP/usr/bin -.DE -specifies that the current directory -(the null string before the first \fB:\fP\|), -\fB/usr/fred/bin, /bin \fRand\fP /usr/bin\fR -are to be searched in that order. -In this way individual users -can have their own `private' commands -that are accessible independently -of the current directory. -If the command name contains a \fB/\fR then this directory search -is not used; a single attempt -is made to execute the command. -.IP \fB$\s-1PS1\s0\fP 8 -The primary shell prompt string, by default, `\fB$\ \fR'. -.IP \fB$\s-1PS2\s0\fP 8 -The shell prompt when further input is needed, -by default, `\fB>\ \fR'. -.IP \fB$\s-1IFS\s0\fP 8 -The set of characters used by \fIblank -interpretation\fR (see section 3.5). -.IP \fB$\s-1ENV\s0\fP 8 -The shell reads and executes the commands in the file -specified by this variable when it is initially started. -Unlike the \fB.profile\fP file, these commands are executed by all -shells, not just the one started at login. -(Most versions of the shell specify a filename that is used if -\s-1ENV\s0 is not explicitly set. See the manual page for your shell.) -.RE -.SH -2.5\ The\ test\ command -.LP -The \fItest\fP command, although not part of the shell, -is intended for use by shell programs. -For example, -.DS - test \(mif file -.DE -returns zero exit status if \fIfile\fP -exists and non-zero exit status otherwise. -In general \fItest\fP evaluates a predicate -and returns the result as its exit status. -Some of the more frequently used \fItest\fP -arguments are given here, see \fItest\fP(1) -for a complete specification. -.DS - test s true if the argument \fIs\fP is not the null string - test \(mif file true if \fIfile\fP exists - test \(mir file true if \fIfile\fP is readable - test \(miw file true if \fIfile\fP is writable - test \(mid file true if \fIfile\fP is a directory -.DE -The \fItest\fP command is known as `\fB[\fP' and may be invoked as -such. -For aesthetic reasons, the command ignores a close bracket `\fB]\fP' given -at the end of a command so -.DS - [ -f filename ] -.DE -and -.DS - test -f filename -.DE -are completely equivalent. -Typically, the bracket notation is used when \fItest\fP is invoked inside -shell control constructs. -.SH -2.6\ Control\ flow\ -\ while -.LP -The actions of -the \fBfor\fP loop and the \fBcase\fP -branch are determined by data available to the shell. -A \fBwhile\fP or \fBuntil\fP loop -and an \fBif then else\fP branch -are also provided whose -actions are determined by the exit status -returned by commands. -A \fBwhile\fP loop has the general form -.DS - \fBwhile\fP \fIcommand-list\*1\fP - \fBdo\fP \fIcommand-list\*2\fP - \fBdone\fP -.DE -.LP -The value tested by the \fBwhile\fP command -is the exit status of the last simple command -following \fBwhile.\fP -Each time round the loop -\fIcommand-list\*1\fP is executed; -if a zero exit status is returned then -\fIcommand-list\*2\fP -is executed; -otherwise, the loop terminates. -For example, -.DS - while [ $1 ] - do \*(ZZ - \*(DOshift - done -.DE -is equivalent to -.DS - for i - do \*(ZZ - done -.DE -\fIshift\fP is a shell command that -renames the positional parameters -\fB$2, $3, \*(ZZ\fR as \fB$1, $2, \*(ZZ\fR -and loses \fB$1\|.\fP -.LP -Another kind of use for the \fBwhile/until\fP -loop is to wait until some -external event occurs and then run -some commands. -In an \fBuntil\fP loop -the termination condition is reversed. -For example, -.DS - until [ \(mif file ] - do sleep 300; done - \fIcommands\fP -.DE -will loop until \fIfile\fP exists. -Each time round the loop it waits for -5 minutes before trying again. -(Presumably another process -will eventually create the file.) -.LP -The most recent enclosing loop may be exited with the \fBbreak\fP -command, or the rest of the body skipped and the next iteration begun -with the \fBcontinue\fP command. -.LP -The commands \fItrue\fP(1) and \fIfalse\fP(1) return 0 and non-zero -exit statuses respectively. They are sometimes of use in control flow, -e.g.: -.DS - while true - do date; sleep 5 - done -.DE -is an infinite loop that prints the date and time every five seconds. -.SH -2.7\ Control\ flow\ -\ if -.LP -Also available is a -general conditional branch -of the form, -.DS - \fBif\fP \fIcommand-list - \fBthen \fIcommand-list - \fBelse \fIcommand-list - \fBfi\fR -.DE -that tests the value returned by the last simple command -following \fBif.\fP -.LP -The \fBif\fP command may be used -in conjunction with the \fItest\fP command -to test for the existence of a file as in -.DS - if [ \(mif file ] - then \fIprocess file\fP - else \fIdo something else\fP - fi -.DE -.LP -An example of the use of \fBif, case\fP -and \fBfor\fP constructions is given in -section 2.10\|. -.LP -A multiple test \fBif\fP command -of the form -.DS - if \*(ZZ - then \*(ZZ - else if \*(ZZ - then \*(ZZ - else if \*(ZZ - \*(ZZ - fi - fi - fi -.DE -may be written using an extension of the \fBif\fP -notation as, -.DS - if \*(ZZ - then \*(ZZ - elif \*(ZZ - then \*(ZZ - elif \*(ZZ - \*(ZZ - fi -.DE -.LP -The following example is an implementation of the \fItouch\fP command -which changes the `last modified' time for a list -of files. -The command may be used in conjunction -with \fImake\fP(1) to force recompilation of a list -of files. -.DS - #!/bin/sh - - flag= - for i - do case $i in - \*(DC\(mic) flag=N ;; - \*(DC\*(ST) if [ \(mif $i ] - \*(DC then cp $i junk$$; mv junk$$ $i - \*(DC elif [ $flag ] - \*(DC then echo file \\'$i\\' does not exist - \*(DC else >$i - \*(DC fi - \*(DO esac - done -.DE -The \fB\(mic\fP flag is used in this command to -force subsequent files to be created if they do not already exist. -Otherwise, if the file does not exist, an error message is printed. -The shell variable \fIflag\fP -is set to some non-null string if the \fB\(mic\fP -argument is encountered. -The commands -.DS - cp \*(ZZ; mv \*(ZZ -.DE -copy the file and then overwrite it with the copy, -thus causing the last modified date to be updated. -.LP -The sequence -.DS - if command1 - then command2 - fi -.DE -may be written -.DS - command1 && command2 -.DE -Conversely, -.DS - command1 \*(VT\*(VT command2 -.DE -executes \fIcommand2\fP only if \fIcommand1\fP -fails. -In each case the value returned -is that of the last simple command executed. -.LP -Placing a `\fB!\fP' in front of a pipeline inverts its exit -status, almost in the manner of the C operator of the same name. -Thus: -.DS - if ! [ -d $1 ] - then - echo $1 is not a directory - fi -.DE -will print a message only if $1 is not a directory. -.SH -2.8\ Command\ grouping -.LP -Commands may be grouped in two ways, -.DS - \fB{\fI command-list\fB ; }\fR -.DE -and -.DS - \fB(\fI command-list\fB )\fR -.DE -.LP -In the first \fIcommand-list\fP is simply executed. -The second form executes \fIcommand-list\fP -as a separate process. -For example, -.DS - (cd x; rm junk ) -.DE -executes \fIrm junk\fP in the directory -\fBx\fP without changing the current -directory of the invoking shell. -.LP -The commands -.DS - cd x; rm junk -.DE -have the same effect but leave the invoking -shell in the directory \fBx.\fP -.SH -2.9\ Shell\ Functions -.LP -A function may be defined by the syntax -.DS - \fIfuncname\fP() \fB{\fI command-list\fB ; }\fR -.DE -Functions are invoked within a script as though they were separate -commands of the same name. -While they are executed, the -positional parameters \fB$1, $2, \*(ZZ\fR are temporarily set to the -arguments passed to the function. For example: -.DS - count() { - echo $2 : $# - } - - count a b c -.DE -would print `b : 3'. -.SH -2.10\ Debugging\ shell\ scripts -.LP -The shell provides two tracing mechanisms -to help when debugging shell scripts. -The first is invoked within the script -as -.DS - set \(miv -.DE -(\fBv\fP for verbose) and causes lines of the -script to be printed as they are read. -It is useful to help isolate syntax errors. -It may be invoked without modifying the script -by saying -.DS - sh \(miv \fIscript\fP \*(ZZ -.DE -where \fIscript\fP is the name of the shell script. -This flag may be used in conjunction -with the \fB\(min\fP flag which prevents -execution of subsequent commands. -(Note that saying \fIset \(min\fP at a terminal -will render the terminal useless -until an end-of-file is typed.) -.LP -The command -.DS - set \(mix -.DE -will produce an execution -trace. -Following parameter substitution -each command is printed as it is executed. -(Try these at the terminal to see -what effect they have.) -Both flags may be turned off by saying -.DS - set \(mi -.DE -and the current setting of the shell flags is available as \fB$\(mi\|\fR. -.SH -2.11\ The\ man\ command -.LP -The following is a simple implementation of the \fIman\fP command, -which is used to display sections of the UNIX manual on your terminal. -It is called, for example, as -.DS - man sh - man \(mit ed - man 2 fork -.DE -In the first the manual section for \fIsh\fP -is displayed.. -Since no section is specified, section 1 is used. -The second example will typeset (\fB\(mit\fP option) -the manual section for \fIed.\fP -The last prints the \fIfork\fP manual page -from section 2, which covers system calls. -.sp 2 -.DS - #!/bin/sh - - cd /usr/share/man - - # "#" is the comment character - # default is nroff ($N), section 1 ($s) - N=n\ s=1 - - for i - do case $i in -.sp .5 - \*(DC[1\(mi9]\*(ST) s=$i ;; -.sp .5 - \*(DC\(mit) N=t ;; -.sp .5 - \*(DC\(min) N=n ;; -.sp .5 - \*(DC\(mi\*(ST) echo unknown flag \\'$i\\' ;; -.sp .5 - \*(DC\*(ST) if [ \(mif man$s/$i.$s ] - \*(DC then - \*(DC ${N}roff \(miman man$s/$i.$s - \*(DC else # look through all manual sections - \*(DC found=no - \*(DC for j in 1 2 3 4 5 6 7 8 9 - \*(DC do - \*(DC \*(DOif [ \(mif man$j/$i.$j ] - \*(DC \*(DOthen - \*(DC \*(DO\*(THman $j $i - \*(DC \*(DO\*(THfound=yes - \*(DC \*(DO\*(THbreak - \*(DC \*(DOfi - \*(DC done - \*(DC case $found in - \*(DC \*(Cano) echo \\'$i: manual page not found\\' - \*(DC esac - \*(DC fi - \*(DOesac - done -.DE -.ce -.ft B -Figure 1. A version of the man command -.ft R diff --git a/bin/sh/USD.doc/t3 b/bin/sh/USD.doc/t3 deleted file mode 100644 index aab53ee11..000000000 --- a/bin/sh/USD.doc/t3 +++ /dev/null @@ -1,976 +0,0 @@ -.\" $NetBSD: t3,v 1.3 2010/08/22 02:19:07 perry Exp $ -.\" -.\" Copyright (C) Caldera International Inc. 2001-2002. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions are -.\" met: -.\" -.\" Redistributions of source code and documentation must retain the above -.\" copyright notice, this list of conditions and the following -.\" disclaimer. -.\" -.\" Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" -.\" This product includes software developed or owned by Caldera -.\" International, Inc. Neither the name of Caldera International, Inc. -.\" nor the names of other contributors may be used to endorse or promote -.\" products derived from this software without specific prior written -.\" permission. -.\" -.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA -.\" INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -.\" DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE -.\" FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -.\" OR OTHERWISE) RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" @(#)t3 8.1 (Berkeley) 6/8/93 -.\" -.SH -3.0\ Keyword\ parameters -.LP -Shell variables may be given values -by assignment -or when a shell script is invoked. -An argument to a command of the form -\fIname=value\fP -that precedes the command name -causes \fIvalue\fP -to be assigned to \fIname\fP -before execution of the command begins. -The value of \fIname\fP in the invoking -shell is not affected. -For example, -.DS - user=fred\ command -.DE -will execute \fIcommand\fP with -\fBuser\fP set to \fIfred\fP. -.\" Removed by Perry Metzger because -k is not in POSIX -.\" -.\" The \fB\(mik\fR flag causes arguments of the form -.\" \fIname=value\fP to be interpreted in this way -.\" anywhere in the argument list. -.\" Such \fInames\fP are sometimes -.\" called keyword parameters. -.\" If any arguments remain they -.\" are available as positional -.\" parameters \fB$1, $2, \*(ZZ\|.\fP -.LP -The \fIset\fP command -may also be used to set positional parameters -from within a script. -For example, -.DS - set\ \(mi\(mi\ \*(ST -.DE -will set \fB$1\fP to the first file name -in the current directory, \fB$2\fP to the next, -and so on. -Note that the first argument, \(mi\(mi, ensures correct treatment -when the first file name begins with a \(mi\|. -.LP -.SH -3.1\ Parameter\ transmission -.LP -When a command is executed both positional parameters -and shell variables may be set on invocation. -Variables are also made available implicitly -to a command -by specifying in advance that such parameters -are to be exported from the invoking shell. -For example, -.DS - export\ user\ box=red -.DE -marks the variables \fBuser\fP and \fBbox\fP -for export (setting \fBbox\fP to ``red'' in the process). -When a command is invoked -copies are made of all exportable variables -(also known as \fIenvironment variables\fP) -for use within the invoked program. -Modification of such variables -within an invoked command does not -affect the values in the invoking shell. -It is generally true of -a shell script or other program -that it -cannot modify the state -of its caller without explicit -actions on the part of the caller. -.\" Removed by Perry Metzger because this is confusing to beginners. -.\" -.\" (Shared file descriptors are an -.\" exception to this rule.) -.LP -Names whose value is intended to remain -constant may be declared \fIreadonly\|.\fP -The form of this command is the same as that of the \fIexport\fP -command, -.DS - readonly name[=value] \*(ZZ -.DE -Subsequent attempts to set readonly variables -are illegal. -.SH -3.2\ Parameter\ substitution -.LP -If a shell parameter is not set -then the null string is substituted for it. -For example, if the variable \fBd\fP -is not set -.DS - echo $d -.DE -or -.DS - echo ${d} -.DE -will echo nothing. -A default string may be given -as in -.DS - echo ${d:\(mi\fB.\fR} -.DE -which will echo -the value of the variable \fBd\fP -if it is set and not null and `\fB.\fP' otherwise. -The default string is evaluated using the usual -quoting conventions so that -.DS - echo ${d:\(mi\'\*(ST\'} -.DE -will echo \fB\*(ST\fP if the variable \fBd\fP -is not set or null. -Similarly -.DS - echo ${d:\(mi$1} -.DE -will echo the value of \fBd\fP if it is set and not null -and the value (if any) of \fB$1\fP otherwise. -.LP -The notation ${d:+\fB.\fR} performs the inverse operation. It -substitutes `\fB.\fP' if \fBd\fP is set or not null, and otherwise -substitutes null. -.LP -A variable may be assigned a default value -using -the notation -.DS - echo ${d:=\fB.\fR} -.DE -which substitutes the same string as -.DS - echo ${d:\(mi\fB.\fR} -.DE -and if \fBd\fP were not previously set or null -then it will be set to the string `\fB.\fP'\|. -.LP -If there is no sensible default then -the notation -.DS - echo ${d:?\fImessage\fP} -.DE -will echo the value of the variable \fBd\fP if it is set and not null, -otherwise \fImessage\fP is printed by the shell and -execution of the shell script is abandoned. -If \fImessage\fP is absent then a standard message -is printed. -A shell script that requires some variables -to be set might start as follows: -.DS - :\ ${user:?}\ ${acct:?}\ ${bin:?} - \*(ZZ -.DE -Colon (\fB:\fP) is a command -that is -built in to the shell and does nothing -once its arguments have been evaluated. -If any of the variables \fBuser, acct\fP -or \fBbin\fP are not set then the shell -will abandon execution of the script. -.SH -3.3\ Command\ substitution -.LP -The standard output from a command can be -substituted in a similar way to parameters. -The command \fIpwd\fP prints on its standard -output the name of the current directory. -For example, if the current directory is -\fB/usr/fred/bin\fR -then the commands -.DS - d=$(pwd) -.DE -(or the older notation d=\`pwd\`) -is equivalent to -.DS - d=/usr/fred/bin -.DE -.LP -The entire string inside $(\*(ZZ)\| (or between grave accents \`\*(ZZ\`) -is taken as the command -to be executed -and is replaced with the output from -the command. -(The difference between the $(\*(ZZ) and \`\*(ZZ\` notations is that -the former may be nested, while the latter cannot be.) -.LP -The command is written using the usual quoting conventions, -except that inside \`\*(ZZ\` -a \fB\`\fR must be escaped using -a \fB\\\|\fR. -For example, -.DS - ls $(echo "$HOME") -.DE -is equivalent to -.DS - ls $HOME -.DE -Command substitution occurs in all contexts -where parameter substitution occurs (including \fIhere\fP documents) and the -treatment of the resulting text is the same -in both cases. -This mechanism allows string -processing commands to be used within -shell scripts. -An example of such a command is \fIbasename\fP -which removes a specified suffix from a string. -For example, -.DS - basename main\fB.\fPc \fB.\fPc -.DE -will print the string \fImain\|.\fP -Its use is illustrated by the following -fragment from a \fIcc\fP command. -.DS - case $A in - \*(Ca\*(ZZ - \*(Ca\*(ST\fB.\fPc) B=$(basename $A \fB.\fPc) - \*(Ca\*(ZZ - esac -.DE -that sets \fBB\fP to the part of \fB$A\fP -with the suffix \fB.c\fP stripped. -.LP -Here are some composite examples. -.RS -.IP \(bu -.ft B -for i in \`ls \(mit\`; do \*(ZZ -.ft R -.br -The variable \fBi\fP is set -to the names of files in time order, -most recent first. -.IP \(bu -.ft B -set \(mi\(mi\| \`date\`; echo $6 $2 $3, $4 -.ft R -.br -will print, e.g., -.ft I -1977 Nov 1, 23:59:59 -.ft R -.RE -.SH -3.4\ Arithmetic\ Expansion -.LP -Within a $((\*(ZZ)) construct, integer arithmetic operations are -evaluated. -(The $ in front of variable names is optional within $((\*(ZZ)). -For example: -.DS - x=5; y=1 - echo $(($x+3*2)) - echo $((y+=x)) - echo $y -.DE -will print `11', then `6', then `6' again. -Most of the constructs permitted in C arithmetic operations are -permitted though some (like `++') are not universally supported \(em -see the shell manual page for details. -.SH -3.5\ Evaluation\ and\ quoting -.LP -The shell is a macro processor that -provides parameter substitution, command substitution and file -name generation for the arguments to commands. -This section discusses the order in which -these evaluations occur and the -effects of the various quoting mechanisms. -.LP -Commands are parsed initially according to the grammar -given in appendix A. -Before a command is executed -the following -substitutions occur. -.RS -.IP \(bu -parameter substitution, e.g. \fB$user\fP -.IP \(bu -command substitution, e.g. \fB$(pwd)\fP or \fB\`pwd\`\fP -.IP \(bu -arithmetic expansion, e.g. \fB$(($count+1))\fP -.RS -.LP -Only one evaluation occurs so that if, for example, the value of the variable -\fBX\fP -is the string \fI$y\fP -then -.DS - echo $X -.DE -will echo \fI$y\|.\fP -.RE -.IP \(bu -blank interpretation -.RS -.LP -Following the above substitutions -the resulting characters -are broken into non-blank words (\fIblank interpretation\fP). -For this purpose `blanks' are the characters of the string -\fB$\s-1IFS\s0\fP. -By default, this string consists of blank, tab and newline. -The null string -is not regarded as a word unless it is quoted. -For example, -.DS - echo \'\' -.DE -will pass on the null string as the first argument to \fIecho\fP, -whereas -.DS - echo $null -.DE -will call \fIecho\fR with no arguments -if the variable \fBnull\fP is not set -or set to the null string. -.RE -.IP \(bu -file name generation -.RS -.LP -Each word -is then scanned for the file pattern characters -\fB\*(ST, ?\fR and \fB[\*(ZZ]\fR -and an alphabetical list of file names -is generated to replace the word. -Each such file name is a separate argument. -.RE -.RE -.LP -The evaluations just described also occur -in the list of words associated with a \fBfor\fP -loop. -Only substitution occurs -in the \fIword\fP used -for a \fBcase\fP branch. -.LP -As well as the quoting mechanisms described -earlier using \fB\\\fR and \fB\'\*(ZZ\'\fR -a third quoting mechanism is provided using double quotes. -Within double quotes parameter and command substitution -occurs but file name generation and the interpretation -of blanks does not. -The following characters -have a special meaning within double quotes -and may be quoted using \fB\\\|.\fP -.DS - \fB$ \fPparameter substitution - \fB$()\fP command substitution - \fB\`\fP command substitution - \fB"\fP ends the quoted string - \fB\e\fP quotes the special characters \fB$ \` " \e\fP -.DE -For example, -.DS - echo "$x" -.DE -will pass the value of the variable \fBx\fP as a -single argument to \fIecho.\fP -Similarly, -.DS - echo "$\*(ST" -.DE -will pass the positional parameters as a single -argument and is equivalent to -.DS - echo "$1 $2 \*(ZZ" -.DE -The notation \fB$@\fP -is the same as \fB$\*(ST\fR -except when it is quoted. -.DS - echo "$@" -.DE -will pass the positional parameters, unevaluated, to \fIecho\fR -and is equivalent to -.DS - echo "$1" "$2" \*(ZZ -.DE -.LP -The following table gives, for each quoting mechanism, -the shell metacharacters that are evaluated. -.DS -.ce -.ft I -metacharacter -.ft -.in 1.5i - \e $ * \` " \' -\' n n n n n t -\` y n n t n n -" y y n y t n - - t terminator - y interpreted - n not interpreted - -.in -.ft B -.ce -Figure 2. Quoting mechanisms -.ft -.DE -.LP -In cases where more than one evaluation of a string -is required the built-in command \fIeval\fP -may be used. -For example, -if the variable \fBX\fP has the value -\fI$y\fP, and if \fBy\fP has the value \fIpqr\fP -then -.DS - eval echo $X -.DE -will echo the string \fIpqr\|.\fP -.LP -In general the \fIeval\fP command -evaluates its arguments (as do all commands) -and treats the result as input to the shell. -The input is read and the resulting command(s) -executed. -For example, -.DS - wg=\'eval who\*(VTgrep\' - $wg fred -.DE -is equivalent to -.DS - who\*(VTgrep fred -.DE -In this example, -\fIeval\fP is required -since there is no interpretation -of metacharacters, such as \fB\*(VT\|\fR, following -substitution. -.SH -3.6\ Error\ handling -.LP -The treatment of errors detected by -the shell depends on the type of error -and on whether the shell is being -used interactively. -An interactive shell is one whose -input and output are connected -to a terminal. -.\" Removed by Perry Metzger, obsolete and excess detail -.\" -.\" (as determined by -.\" \fIgtty\fP (2)). -A shell invoked with the \fB\(mii\fP -flag is also interactive. -.LP -Execution of a command (see also 3.7) may fail -for any of the following reasons. -.IP \(bu -Input output redirection may fail. -For example, if a file does not exist -or cannot be created. -.IP \(bu -The command itself does not exist -or cannot be executed. -.IP \(bu -The command terminates abnormally, -for example, with a "bus error" -or "memory fault". -See Figure 2 below for a complete list -of UNIX signals. -.IP \(bu -The command terminates normally -but returns a non-zero exit status. -.LP -In all of these cases the shell -will go on to execute the next command. -Except for the last case an error -message will be printed by the shell. -All remaining errors cause the shell -to exit from a script. -An interactive shell will return -to read another command from the terminal. -Such errors include the following. -.IP \(bu -Syntax errors. -e.g., if \*(ZZ then \*(ZZ done -.IP \(bu -A signal such as interrupt. -The shell waits for the current -command, if any, to finish execution and -then either exits or returns to the terminal. -.IP \(bu -Failure of any of the built-in commands -such as \fIcd.\fP -.LP -The shell flag \fB\(mie\fP -causes the shell to terminate -if any error is detected. -.DS -1 hangup -2 interrupt -3* quit -4* illegal instruction -5* trace trap -6* IOT instruction -7* EMT instruction -8* floating point exception -9 kill (cannot be caught or ignored) -10* bus error -11* segmentation violation -12* bad argument to system call -13 write on a pipe with no one to read it -14 alarm clock -15 software termination (from \fIkill\fP (1)) - -.DE -.ft B -.ce -Figure 3. UNIX signals\(dg -.ft -.FS -\(dg Additional signals have been added in modern Unix. -See \fIsigvec\fP(2) or \fIsignal\fP(3) for an up-to-date list. -.FE -Those signals marked with an asterisk -produce a core dump -if not caught. -However, -the shell itself ignores quit which is the only -external signal that can cause a dump. -The signals in this list of potential interest -to shell programs are 1, 2, 3, 14 and 15. -.SH -3.7\ Fault\ handling -.LP -shell scripts normally terminate -when an interrupt is received from the -terminal. -The \fItrap\fP command is used -if some cleaning up is required, such -as removing temporary files. -For example, -.DS - trap\ \'rm\ /tmp/ps$$; exit\'\ 2 -.DE -sets a trap for signal 2 (terminal -interrupt), and if this signal is received -will execute the commands -.DS - rm /tmp/ps$$; exit -.DE -\fIexit\fP is -another built-in command -that terminates execution of a shell script. -The \fIexit\fP is required; otherwise, -after the trap has been taken, -the shell will resume executing -the script -at the place where it was interrupted. -.LP -UNIX signals can be handled in one of three ways. -They can be ignored, in which case -the signal is never sent to the process. -They can be caught, in which case the process -must decide what action to take when the -signal is received. -Lastly, they can be left to cause -termination of the process without -it having to take any further action. -If a signal is being ignored -on entry to the shell script, for example, -by invoking it in the background (see 3.7) then \fItrap\fP -commands (and the signal) are ignored. -.LP -The use of \fItrap\fP is illustrated -by this modified version of the \fItouch\fP -command (Figure 4). -The cleanup action is to remove the file \fBjunk$$\fR\|. -.DS - #!/bin/sh - - flag= - trap\ \'rm\ \(mif\ junk$$;\ exit\'\ 1 2 3 15 - for i - do\ case\ $i\ in - \*(DC\(mic) flag=N ;; - \*(DC\*(ST) if\ test\ \(mif\ $i - \*(DC then cp\ $i\ junk$$;\ mv\ junk$$ $i - \*(DC elif\ test\ $flag - \*(DC then echo\ file\ \\'$i\\'\ does\ not\ exist - \*(DC else >$i - \*(DC fi - \*(DOesac - done -.DE -.sp -.ft B -.ce -Figure 4. The touch command -.ft -.sp -The \fItrap\fP command -appears before the creation -of the temporary file; -otherwise it would be -possible for the process -to die without removing -the file. -.LP -Since there is no signal 0 in UNIX -it is used by the shell to indicate the -commands to be executed on exit from the -shell script. -.LP -A script may, itself, elect to -ignore signals by specifying the null -string as the argument to trap. -The following fragment is taken from the -\fInohup\fP command. -.DS - trap \'\' 1 2 3 15 -.DE -which causes \fIhangup, interrupt, quit \fRand\fI kill\fR -to be ignored both by the -script and by invoked commands. -.LP -Traps may be reset by saying -.DS - trap 2 3 -.DE -which resets the traps for signals 2 and 3 to their default values. -A list of the current values of traps may be obtained -by writing -.DS - trap -.DE -.LP -The script \fIscan\fP (Figure 5) is an example -of the use of \fItrap\fP where there is no exit -in the trap command. -\fIscan\fP takes each directory -in the current directory, prompts -with its name, and then executes -commands typed at the terminal -until an end of file or an interrupt is received. -Interrupts are ignored while executing -the requested commands but cause -termination when \fIscan\fP is -waiting for input. -.DS - d=\`pwd\` - for\ i\ in\ \*(ST - do\ if\ test\ \(mid\ $d/$i - \*(DOthen\ cd\ $d/$i - \*(DO\*(THwhile\ echo\ "$i:" - \*(DO\*(TH\*(WHtrap\ exit\ 2 - \*(DO\*(TH\*(WHread\ x - \*(DO\*(THdo\ trap\ :\ 2;\ eval\ $x;\ done - \*(DOfi - done -.DE -.sp -.ft B -.ce -Figure 5. The scan command -.ft -.sp -\fIread x\fR is a built-in command that reads one line from the -standard input -and places the result in the variable \fBx\|.\fP -It returns a non-zero exit status if either -an end-of-file is read or an interrupt -is received. -.SH -3.8\ Command\ execution -.LP -To run a command (other than a built-in) the shell first creates -a new process using the system call \fIfork.\fP -The execution environment for the command -includes input, output and the states of signals, and -is established in the child process -before the command is executed. -The built-in command \fIexec\fP -is used in the rare cases when no fork -is required -and simply replaces the shell with a new command. -For example, a simple version of the \fInohup\fP -command looks like -.DS - trap \\'\\' 1 2 3 15 - exec $\*(ST -.DE -The \fItrap\fP turns off the signals specified -so that they are ignored by subsequently created commands -and \fIexec\fP replaces the shell by the command -specified. -.LP -Most forms of input output redirection have already been -described. -In the following \fIword\fP is only subject -to parameter and command substitution. -No file name generation or blank interpretation -takes place so that, for example, -.DS - echo \*(ZZ >\*(ST.c -.DE -will write its output into a file whose name is \fB\*(ST.c\|.\fP -Input output specifications are evaluated left to right -as they appear in the command. -.IP >\ \fIword\fP 12 -The standard output (file descriptor 1) -is sent to the file \fIword\fP which is -created if it does not already exist. -.IP \*(AP\ \fIword\fP 12 -The standard output is sent to file \fIword.\fP -If the file exists then output is appended -(by seeking to the end); -otherwise the file is created. -.IP <\ \fIword\fP 12 -The standard input (file descriptor 0) -is taken from the file \fIword.\fP -.IP \*(HE\ \fIword\fP 12 -The standard input is taken from the lines -of shell input that follow up to but not -including a line consisting only of \fIword.\fP -If \fIword\fP is quoted then no interpretation -of the document occurs. -If \fIword\fP is not quoted -then parameter and command substitution -occur and \fB\\\fP is used to quote -the characters \fB\\\fP \fB$\fP \fB\`\fP and the first character -of \fIword.\fP -In the latter case \fB\\newline\fP is ignored (c.f. quoted strings). -.IP >&\ \fIdigit\fP 12 -The file descriptor \fIdigit\fP is duplicated using the system -call \fIdup\fP (2) -and the result is used as the standard output. -.IP <&\ \fIdigit\fP 12 -The standard input is duplicated from file descriptor \fIdigit.\fP -.IP <&\(mi 12 -The standard input is closed. -.IP >&\(mi 12 -The standard output is closed. -.LP -Any of the above may be preceded by a digit in which -case the file descriptor created is that specified by the digit -instead of the default 0 or 1. -For example, -.DS - \*(ZZ 2>file -.DE -runs a command with message output (file descriptor 2) -directed to \fIfile.\fP -.DS - \*(ZZ 2>&1 -.DE -runs a command with its standard output and message output -merged. -(Strictly speaking file descriptor 2 is created -by duplicating file descriptor 1 but the effect is usually to -merge the two streams.) -.\" Removed by Perry Metzger, most of this is now obsolete -.\" -.\" .LP -.\" The environment for a command run in the background such as -.\" .DS -.\" list \*(ST.c \*(VT lpr & -.\" .DE -.\" is modified in two ways. -.\" Firstly, the default standard input -.\" for such a command is the empty file \fB/dev/null\|.\fR -.\" This prevents two processes (the shell and the command), -.\" which are running in parallel, from trying to -.\" read the same input. -.\" Chaos would ensue -.\" if this were not the case. -.\" For example, -.\" .DS -.\" ed file & -.\" .DE -.\" would allow both the editor and the shell -.\" to read from the same input at the same time. -.\" .LP -.\" The other modification to the environment of a background -.\" command is to turn off the QUIT and INTERRUPT signals -.\" so that they are ignored by the command. -.\" This allows these signals to be used -.\" at the terminal without causing background -.\" commands to terminate. -.\" For this reason the UNIX convention -.\" for a signal is that if it is set to 1 -.\" (ignored) then it is never changed -.\" even for a short time. -.\" Note that the shell command \fItrap\fP -.\" has no effect for an ignored signal. -.SH -3.9\ Invoking\ the\ shell -.LP -The following flags are interpreted by the shell -when it is invoked. -If the first character of argument zero is a minus, -then commands are read from the file \fB.profile\|.\fP -.IP \fB\(mic\fP\ \fIstring\fP -.br -If the \fB\(mic\fP flag is present then -commands are read from \fIstring\|.\fP -.IP \fB\(mis\fP -If the \fB\(mis\fP flag is present or if no -arguments remain -then commands are read from the standard input. -Shell output is written to -file descriptor 2. -.IP \fB\(mii\fP -If the \fB\(mii\fP flag is present or -if the shell input and output are attached to a terminal (as told by \fIgtty\fP) -then this shell is \fIinteractive.\fP -In this case TERMINATE is ignored (so that \fBkill 0\fP -does not kill an interactive shell) and INTERRUPT is caught and ignored -(so that \fBwait\fP is interruptable). -In all cases QUIT is ignored by the shell. -.SH -3.10\ Job\ Control -.LP -When a command or pipeline (also known as a \fIjob\fP) is running in -the foreground, entering the stop character (typically -\s-1CONTROL-Z\s0 but user settable with the \fIstty\fP(1) command) -will usually cause the job to stop. -.LP -The jobs associated with the current shell may be listed by entering -the \fIjobs\fP command. -Each job has an associated \fIjob number\fP. -Jobs that are stopped may be continued by entering -.DS - bg %\fIjobnumber\fP -.DE -and jobs may be moved to the foreground by entering -.DS - fg %\fIjobnumber\fP -.DE -If there is a sole job with a particular name (say only one instance -of \fIcc\fP running), \fIfg\fP and \fIbg\fP may also use name of the -command in place of the number, as in: -.DS - bg %cc -.DE -If no `\fB%\fP' clause is entered, most recently stopped job -(indicated with a `+' by the \fIjobs\fP command) will be assumed. -See the manual page for the shell for more details. -.SH -3.11\ Aliases -.LP -The \fIalias\fP command creates a so-called shell alias, which is an -abbreviation that macro-expands at run time into some other command. -For example: -.DS - alias ls="ls -F" -.DE -would cause the command sequence \fBls -F\fP to be executed whenever -the user types \fBls\fP into the shell. -Note that if the user types \fBls -a\fP, the shell will in fact -execute \fBls -F -a\fP. -The command \fBalias\fP on its own prints out all current aliases. -The \fIunalias\fP command, as in: -.DS - unalias ls -.DE -will remove an existing alias. -Aliases can shadow pre-existing commands, as in the example above. -They are typically used to override the interactive behavior of -commands in small ways, for example to always invoke some program with -a favorite option, and are almost never found in scripts. -.SH -3.12\ Command\ Line\ Editing\ and\ Recall -.LP -When working interactively with the shell, it is often tedious to -retype previously entered commands, especially if they are complicated. -The shell therefore maintains a so-called \fIhistory\fP, which is -stored in the file specified by the \fB\s-1HISTFILE\s0\fP environment -variable if it is set. -Users may view, edit, and re-enter previous lines of input using -a small subset of the commands of the \fIvi\fP(1) or -\fIemacs\fP(1)\(dg editors. -.FS -Technically, vi command editing is standardized by POSIX while emacs -is not. -However, all modern shells support both styles. -.FE -Emacs style editing may be selected by entering -.DS - set -o emacs -.DE -and vi style editing may be selected with -.DS - set -o vi -.DE -The details of how command line editing works are beyond the scope of -this document. -See the shell manual page for details. -.SH -Acknowledgements -.LP -The design of the shell is -based in part on the original UNIX shell -.[ -unix command language thompson -.] -and the PWB/UNIX shell, -.[ -pwb shell mashey unix -.] -some -features having been taken from both. -Similarities also exist with the -command interpreters -of the Cambridge Multiple Access System -.[ -cambridge multiple access system hartley -.] -and of CTSS. -.[ -ctss -.] -.LP -I would like to thank Dennis Ritchie -and John Mashey for many -discussions during the design of the shell. -I am also grateful to the members of the Computing Science Research Center -and to Joe Maranzano for their -comments on drafts of this document. -.SH -.[ -$LIST$ -.] diff --git a/bin/sh/USD.doc/t4 b/bin/sh/USD.doc/t4 deleted file mode 100644 index 7719d6c40..000000000 --- a/bin/sh/USD.doc/t4 +++ /dev/null @@ -1,180 +0,0 @@ -.\" $NetBSD: t4,v 1.3 2010/08/22 02:19:07 perry Exp $ -.\" -.\" Copyright (C) Caldera International Inc. 2001-2002. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions are -.\" met: -.\" -.\" Redistributions of source code and documentation must retain the above -.\" copyright notice, this list of conditions and the following -.\" disclaimer. -.\" -.\" Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" -.\" All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" -.\" This product includes software developed or owned by Caldera -.\" International, Inc. Neither the name of Caldera International, Inc. -.\" nor the names of other contributors may be used to endorse or promote -.\" products derived from this software without specific prior written -.\" permission. -.\" -.\" USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA -.\" INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -.\" DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE -.\" FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR -.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -.\" OR OTHERWISE) RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN -.\" IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" @(#)t4 8.1 (Berkeley) 8/14/93 -.\" -.bp -.SH -Appendix\ A\ -\ Grammar -.LP -Note: This grammar needs updating, it is obsolete. -.LP -.LD -\fIitem: word - input-output - name = value -.sp 0.7 -simple-command: item - simple-command item -.sp 0.7 -command: simple-command - \fB( \fIcommand-list \fB) - \fB{ \fIcommand-list \fB} - \fBfor \fIname \fBdo \fIcommand-list \fBdone - \fBfor \fIname \fBin \fIword \*(ZZ \fBdo \fIcommand-list \fBdone - \fBwhile \fIcommand-list \fBdo \fIcommand-list \fBdone - \fBuntil \fIcommand-list \fBdo \fIcommand-list \fBdone - \fBcase \fIword \fBin \fIcase-part \*(ZZ \fBesac - \fBif \fIcommand-list \fBthen \fIcommand-list \fIelse-part \fBfi -.sp 0.7 -\fIpipeline: command - pipeline \fB\*(VT\fI command -.sp 0.7 -andor: pipeline - andor \fB&&\fI pipeline - andor \fB\*(VT\*(VT\fI pipeline -.sp 0.7 -command-list: andor - command-list \fB;\fI - command-list \fB&\fI - command-list \fB;\fI andor - command-list \fB&\fI andor -.sp 0.7 -input-output: \fB> \fIfile - \fB< \fIfile - \fB\*(AP \fIword - \fB\*(HE \fIword -.sp 0.7 -file: word - \fB&\fI digit - \fB&\fI \(mi -.sp 0.7 -case-part: pattern\fB ) \fIcommand-list\fB ;; -.sp 0.7 -\fIpattern: word - pattern \fB\*(VT\fI word -.sp 0.7 -\fIelse-part: \fBelif \fIcommand-list\fB then\fI command-list else-part\fP - \fBelse \fIcommand-list\fI - empty -.sp 0.7 -empty: -.sp 0.7 -word: \fRa sequence of non-blank characters\fI -.sp 0.7 -name: \fRa sequence of letters, digits or underscores starting with a letter\fI -.sp 0.7 -digit: \fB0 1 2 3 4 5 6 7 8 9\fP -.DE -.LP -.bp -.SH -Appendix\ B\ -\ Meta-characters\ and\ Reserved\ Words -.LP -a) syntactic -.RS -.IP \fB\*(VT\fR 6 -pipe symbol -.IP \fB&&\fR 6 -`andf' symbol -.IP \fB\*(VT\*(VT\fR 6 -`orf' symbol -.IP \fB;\fP 8 -command separator -.IP \fB;;\fP 8 -case delimiter -.IP \fB&\fP 8 -background commands -.IP \fB(\ )\fP 8 -command grouping -.IP \fB<\fP 8 -input redirection -.IP \fB\*(HE\fP 8 -input from a here document -.IP \fB>\fP 8 -output creation -.IP \fB\*(AP\fP 8 -output append -.sp 2 -.RE -.LP -b) patterns -.RS -.IP \fB\*(ST\fP 8 -match any character(s) including none -.IP \fB?\fP 8 -match any single character -.IP \fB[...]\fP 8 -match any of the enclosed characters -.sp 2 -.RE -.LP -c) substitution -.RS -.IP \fB${...}\fP 8 -substitute shell variable -.IP \fB$(...)\fP 8 -substitute command output -.IP \fB\`...\`\fP 8 -substitute command output -.IP \fB$((...))\fP 8 -substitute arithmetic expression -.sp 2 -.RE -.LP -d) quoting -.RS -.IP \fB\e\fP 8 -quote the next character -.IP \fB\'...\'\fP 8 -quote the enclosed characters except for \' -.IP \fB"\&..."\fP 8 -quote the enclosed characters except -for \fB$ \` \e "\fP -.sp 2 -.RE -.LP -e) reserved words -.DS -.ft B -if then else elif fi -case in esac -for while until do done -! { } -.ft -.DE diff --git a/bin/sh/alias.c b/bin/sh/alias.c deleted file mode 100644 index 669a5de0f..000000000 --- a/bin/sh/alias.c +++ /dev/null @@ -1,275 +0,0 @@ -/* $NetBSD: alias.c,v 1.15 2014/06/18 18:17:30 christos Exp $ */ - -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: alias.c,v 1.15 2014/06/18 18:17:30 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include "shell.h" -#include "input.h" -#include "output.h" -#include "error.h" -#include "memalloc.h" -#include "mystring.h" -#include "alias.h" -#include "options.h" /* XXX for argptr (should remove?) */ -#include "builtins.h" -#include "var.h" - -#define ATABSIZE 39 - -struct alias *atab[ATABSIZE]; - -STATIC void setalias(char *, char *); -STATIC int unalias(char *); -STATIC struct alias **hashalias(const char *); - -STATIC -void -setalias(char *name, char *val) -{ - struct alias *ap, **app; - - app = hashalias(name); - for (ap = *app; ap; ap = ap->next) { - if (equal(name, ap->name)) { - INTOFF; - ckfree(ap->val); - ap->val = savestr(val); - INTON; - return; - } - } - /* not found */ - INTOFF; - ap = ckmalloc(sizeof (struct alias)); - ap->name = savestr(name); - ap->flag = 0; - /* - * XXX - HACK: in order that the parser will not finish reading the - * alias value off the input before processing the next alias, we - * dummy up an extra space at the end of the alias. This is a crock - * and should be re-thought. The idea (if you feel inclined to help) - * is to avoid alias recursions. The mechanism used is: when - * expanding an alias, the value of the alias is pushed back on the - * input as a string and a pointer to the alias is stored with the - * string. The alias is marked as being in use. When the input - * routine finishes reading the string, it markes the alias not - * in use. The problem is synchronization with the parser. Since - * it reads ahead, the alias is marked not in use before the - * resulting token(s) is next checked for further alias sub. The - * H A C K is that we add a little fluff after the alias value - * so that the string will not be exhausted. This is a good - * idea ------- ***NOT*** - */ -#ifdef notyet - ap->val = savestr(val); -#else /* hack */ - { - int len = strlen(val); - ap->val = ckmalloc(len + 2); - memcpy(ap->val, val, len); - ap->val[len] = ' '; /* fluff */ - ap->val[len+1] = '\0'; - } -#endif - ap->next = *app; - *app = ap; - INTON; -} - -STATIC int -unalias(char *name) -{ - struct alias *ap, **app; - - app = hashalias(name); - - for (ap = *app; ap; app = &(ap->next), ap = ap->next) { - if (equal(name, ap->name)) { - /* - * if the alias is currently in use (i.e. its - * buffer is being used by the input routine) we - * just null out the name instead of freeing it. - * We could clear it out later, but this situation - * is so rare that it hardly seems worth it. - */ - if (ap->flag & ALIASINUSE) - *ap->name = '\0'; - else { - INTOFF; - *app = ap->next; - ckfree(ap->name); - ckfree(ap->val); - ckfree(ap); - INTON; - } - return (0); - } - } - - return (1); -} - -#ifdef mkinit -MKINIT void rmaliases(void); - -SHELLPROC { - rmaliases(); -} -#endif - -void -rmaliases(void) -{ - struct alias *ap, *tmp; - int i; - - INTOFF; - for (i = 0; i < ATABSIZE; i++) { - ap = atab[i]; - atab[i] = NULL; - while (ap) { - ckfree(ap->name); - ckfree(ap->val); - tmp = ap; - ap = ap->next; - ckfree(tmp); - } - } - INTON; -} - -struct alias * -lookupalias(const char *name, int check) -{ - struct alias *ap = *hashalias(name); - - for (; ap; ap = ap->next) { - if (equal(name, ap->name)) { - if (check && (ap->flag & ALIASINUSE)) - return (NULL); - return (ap); - } - } - - return (NULL); -} - -const char * -alias_text(void *dummy __unused, const char *name) -{ - struct alias *ap; - - ap = lookupalias(name, 0); - if (ap == NULL) - return NULL; - return ap->val; -} - -/* - * TODO - sort output - */ -int -aliascmd(int argc, char **argv) -{ - char *n, *v; - int ret = 0; - struct alias *ap; - - if (argc == 1) { - int i; - - for (i = 0; i < ATABSIZE; i++) - for (ap = atab[i]; ap; ap = ap->next) { - if (*ap->name != '\0') { - out1fmt("alias %s=", ap->name); - print_quoted(ap->val); - out1c('\n'); - } - } - return (0); - } - while ((n = *++argv) != NULL) { - if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */ - if ((ap = lookupalias(n, 0)) == NULL) { - outfmt(out2, "alias: %s not found\n", n); - ret = 1; - } else { - out1fmt("alias %s=", n); - print_quoted(ap->val); - out1c('\n'); - } - } else { - *v++ = '\0'; - setalias(n, v); - } - } - - return (ret); -} - -int -unaliascmd(int argc, char **argv) -{ - int i; - - while ((i = nextopt("a")) != '\0') { - if (i == 'a') { - rmaliases(); - return (0); - } - } - for (i = 0; *argptr; argptr++) - i = unalias(*argptr); - - return (i); -} - -STATIC struct alias ** -hashalias(const char *p) -{ - unsigned int hashval; - - hashval = *p << 4; - while (*p) - hashval+= *p++; - return &atab[hashval % ATABSIZE]; -} diff --git a/bin/sh/alias.h b/bin/sh/alias.h deleted file mode 100644 index 625899890..000000000 --- a/bin/sh/alias.h +++ /dev/null @@ -1,48 +0,0 @@ -/* $NetBSD: alias.h,v 1.8 2014/06/18 18:17:30 christos Exp $ */ - -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)alias.h 8.2 (Berkeley) 5/4/95 - */ - -#define ALIASINUSE 1 - -struct alias { - struct alias *next; - char *name; - char *val; - int flag; -}; - -struct alias *lookupalias(const char *, int); -const char *alias_text(void *, const char *); -void rmaliases(void); diff --git a/bin/sh/arith.y b/bin/sh/arith.y deleted file mode 100644 index 4fbfa1837..000000000 --- a/bin/sh/arith.y +++ /dev/null @@ -1,206 +0,0 @@ -%{ -/* $NetBSD: arith.y,v 1.22 2012/03/20 18:42:29 matt Exp $ */ - -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: arith.y,v 1.22 2012/03/20 18:42:29 matt Exp $"); -#endif -#endif /* not lint */ - -#include -#include "expand.h" -#include "builtins.h" -#include "shell.h" -#include "error.h" -#include "output.h" -#include "memalloc.h" - -typedef intmax_t YYSTYPE; -#define YYSTYPE YYSTYPE - -intmax_t arith_result; -const char *arith_buf, *arith_startbuf; - -__dead static void yyerror(const char *); -#ifdef TESTARITH -int main(int , char *[]); -int error(char *); -#endif - -%} -%token ARITH_NUM ARITH_LPAREN ARITH_RPAREN - -%left ARITH_OR -%left ARITH_AND -%left ARITH_BOR -%left ARITH_BXOR -%left ARITH_BAND -%left ARITH_EQ ARITH_NE -%left ARITH_LT ARITH_GT ARITH_GE ARITH_LE -%left ARITH_LSHIFT ARITH_RSHIFT -%left ARITH_ADD ARITH_SUB -%left ARITH_MUL ARITH_DIV ARITH_REM -%left ARITH_UNARYMINUS ARITH_UNARYPLUS ARITH_NOT ARITH_BNOT -%% - -exp: expr { - /* - * yyparse() returns int, so we have to save - * the desired result elsewhere. - */ - arith_result = $1; - } - ; - - -expr: ARITH_LPAREN expr ARITH_RPAREN { $$ = $2; } - | expr ARITH_OR expr { $$ = $1 ? $1 : $3 ? $3 : 0; } - | expr ARITH_AND expr { $$ = $1 ? ( $3 ? $3 : 0 ) : 0; } - | expr ARITH_BOR expr { $$ = $1 | $3; } - | expr ARITH_BXOR expr { $$ = $1 ^ $3; } - | expr ARITH_BAND expr { $$ = $1 & $3; } - | expr ARITH_EQ expr { $$ = $1 == $3; } - | expr ARITH_GT expr { $$ = $1 > $3; } - | expr ARITH_GE expr { $$ = $1 >= $3; } - | expr ARITH_LT expr { $$ = $1 < $3; } - | expr ARITH_LE expr { $$ = $1 <= $3; } - | expr ARITH_NE expr { $$ = $1 != $3; } - | expr ARITH_LSHIFT expr { $$ = $1 << $3; } - | expr ARITH_RSHIFT expr { $$ = $1 >> $3; } - | expr ARITH_ADD expr { $$ = $1 + $3; } - | expr ARITH_SUB expr { $$ = $1 - $3; } - | expr ARITH_MUL expr { $$ = $1 * $3; } - | expr ARITH_DIV expr { - if ($3 == 0) - yyerror("division by zero"); - $$ = $1 / $3; - } - | expr ARITH_REM expr { - if ($3 == 0) - yyerror("division by zero"); - $$ = $1 % $3; - } - | ARITH_NOT expr { $$ = !($2); } - | ARITH_BNOT expr { $$ = ~($2); } - | ARITH_SUB expr %prec ARITH_UNARYMINUS { $$ = -($2); } - | ARITH_ADD expr %prec ARITH_UNARYPLUS { $$ = $2; } - | ARITH_NUM - ; -%% -intmax_t -arith(const char *s) -{ - intmax_t result; - - arith_buf = arith_startbuf = s; - - INTOFF; - (void) yyparse(); - result = arith_result; - arith_lex_reset(); /* reprime lex */ - INTON; - - return (result); -} - - -/* - * The exp(1) builtin. - */ -int -expcmd(int argc, char **argv) -{ - const char *p; - char *concat; - char **ap; - intmax_t i; - - if (argc > 1) { - p = argv[1]; - if (argc > 2) { - /* - * concatenate arguments - */ - STARTSTACKSTR(concat); - ap = argv + 2; - for (;;) { - while (*p) - STPUTC(*p++, concat); - if ((p = *ap++) == NULL) - break; - STPUTC(' ', concat); - } - STPUTC('\0', concat); - p = grabstackstr(concat); - } - } else - p = ""; - - (void)arith(p); - i = arith_result; - - out1fmt("%"PRIdMAX"\n", i); - return (! i); -} - -/*************************/ -#ifdef TEST_ARITH -#include -main(argc, argv) - char *argv[]; -{ - printf("%"PRIdMAX"\n", exp(argv[1])); -} -error(s) - char *s; -{ - fprintf(stderr, "exp: %s\n", s); - exit(1); -} -#endif - -static void -yyerror(const char *s) -{ - - yyerrok; - yyclearin; - arith_lex_reset(); /* reprime lex */ - error("arithmetic expression: %s: \"%s\"", s, arith_startbuf); - /* NOTREACHED */ -} diff --git a/bin/sh/arith_lex.l b/bin/sh/arith_lex.l deleted file mode 100644 index 6f7a933ab..000000000 --- a/bin/sh/arith_lex.l +++ /dev/null @@ -1,103 +0,0 @@ -%{ -/* $NetBSD: arith_lex.l,v 1.16 2012/03/20 18:42:29 matt Exp $ */ - -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: arith_lex.l,v 1.16 2012/03/20 18:42:29 matt Exp $"); -#endif -#endif /* not lint */ - -#include -#include "arith.h" -#include "error.h" -#include "expand.h" -#include "var.h" - -extern intmax_t yylval; -extern const char *arith_buf, *arith_startbuf; -#undef YY_INPUT -#define YY_INPUT(buf,result,max) \ - result = (*buf = *arith_buf++) ? 1 : YY_NULL; -%} - -%option nounput noinput - -%% -[ \t\n] { ; } -0x[0-9a-fA-F]+ { yylval = strtoimax(yytext, 0, 0); return(ARITH_NUM); } -0[0-7]* { yylval = strtoimax(yytext, 0, 0); return(ARITH_NUM); } -[1-9][0-9]* { yylval = strtoimax(yytext, 0, 0); return(ARITH_NUM); } -[A-Za-z_][A-Za-z_0-9]* { char *v = lookupvar(yytext); - if (v) { - yylval = strtoimax(v, &v, 0); - if (*v == 0) - return ARITH_NUM; - } - error("arith: syntax error: \"%s\"", arith_startbuf); - } -"(" { return(ARITH_LPAREN); } -")" { return(ARITH_RPAREN); } -"||" { return(ARITH_OR); } -"&&" { return(ARITH_AND); } -"|" { return(ARITH_BOR); } -"^" { return(ARITH_BXOR); } -"&" { return(ARITH_BAND); } -"==" { return(ARITH_EQ); } -"!=" { return(ARITH_NE); } -">" { return(ARITH_GT); } -">=" { return(ARITH_GE); } -"<" { return(ARITH_LT); } -"<=" { return(ARITH_LE); } -"<<" { return(ARITH_LSHIFT); } -">>" { return(ARITH_RSHIFT); } -"*" { return(ARITH_MUL); } -"/" { return(ARITH_DIV); } -"%" { return(ARITH_REM); } -"+" { return(ARITH_ADD); } -"-" { return(ARITH_SUB); } -"~" { return(ARITH_BNOT); } -"!" { return(ARITH_NOT); } -. { error("arith: syntax error: \"%s\"", arith_startbuf); } -%% - -void -arith_lex_reset(void) { -#ifdef YY_NEW_FILE - YY_NEW_FILE; -#endif -} diff --git a/bin/sh/bltin/bltin.h b/bin/sh/bltin/bltin.h deleted file mode 100644 index 5cd90f5ac..000000000 --- a/bin/sh/bltin/bltin.h +++ /dev/null @@ -1,100 +0,0 @@ -/* $NetBSD: bltin.h,v 1.13 2008/10/12 01:40:37 dholland Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)bltin.h 8.1 (Berkeley) 5/31/93 - */ - -/* - * This file is included by programs which are optionally built into the - * shell. - * - * We always define SHELL_BUILTIN, to allow other included headers to - * hide some of their symbols if appropriate. - * - * If SHELL is defined, we try to map the standard UNIX library routines - * to ash routines using defines. - */ - -#define SHELL_BUILTIN -#include "../shell.h" -#include "../mystring.h" -#ifdef SHELL -#include "../output.h" -#include "../error.h" -#undef stdout -#undef stderr -#undef putc -#undef putchar -#undef fileno -#undef ferror -#define FILE struct output -#define stdout out1 -#define stderr out2 -#define _RETURN_INT(x) ((x), 0) /* map from void foo() to int bar() */ -#define fprintf(...) _RETURN_INT(outfmt(__VA_ARGS__)) -#define printf(...) _RETURN_INT(out1fmt(__VA_ARGS__)) -#define putc(c, file) _RETURN_INT(outc(c, file)) -#define putchar(c) _RETURN_INT(out1c(c)) -#define fputs(...) _RETURN_INT(outstr(__VA_ARGS__)) -#define fflush(f) _RETURN_INT(flushout(f)) -#define fileno(f) ((f)->fd) -#define ferror(f) ((f)->flags & OUTPUT_ERR) -#define INITARGS(argv) -#define err sh_err -#define verr sh_verr -#define errx sh_errx -#define verrx sh_verrx -#define warn sh_warn -#define vwarn sh_vwarn -#define warnx sh_warnx -#define vwarnx sh_vwarnx -#define exit sh_exit -#define setprogname(s) -#define getprogname() commandname -#define setlocate(l,s) 0 - -#define getenv(p) bltinlookup((p),0) - -#else /* ! SHELL */ -#undef NULL -#include -#undef main -#define INITARGS(argv) if ((commandname = argv[0]) == NULL) {fputs("Argc is zero\n", stderr); exit(2);} else -#endif /* ! SHELL */ - -pointer stalloc(int); - -int echocmd(int, char **); - - -extern const char *commandname; diff --git a/bin/sh/bltin/echo.1 b/bin/sh/bltin/echo.1 deleted file mode 100644 index 7e71fa336..000000000 --- a/bin/sh/bltin/echo.1 +++ /dev/null @@ -1,109 +0,0 @@ -.\" $NetBSD: echo.1,v 1.13 2003/08/07 09:05:40 agc Exp $ -.\" -.\" Copyright (c) 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" Kenneth Almquist. -.\" Copyright 1989 by Kenneth Almquist -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)echo.1 8.1 (Berkeley) 5/31/93 -.\" -.Dd May 31, 1993 -.Dt ECHO 1 -.Os -.Sh NAME -.Nm echo -.Nd produce message in a shell script -.Sh SYNOPSIS -.Nm -.Op Fl n | Fl e -.Ar args ... -.Sh DESCRIPTION -.Nm -prints its arguments on the standard output, separated by spaces. -Unless the -.Fl n -option is present, a newline is output following the arguments. -The -.Fl e -option causes -.Nm -to treat the escape sequences specially, as described in the following -paragraph. -The -.Fl e -option is the default, and is provided solely for compatibility with -other systems. -Only one of the options -.Fl n -and -.Fl e -may be given. -.Pp -If any of the following sequences of characters is encountered during -output, the sequence is not output. Instead, the specified action is -performed: -.Bl -tag -width indent -.It Li \eb -A backspace character is output. -.It Li \ec -Subsequent output is suppressed. This is normally used at the end of the -last argument to suppress the trailing newline that -.Nm -would otherwise output. -.It Li \ef -Output a form feed. -.It Li \en -Output a newline character. -.It Li \er -Output a carriage return. -.It Li \et -Output a (horizontal) tab character. -.It Li \ev -Output a vertical tab. -.It Li \e0 Ns Ar digits -Output the character whose value is given by zero to three digits. -If there are zero digits, a nul character is output. -.It Li \e\e -Output a backslash. -.El -.Sh HINTS -Remember that backslash is special to the shell and needs to be escaped. -To output a message to standard error, say -.Pp -.D1 echo message \*[Gt]\*[Am]2 -.Sh BUGS -The octal character escape mechanism -.Pq Li \e0 Ns Ar digits -differs from the -C language mechanism. -.Pp -There is no way to force -.Nm -to treat its arguments literally, rather than interpreting them as -options and escape sequences. diff --git a/bin/sh/bltin/echo.c b/bin/sh/bltin/echo.c deleted file mode 100644 index 440e01bcd..000000000 --- a/bin/sh/bltin/echo.c +++ /dev/null @@ -1,122 +0,0 @@ -/* $NetBSD: echo.c,v 1.14 2008/10/12 01:40:37 dholland Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)echo.c 8.1 (Berkeley) 5/31/93 - */ - -/* - * Echo command. - * - * echo is steeped in tradition - several of them! - * netbsd has supported 'echo [-n | -e] args' in spite of -e not being - * documented anywhere. - * Posix requires that -n be supported, output from strings containing - * \ is implementation defined - * The Single Unix Spec requires that \ escapes be treated as if -e - * were set, but that -n not be treated as an option. - * (ksh supports 'echo [-eEn] args', but not -- so that it is actually - * impossible to actually output '-n') - * - * It is suggested that 'printf "%b" "string"' be used to get \ sequences - * expanded. printf is now a builtin of netbsd's sh and csh. - */ - -#include -__RCSID("$NetBSD: echo.c,v 1.14 2008/10/12 01:40:37 dholland Exp $"); - -#define main echocmd - -#include "bltin.h" - -int -main(int argc, char **argv) -{ - char **ap; - char *p; - char c; - int count; - int nflag = 0; - int eflag = 0; - - ap = argv; - if (argc) - ap++; - - if ((p = *ap) != NULL) { - if (equal(p, "-n")) { - nflag = 1; - ap++; - } else if (equal(p, "-e")) { - eflag = 1; - ap++; - } - } - - while ((p = *ap++) != NULL) { - while ((c = *p++) != '\0') { - if (c == '\\' && eflag) { - switch (*p++) { - case 'a': c = '\a'; break; /* bell */ - case 'b': c = '\b'; break; - case 'c': return 0; /* exit */ - case 'e': c = 033; break; /* escape */ - case 'f': c = '\f'; break; - case 'n': c = '\n'; break; - case 'r': c = '\r'; break; - case 't': c = '\t'; break; - case 'v': c = '\v'; break; - case '\\': break; /* c = '\\' */ - case '0': - c = 0; - count = 3; - while (--count >= 0 && (unsigned)(*p - '0') < 8) - c = (c << 3) + (*p++ - '0'); - break; - default: - /* Output the '/' and char following */ - p--; - break; - } - } - putchar(c); - } - if (*ap) - putchar(' '); - } - if (! nflag) - putchar('\n'); - fflush(stdout); - if (ferror(stdout)) - return 1; - return 0; -} diff --git a/bin/sh/builtins.def b/bin/sh/builtins.def deleted file mode 100644 index 5f32b4c1d..000000000 --- a/bin/sh/builtins.def +++ /dev/null @@ -1,93 +0,0 @@ -#!/bin/sh - -# $NetBSD: builtins.def,v 1.23 2015/05/10 20:30:54 joerg Exp $ -# -# Copyright (c) 1991, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Kenneth Almquist. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)builtins.def 8.4 (Berkeley) 5/4/95 - -# -# This file lists all the builtin commands. The first column is the name -# of a C routine. -# The -j flag specifies that this command is to be excluded from systems -# without job control. -# The -h flag specifies that this command is to be excluded from systems -# based on the SMALL compile-time symbol. -# The -s flag specifies that this is a posix 'special builtin' command. -# The -u flag specifies that this is a posix 'standard utility'. -# The rest of the line specifies the command name or names used to run -# the command. - -bltincmd -u command -bgcmd -j -u bg -breakcmd -s break -s continue -cdcmd -u cd chdir -dotcmd -s . -echocmd echo -evalcmd -s eval -execcmd -s exec -exitcmd -s exit -expcmd exp let -exportcmd -s export -s readonly -falsecmd -u false -histcmd -h -u fc -inputrc inputrc -fgcmd -j -u fg -fgcmd_percent -j -u % -getoptscmd -u getopts -hashcmd hash -jobidcmd jobid -jobscmd -u jobs -localcmd local -#ifndef TINY -printfcmd printf -#endif -pwdcmd -u pwd -readcmd -u read -returncmd -s return -setcmd -s set -setvarcmd setvar -shiftcmd -s shift -timescmd -s times -trapcmd -s trap -truecmd -s : -u true -typecmd type -umaskcmd -u umask -unaliascmd -u unalias -unsetcmd -s unset -waitcmd -u wait -aliascmd -u alias -ulimitcmd ulimit -testcmd test [ -killcmd -u kill # mandated by posix for 'kill %job' -wordexpcmd wordexp -#newgrp -u newgrp # optional command in posix - -#exprcmd expr diff --git a/bin/sh/cd.c b/bin/sh/cd.c deleted file mode 100644 index 829570825..000000000 --- a/bin/sh/cd.c +++ /dev/null @@ -1,464 +0,0 @@ -/* $NetBSD: cd.c,v 1.44 2011/08/31 16:24:54 plunky Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: cd.c,v 1.44 2011/08/31 16:24:54 plunky Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include - -/* - * The cd and pwd commands. - */ - -#include "shell.h" -#include "var.h" -#include "nodes.h" /* for jobs.h */ -#include "jobs.h" -#include "options.h" -#include "builtins.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" -#include "exec.h" -#include "redir.h" -#include "mystring.h" -#include "show.h" -#include "cd.h" - -STATIC int docd(const char *, int); -STATIC char *getcomponent(void); -STATIC void updatepwd(const char *); -STATIC void find_curdir(int noerror); - -char *curdir = NULL; /* current working directory */ -char *prevdir; /* previous working directory */ -STATIC char *cdcomppath; - -int -cdcmd(int argc, char **argv) -{ - const char *dest; - const char *path, *p; - char *d; - struct stat statb; - int print = cdprint; /* set -cdprint to enable */ - - while (nextopt("P") != '\0') - ; - - /* - * Try (quite hard) to have 'curdir' defined, nothing has set - * it on entry to the shell, but we want 'cd fred; cd -' to work. - */ - getpwd(1); - dest = *argptr; - if (dest == NULL) { - dest = bltinlookup("HOME", 1); - if (dest == NULL) - error("HOME not set"); - } else { - if (argptr[1]) { - /* Do 'ksh' style substitution */ - if (!curdir) - error("PWD not set"); - p = strstr(curdir, dest); - if (!p) - error("bad substitution"); - d = stalloc(strlen(curdir) + strlen(argptr[1]) + 1); - memcpy(d, curdir, p - curdir); - strcpy(d + (p - curdir), argptr[1]); - strcat(d, p + strlen(dest)); - dest = d; - print = 1; - } - } - - if (dest[0] == '-' && dest[1] == '\0') { - dest = prevdir ? prevdir : curdir; - print = 1; - } - if (*dest == '\0') - dest = "."; - p = dest; - if (*p == '.' && *++p == '.') - p++; - if (*p == 0 || *p == '/' || (path = bltinlookup("CDPATH", 1)) == NULL) - path = nullstr; - while ((p = padvance(&path, dest)) != NULL) { - if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) { - if (!print) { - /* - * XXX - rethink - */ - if (p[0] == '.' && p[1] == '/' && p[2] != '\0') - print = strcmp(p + 2, dest); - else - print = strcmp(p, dest); - } - if (docd(p, print) >= 0) - return 0; - - } - } - error("can't cd to %s", dest); - /* NOTREACHED */ -} - - -/* - * Actually do the chdir. In an interactive shell, print the - * directory name if "print" is nonzero. - */ - -STATIC int -docd(const char *dest, int print) -{ - char *p; - char *q; - char *component; - struct stat statb; - int first; - int badstat; - - TRACE(("docd(\"%s\", %d) called\n", dest, print)); - - /* - * Check each component of the path. If we find a symlink or - * something we can't stat, clear curdir to force a getcwd() - * next time we get the value of the current directory. - */ - badstat = 0; - cdcomppath = stalloc(strlen(dest) + 1); - scopy(dest, cdcomppath); - STARTSTACKSTR(p); - if (*dest == '/') { - STPUTC('/', p); - cdcomppath++; - } - first = 1; - while ((q = getcomponent()) != NULL) { - if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0')) - continue; - if (! first) - STPUTC('/', p); - first = 0; - component = q; - while (*q) - STPUTC(*q++, p); - if (equal(component, "..")) - continue; - STACKSTRNUL(p); - if ((lstat(stackblock(), &statb) < 0) - || (S_ISLNK(statb.st_mode))) { - /* print = 1; */ - badstat = 1; - break; - } - } - - INTOFF; - if (chdir(dest) < 0) { - INTON; - return -1; - } - updatepwd(badstat ? NULL : dest); - INTON; - if (print && iflag == 1 && curdir) - out1fmt("%s\n", curdir); - return 0; -} - - -/* - * Get the next component of the path name pointed to by cdcomppath. - * This routine overwrites the string pointed to by cdcomppath. - */ - -STATIC char * -getcomponent(void) -{ - char *p; - char *start; - - if ((p = cdcomppath) == NULL) - return NULL; - start = cdcomppath; - while (*p != '/' && *p != '\0') - p++; - if (*p == '\0') { - cdcomppath = NULL; - } else { - *p++ = '\0'; - cdcomppath = p; - } - return start; -} - - - -/* - * Update curdir (the name of the current directory) in response to a - * cd command. We also call hashcd to let the routines in exec.c know - * that the current directory has changed. - */ - -STATIC void -updatepwd(const char *dir) -{ - char *new; - char *p; - - hashcd(); /* update command hash table */ - - /* - * If our argument is NULL, we don't know the current directory - * any more because we traversed a symbolic link or something - * we couldn't stat(). - */ - if (dir == NULL || curdir == NULL) { - if (prevdir) - ckfree(prevdir); - INTOFF; - prevdir = curdir; - curdir = NULL; - getpwd(1); - INTON; - if (curdir) { - setvar("OLDPWD", prevdir, VEXPORT); - setvar("PWD", curdir, VEXPORT); - } else - unsetvar("PWD", 0); - return; - } - cdcomppath = stalloc(strlen(dir) + 1); - scopy(dir, cdcomppath); - STARTSTACKSTR(new); - if (*dir != '/') { - p = curdir; - while (*p) - STPUTC(*p++, new); - if (p[-1] == '/') - STUNPUTC(new); - } - while ((p = getcomponent()) != NULL) { - if (equal(p, "..")) { - while (new > stackblock() && (STUNPUTC(new), *new) != '/'); - } else if (*p != '\0' && ! equal(p, ".")) { - STPUTC('/', new); - while (*p) - STPUTC(*p++, new); - } - } - if (new == stackblock()) - STPUTC('/', new); - STACKSTRNUL(new); - INTOFF; - if (prevdir) - ckfree(prevdir); - prevdir = curdir; - curdir = savestr(stackblock()); - setvar("OLDPWD", prevdir, VEXPORT); - setvar("PWD", curdir, VEXPORT); - INTON; -} - -/* - * Posix says the default should be 'pwd -L' (as below), however - * the 'cd' command (above) does something much nearer to the - * posix 'cd -P' (not the posix default of 'cd -L'). - * If 'cd' is changed to support -P/L then the default here - * needs to be revisited if the historic behaviour is to be kept. - */ - -int -pwdcmd(int argc, char **argv) -{ - int i; - char opt = 'L'; - - while ((i = nextopt("LP")) != '\0') - opt = i; - if (*argptr) - error("unexpected argument"); - - if (opt == 'L') - getpwd(0); - else - find_curdir(0); - - setvar("OLDPWD", prevdir, VEXPORT); - setvar("PWD", curdir, VEXPORT); - out1str(curdir); - out1c('\n'); - return 0; -} - - - -void -initpwd(void) -{ - getpwd(1); - if (curdir) - setvar("PWD", curdir, VEXPORT); - else - sh_warnx("Cannot determine current working directory"); -} - -#define MAXPWD 256 - -/* - * Find out what the current directory is. If we already know the current - * directory, this routine returns immediately. - */ -void -getpwd(int noerror) -{ - char *pwd; - struct stat stdot, stpwd; - static int first = 1; - - if (curdir) - return; - - if (first) { - first = 0; - pwd = getenv("PWD"); - if (pwd && *pwd == '/' && stat(".", &stdot) != -1 && - stat(pwd, &stpwd) != -1 && - stdot.st_dev == stpwd.st_dev && - stdot.st_ino == stpwd.st_ino) { - curdir = savestr(pwd); - return; - } - } - - find_curdir(noerror); - - return; -} - -STATIC void -find_curdir(int noerror) -{ - int i; - char *pwd; - - /* - * Things are a bit complicated here; we could have just used - * getcwd, but traditionally getcwd is implemented using popen - * to /bin/pwd. This creates a problem for us, since we cannot - * keep track of the job if it is being ran behind our backs. - * So we re-implement getcwd(), and we suppress interrupts - * throughout the process. This is not completely safe, since - * the user can still break out of it by killing the pwd program. - * We still try to use getcwd for systems that we know have a - * c implementation of getcwd, that does not open a pipe to - * /bin/pwd. - */ -#if defined(__NetBSD__) || defined(__SVR4) || defined(__minix) - - for (i = MAXPWD;; i *= 2) { - pwd = stalloc(i); - if (getcwd(pwd, i) != NULL) { - curdir = savestr(pwd); - return; - } - stunalloc(pwd); - if (errno == ERANGE) - continue; - if (!noerror) - error("getcwd() failed: %s", strerror(errno)); - return; - } -#else - { - char *p; - int status; - struct job *jp; - int pip[2]; - - pwd = stalloc(MAXPWD); - INTOFF; - if (pipe(pip) < 0) - error("Pipe call failed"); - jp = makejob(NULL, 1); - if (forkshell(jp, NULL, FORK_NOJOB) == 0) { - (void) close(pip[0]); - if (pip[1] != 1) { - close(1); - copyfd(pip[1], 1, 1); - close(pip[1]); - } - (void) execl("/bin/pwd", "pwd", (char *)0); - error("Cannot exec /bin/pwd"); - } - (void) close(pip[1]); - pip[1] = -1; - p = pwd; - while ((i = read(pip[0], p, pwd + MAXPWD - p)) > 0 - || (i == -1 && errno == EINTR)) { - if (i > 0) - p += i; - } - (void) close(pip[0]); - pip[0] = -1; - status = waitforjob(jp); - if (status != 0) - error((char *)0); - if (i < 0 || p == pwd || p[-1] != '\n') { - if (noerror) { - INTON; - return; - } - error("pwd command failed"); - } - p[-1] = '\0'; - INTON; - curdir = savestr(pwd); - return; - } -#endif -} diff --git a/bin/sh/cd.h b/bin/sh/cd.h deleted file mode 100644 index 7600955da..000000000 --- a/bin/sh/cd.h +++ /dev/null @@ -1,34 +0,0 @@ -/* $NetBSD: cd.h,v 1.6 2011/06/18 21:18:46 christos Exp $ */ - -/*- - * Copyright (c) 1995 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -void initpwd(void); -void getpwd(int); diff --git a/bin/sh/error.c b/bin/sh/error.c deleted file mode 100644 index 2ac98b69a..000000000 --- a/bin/sh/error.c +++ /dev/null @@ -1,370 +0,0 @@ -/* $NetBSD: error.c,v 1.38 2012/03/15 02:02:20 joerg Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: error.c,v 1.38 2012/03/15 02:02:20 joerg Exp $"); -#endif -#endif /* not lint */ - -/* - * Errors and exceptions. - */ - -#include -#include -#include -#include -#include -#include - -#include "shell.h" -#include "eval.h" /* for commandname */ -#include "main.h" -#include "options.h" -#include "output.h" -#include "error.h" -#include "show.h" - - -/* - * Code to handle exceptions in C. - */ - -struct jmploc *handler; -int exception; -volatile int suppressint; -volatile int intpending; - - -static void exverror(int, const char *, va_list) __dead; - -/* - * Called to raise an exception. Since C doesn't include exceptions, we - * just do a longjmp to the exception handler. The type of exception is - * stored in the global variable "exception". - */ - -void -exraise(int e) -{ - if (handler == NULL) - abort(); - exception = e; - longjmp(handler->loc, 1); -} - - -/* - * Called from trap.c when a SIGINT is received. (If the user specifies - * that SIGINT is to be trapped or ignored using the trap builtin, then - * this routine is not called.) Suppressint is nonzero when interrupts - * are held using the INTOFF macro. The call to _exit is necessary because - * there is a short period after a fork before the signal handlers are - * set to the appropriate value for the child. (The test for iflag is - * just defensive programming.) - */ - -void -onint(void) -{ - sigset_t nsigset; - - if (suppressint) { - intpending = 1; - return; - } - intpending = 0; - sigemptyset(&nsigset); - sigprocmask(SIG_SETMASK, &nsigset, NULL); - if (rootshell && iflag) - exraise(EXINT); - else { - signal(SIGINT, SIG_DFL); - raise(SIGINT); - } - /* NOTREACHED */ -} - -static __printflike(2, 0) void -exvwarning(int sv_errno, const char *msg, va_list ap) -{ - /* Partially emulate line buffered output so that: - * printf '%d\n' 1 a 2 - * and - * printf '%d %d %d\n' 1 a 2 - * both generate sensible text when stdout and stderr are merged. - */ - if (output.nextc != output.buf && output.nextc[-1] == '\n') - flushout(&output); - if (commandname) - outfmt(&errout, "%s: ", commandname); - else - outfmt(&errout, "%s: ", getprogname()); - if (msg != NULL) { - doformat(&errout, msg, ap); - if (sv_errno >= 0) - outfmt(&errout, ": "); - } - if (sv_errno >= 0) - outfmt(&errout, "%s", strerror(sv_errno)); - out2c('\n'); - flushout(&errout); -} - -/* - * Exverror is called to raise the error exception. If the second argument - * is not NULL then error prints an error message using printf style - * formatting. It then raises the error exception. - */ -static __printflike(2, 0) void -exverror(int cond, const char *msg, va_list ap) -{ - CLEAR_PENDING_INT; - INTOFF; - -#ifdef DEBUG - if (msg) { - TRACE(("exverror(%d, \"", cond)); - TRACEV((msg, ap)); - TRACE(("\") pid=%d\n", getpid())); - } else - TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid())); -#endif - if (msg) - exvwarning(-1, msg, ap); - - flushall(); - exraise(cond); - /* NOTREACHED */ -} - - -void -error(const char *msg, ...) -{ - va_list ap; - - va_start(ap, msg); - exverror(EXERROR, msg, ap); - /* NOTREACHED */ - va_end(ap); -} - - -void -exerror(int cond, const char *msg, ...) -{ - va_list ap; - - va_start(ap, msg); - exverror(cond, msg, ap); - /* NOTREACHED */ - va_end(ap); -} - -/* - * error/warning routines for external builtins - */ - -void -sh_exit(int rval) -{ - exerrno = rval & 255; - exraise(EXEXEC); -} - -void -sh_err(int status, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - exvwarning(errno, fmt, ap); - va_end(ap); - sh_exit(status); -} - -void -sh_verr(int status, const char *fmt, va_list ap) -{ - exvwarning(errno, fmt, ap); - sh_exit(status); -} - -void -sh_errx(int status, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - exvwarning(-1, fmt, ap); - va_end(ap); - sh_exit(status); -} - -void -sh_verrx(int status, const char *fmt, va_list ap) -{ - exvwarning(-1, fmt, ap); - sh_exit(status); -} - -void -sh_warn(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - exvwarning(errno, fmt, ap); - va_end(ap); -} - -void -sh_vwarn(const char *fmt, va_list ap) -{ - exvwarning(errno, fmt, ap); -} - -void -sh_warnx(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - exvwarning(-1, fmt, ap); - va_end(ap); -} - -void -sh_vwarnx(const char *fmt, va_list ap) -{ - exvwarning(-1, fmt, ap); -} - - -/* - * Table of error messages. - */ - -struct errname { - short errcode; /* error number */ - short action; /* operation which encountered the error */ - const char *msg; /* text describing the error */ -}; - - -#define ALL (E_OPEN|E_CREAT|E_EXEC) - -STATIC const struct errname errormsg[] = { - { EINTR, ALL, "interrupted" }, - { EACCES, ALL, "permission denied" }, - { EIO, ALL, "I/O error" }, - { EEXIST, ALL, "file exists" }, - { ENOENT, E_OPEN, "no such file" }, - { ENOENT, E_CREAT,"directory nonexistent" }, - { ENOENT, E_EXEC, "not found" }, - { ENOTDIR, E_OPEN, "no such file" }, - { ENOTDIR, E_CREAT,"directory nonexistent" }, - { ENOTDIR, E_EXEC, "not found" }, - { EISDIR, ALL, "is a directory" }, -#ifdef EMFILE - { EMFILE, ALL, "too many open files" }, -#endif - { ENFILE, ALL, "file table overflow" }, - { ENOSPC, ALL, "file system full" }, -#ifdef EDQUOT - { EDQUOT, ALL, "disk quota exceeded" }, -#endif -#ifdef ENOSR - { ENOSR, ALL, "no streams resources" }, -#endif - { ENXIO, ALL, "no such device or address" }, - { EROFS, ALL, "read-only file system" }, - { ETXTBSY, ALL, "text busy" }, -#ifdef EAGAIN - { EAGAIN, E_EXEC, "not enough memory" }, -#endif - { ENOMEM, ALL, "not enough memory" }, -#ifdef ENOLINK - { ENOLINK, ALL, "remote access failed" }, -#endif -#ifdef EMULTIHOP - { EMULTIHOP, ALL, "remote access failed" }, -#endif -#ifdef ECOMM - { ECOMM, ALL, "remote access failed" }, -#endif -#ifdef ESTALE - { ESTALE, ALL, "remote access failed" }, -#endif -#ifdef ETIMEDOUT - { ETIMEDOUT, ALL, "remote access failed" }, -#endif -#ifdef ELOOP - { ELOOP, ALL, "symbolic link loop" }, -#endif -#ifdef ENAMETOOLONG - { ENAMETOOLONG, ALL, "file name too long" }, -#endif - { E2BIG, E_EXEC, "argument list too long" }, -#ifdef ELIBACC - { ELIBACC, E_EXEC, "shared library missing" }, -#endif - { 0, 0, NULL }, -}; - - -/* - * Return a string describing an error. The returned string may be a - * pointer to a static buffer that will be overwritten on the next call. - * Action describes the operation that got the error. - */ - -const char * -errmsg(int e, int action) -{ - struct errname const *ep; - static char buf[12]; - - for (ep = errormsg ; ep->errcode ; ep++) { - if (ep->errcode == e && (ep->action & action) != 0) - return ep->msg; - } - fmtstr(buf, sizeof buf, "error %d", e); - return buf; -} diff --git a/bin/sh/error.h b/bin/sh/error.h deleted file mode 100644 index b4121b8da..000000000 --- a/bin/sh/error.h +++ /dev/null @@ -1,119 +0,0 @@ -/* $NetBSD: error.h,v 1.19 2012/03/15 02:02:20 joerg Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)error.h 8.2 (Berkeley) 5/4/95 - */ - -#include - -/* - * Types of operations (passed to the errmsg routine). - */ - -#define E_OPEN 01 /* opening a file */ -#define E_CREAT 02 /* creating a file */ -#define E_EXEC 04 /* executing a program */ - - -/* - * We enclose jmp_buf in a structure so that we can declare pointers to - * jump locations. The global variable handler contains the location to - * jump to when an exception occurs, and the global variable exception - * contains a code identifying the exeception. To implement nested - * exception handlers, the user should save the value of handler on entry - * to an inner scope, set handler to point to a jmploc structure for the - * inner scope, and restore handler on exit from the scope. - */ - -#include - -struct jmploc { - jmp_buf loc; -}; - -extern struct jmploc *handler; -extern int exception; -extern int exerrno; /* error for EXEXEC */ - -/* exceptions */ -#define EXINT 0 /* SIGINT received */ -#define EXERROR 1 /* a generic error */ -#define EXSHELLPROC 2 /* execute a shell procedure */ -#define EXEXEC 3 /* command execution failed */ - - -/* - * These macros allow the user to suspend the handling of interrupt signals - * over a period of time. This is similar to SIGHOLD to or sigblock, but - * much more efficient and portable. (But hacking the kernel is so much - * more fun than worrying about efficiency and portability. :-)) - */ - -extern volatile int suppressint; -extern volatile int intpending; - -#define INTOFF suppressint++ -#define INTON { if (--suppressint == 0 && intpending) onint(); } -#define FORCEINTON {suppressint = 0; if (intpending) onint();} -#define CLEAR_PENDING_INT intpending = 0 -#define int_pending() intpending - -#if ! defined(SHELL_BUILTIN) -void exraise(int) __dead; -void onint(void); -void error(const char *, ...) __dead __printflike(1, 2); -void exerror(int, const char *, ...) __dead __printflike(2, 3); -const char *errmsg(int, int); -#endif /* ! SHELL_BUILTIN */ - -void sh_err(int, const char *, ...) __dead __printflike(2, 3); -void sh_verr(int, const char *, va_list) __dead __printflike(2, 0); -void sh_errx(int, const char *, ...) __dead __printflike(2, 3); -void sh_verrx(int, const char *, va_list) __dead __printflike(2, 0); -void sh_warn(const char *, ...) __printflike(1, 2); -void sh_vwarn(const char *, va_list) __printflike(1, 0); -void sh_warnx(const char *, ...) __printflike(1, 2); -void sh_vwarnx(const char *, va_list) __printflike(1, 0); - -void sh_exit(int) __dead; - - -/* - * BSD setjmp saves the signal mask, which violates ANSI C and takes time, - * so we use _setjmp instead. - */ - -#if defined(BSD) && !defined(__SVR4) -#define setjmp(jmploc) _setjmp(jmploc) -#define longjmp(jmploc, val) _longjmp(jmploc, val) -#endif diff --git a/bin/sh/eval.c b/bin/sh/eval.c deleted file mode 100644 index 7299a5b84..000000000 --- a/bin/sh/eval.c +++ /dev/null @@ -1,1366 +0,0 @@ -/* $NetBSD: eval.c,v 1.110 2015/01/02 19:56:20 christos Exp $ */ - -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; -#else -__RCSID("$NetBSD: eval.c,v 1.110 2015/01/02 19:56:20 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Evaluate a command. - */ - -#include "shell.h" -#include "nodes.h" -#include "syntax.h" -#include "expand.h" -#include "parser.h" -#include "jobs.h" -#include "eval.h" -#include "builtins.h" -#include "options.h" -#include "exec.h" -#include "redir.h" -#include "input.h" -#include "output.h" -#include "trap.h" -#include "var.h" -#include "memalloc.h" -#include "error.h" -#include "show.h" -#include "mystring.h" -#include "main.h" -#ifndef SMALL -#include "myhistedit.h" -#endif - - -/* flags in argument to evaltree */ -#define EV_EXIT 01 /* exit after evaluating tree */ -#define EV_TESTED 02 /* exit status is checked; ignore -e flag */ -#define EV_BACKCMD 04 /* command executing within back quotes */ - -STATIC enum skipstate evalskip; /* != SKIPNONE if we are skipping commands */ -STATIC int skipcount; /* number of levels to skip */ -STATIC int loopnest; /* current loop nesting level */ -STATIC int funcnest; /* depth of function calls */ -STATIC int builtin_flags; /* evalcommand flags for builtins */ -/* - * Base function nesting level inside a dot command. Set to 0 initially - * and to (funcnest + 1) before every dot command to enable - * 1) detection of being in a file sourced by a dot command and - * 2) counting of function nesting in that file for the implementation - * of the return command. - * The value is reset to its previous value after the dot command. - */ -STATIC int dot_funcnest; - - -const char *commandname; -struct strlist *cmdenviron; -int exitstatus; /* exit status of last command */ -int back_exitstatus; /* exit status of backquoted command */ - - -STATIC void evalloop(union node *, int); -STATIC void evalfor(union node *, int); -STATIC void evalcase(union node *, int); -STATIC void evalsubshell(union node *, int); -STATIC void expredir(union node *); -STATIC void evalpipe(union node *); -STATIC void evalcommand(union node *, int, struct backcmd *); -STATIC void prehash(union node *); - -STATIC char *find_dot_file(char *); - -/* - * Called to reset things after an exception. - */ - -#ifdef mkinit -INCLUDE "eval.h" - -RESET { - reset_eval(); -} - -SHELLPROC { - exitstatus = 0; -} -#endif - -void -reset_eval(void) -{ - evalskip = SKIPNONE; - dot_funcnest = 0; - loopnest = 0; - funcnest = 0; -} - -static int -sh_pipe(int fds[2]) -{ - int nfd; - - if (pipe(fds)) - return -1; - - if (fds[0] < 3) { - nfd = fcntl(fds[0], F_DUPFD, 3); - if (nfd != -1) { - close(fds[0]); - fds[0] = nfd; - } - } - - if (fds[1] < 3) { - nfd = fcntl(fds[1], F_DUPFD, 3); - if (nfd != -1) { - close(fds[1]); - fds[1] = nfd; - } - } - return 0; -} - - -/* - * The eval commmand. - */ - -int -evalcmd(int argc, char **argv) -{ - char *p; - char *concat; - char **ap; - - if (argc > 1) { - p = argv[1]; - if (argc > 2) { - STARTSTACKSTR(concat); - ap = argv + 2; - for (;;) { - while (*p) - STPUTC(*p++, concat); - if ((p = *ap++) == NULL) - break; - STPUTC(' ', concat); - } - STPUTC('\0', concat); - p = grabstackstr(concat); - } - evalstring(p, builtin_flags & EV_TESTED); - } - return exitstatus; -} - - -/* - * Execute a command or commands contained in a string. - */ - -void -evalstring(char *s, int flag) -{ - union node *n; - struct stackmark smark; - - setstackmark(&smark); - setinputstring(s, 1); - - while ((n = parsecmd(0)) != NEOF) { - evaltree(n, flag); - popstackmark(&smark); - } - popfile(); - popstackmark(&smark); -} - - - -/* - * Evaluate a parse tree. The value is left in the global variable - * exitstatus. - */ - -void -evaltree(union node *n, int flags) -{ - bool do_etest; - - do_etest = false; - if (n == NULL) { - TRACE(("evaltree(NULL) called\n")); - exitstatus = 0; - goto out; - } -#ifndef SMALL - displayhist = 1; /* show history substitutions done with fc */ -#endif - TRACE(("pid %d, evaltree(%p: %d, %d) called\n", - getpid(), n, n->type, flags)); - switch (n->type) { - case NSEMI: - evaltree(n->nbinary.ch1, flags & EV_TESTED); - if (evalskip) - goto out; - evaltree(n->nbinary.ch2, flags); - break; - case NAND: - evaltree(n->nbinary.ch1, EV_TESTED); - if (evalskip || exitstatus != 0) - goto out; - evaltree(n->nbinary.ch2, flags); - break; - case NOR: - evaltree(n->nbinary.ch1, EV_TESTED); - if (evalskip || exitstatus == 0) - goto out; - evaltree(n->nbinary.ch2, flags); - break; - case NREDIR: - expredir(n->nredir.redirect); - redirect(n->nredir.redirect, REDIR_PUSH); - evaltree(n->nredir.n, flags); - popredir(); - break; - case NSUBSHELL: - evalsubshell(n, flags); - do_etest = !(flags & EV_TESTED); - break; - case NBACKGND: - evalsubshell(n, flags); - break; - case NIF: { - evaltree(n->nif.test, EV_TESTED); - if (evalskip) - goto out; - if (exitstatus == 0) - evaltree(n->nif.ifpart, flags); - else if (n->nif.elsepart) - evaltree(n->nif.elsepart, flags); - else - exitstatus = 0; - break; - } - case NWHILE: - case NUNTIL: - evalloop(n, flags); - break; - case NFOR: - evalfor(n, flags); - break; - case NCASE: - evalcase(n, flags); - break; - case NDEFUN: - defun(n->narg.text, n->narg.next); - exitstatus = 0; - break; - case NNOT: - evaltree(n->nnot.com, EV_TESTED); - exitstatus = !exitstatus; - break; - case NPIPE: - evalpipe(n); - do_etest = !(flags & EV_TESTED); - break; - case NCMD: - evalcommand(n, flags, NULL); - do_etest = !(flags & EV_TESTED); - break; - default: - out1fmt("Node type = %d\n", n->type); - flushout(&output); - break; - } -out: - if (pendingsigs) - dotrap(); - if ((flags & EV_EXIT) != 0 || (eflag && exitstatus != 0 && do_etest)) - exitshell(exitstatus); -} - - -STATIC void -evalloop(union node *n, int flags) -{ - int status; - - loopnest++; - status = 0; - for (;;) { - evaltree(n->nbinary.ch1, EV_TESTED); - if (evalskip) { -skipping: if (evalskip == SKIPCONT && --skipcount <= 0) { - evalskip = SKIPNONE; - continue; - } - if (evalskip == SKIPBREAK && --skipcount <= 0) - evalskip = SKIPNONE; - break; - } - if (n->type == NWHILE) { - if (exitstatus != 0) - break; - } else { - if (exitstatus == 0) - break; - } - evaltree(n->nbinary.ch2, flags & EV_TESTED); - status = exitstatus; - if (evalskip) - goto skipping; - } - loopnest--; - exitstatus = status; -} - - - -STATIC void -evalfor(union node *n, int flags) -{ - struct arglist arglist; - union node *argp; - struct strlist *sp; - struct stackmark smark; - int status = 0; - - setstackmark(&smark); - arglist.lastp = &arglist.list; - for (argp = n->nfor.args ; argp ; argp = argp->narg.next) { - expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); - if (evalskip) - goto out; - } - *arglist.lastp = NULL; - - loopnest++; - for (sp = arglist.list ; sp ; sp = sp->next) { - setvar(n->nfor.var, sp->text, 0); - evaltree(n->nfor.body, flags & EV_TESTED); - status = exitstatus; - if (evalskip) { - if (evalskip == SKIPCONT && --skipcount <= 0) { - evalskip = SKIPNONE; - continue; - } - if (evalskip == SKIPBREAK && --skipcount <= 0) - evalskip = SKIPNONE; - break; - } - } - loopnest--; - exitstatus = status; -out: - popstackmark(&smark); -} - - - -STATIC void -evalcase(union node *n, int flags) -{ - union node *cp; - union node *patp; - struct arglist arglist; - struct stackmark smark; - int status = 0; - - setstackmark(&smark); - arglist.lastp = &arglist.list; - expandarg(n->ncase.expr, &arglist, EXP_TILDE); - for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) { - for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) { - if (casematch(patp, arglist.list->text)) { - if (evalskip == 0) { - evaltree(cp->nclist.body, flags); - status = exitstatus; - } - goto out; - } - } - } -out: - exitstatus = status; - popstackmark(&smark); -} - - - -/* - * Kick off a subshell to evaluate a tree. - */ - -STATIC void -evalsubshell(union node *n, int flags) -{ - struct job *jp; - int backgnd = (n->type == NBACKGND); - - expredir(n->nredir.redirect); - INTOFF; - jp = makejob(n, 1); - if (forkshell(jp, n, backgnd ? FORK_BG : FORK_FG) == 0) { - INTON; - if (backgnd) - flags &=~ EV_TESTED; - redirect(n->nredir.redirect, 0); - /* never returns */ - evaltree(n->nredir.n, flags | EV_EXIT); - } - if (! backgnd) - exitstatus = waitforjob(jp); - INTON; -} - - - -/* - * Compute the names of the files in a redirection list. - */ - -STATIC void -expredir(union node *n) -{ - union node *redir; - - for (redir = n ; redir ; redir = redir->nfile.next) { - struct arglist fn; - fn.lastp = &fn.list; - switch (redir->type) { - case NFROMTO: - case NFROM: - case NTO: - case NCLOBBER: - case NAPPEND: - expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); - redir->nfile.expfname = fn.list->text; - break; - case NFROMFD: - case NTOFD: - if (redir->ndup.vname) { - expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE); - fixredir(redir, fn.list->text, 1); - } - break; - } - } -} - - - -/* - * Evaluate a pipeline. All the processes in the pipeline are children - * of the process creating the pipeline. (This differs from some versions - * of the shell, which make the last process in a pipeline the parent - * of all the rest.) - */ - -STATIC void -evalpipe(union node *n) -{ - struct job *jp; - struct nodelist *lp; - int pipelen; - int prevfd; - int pip[2]; - - TRACE(("evalpipe(0x%lx) called\n", (long)n)); - pipelen = 0; - for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) - pipelen++; - INTOFF; - jp = makejob(n, pipelen); - prevfd = -1; - for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { - prehash(lp->n); - pip[1] = -1; - if (lp->next) { - if (sh_pipe(pip) < 0) { - if (prevfd >= 0) - close(prevfd); - error("Pipe call failed"); - } - } - if (forkshell(jp, lp->n, n->npipe.backgnd ? FORK_BG : FORK_FG) == 0) { - INTON; - if (prevfd > 0) { - close(0); - copyfd(prevfd, 0, 1); - close(prevfd); - } - if (pip[1] >= 0) { - close(pip[0]); - if (pip[1] != 1) { - close(1); - copyfd(pip[1], 1, 1); - close(pip[1]); - } - } - evaltree(lp->n, EV_EXIT); - } - if (prevfd >= 0) - close(prevfd); - prevfd = pip[0]; - close(pip[1]); - } - if (n->npipe.backgnd == 0) { - exitstatus = waitforjob(jp); - TRACE(("evalpipe: job done exit status %d\n", exitstatus)); - } - INTON; -} - - - -/* - * Execute a command inside back quotes. If it's a builtin command, we - * want to save its output in a block obtained from malloc. Otherwise - * we fork off a subprocess and get the output of the command via a pipe. - * Should be called with interrupts off. - */ - -void -evalbackcmd(union node *n, struct backcmd *result) -{ - int pip[2]; - struct job *jp; - struct stackmark smark; /* unnecessary */ - - setstackmark(&smark); - result->fd = -1; - result->buf = NULL; - result->nleft = 0; - result->jp = NULL; - if (n == NULL) { - goto out; - } -#ifdef notyet - /* - * For now we disable executing builtins in the same - * context as the shell, because we are not keeping - * enough state to recover from changes that are - * supposed only to affect subshells. eg. echo "`cd /`" - */ - if (n->type == NCMD) { - exitstatus = oexitstatus; - evalcommand(n, EV_BACKCMD, result); - } else -#endif - { - INTOFF; - if (sh_pipe(pip) < 0) - error("Pipe call failed"); - jp = makejob(n, 1); - if (forkshell(jp, n, FORK_NOJOB) == 0) { - FORCEINTON; - close(pip[0]); - if (pip[1] != 1) { - close(1); - copyfd(pip[1], 1, 1); - close(pip[1]); - } - eflag = 0; - evaltree(n, EV_EXIT); - /* NOTREACHED */ - } - close(pip[1]); - result->fd = pip[0]; - result->jp = jp; - INTON; - } -out: - popstackmark(&smark); - TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n", - result->fd, result->buf, result->nleft, result->jp)); -} - -static const char * -syspath(void) -{ - static char *sys_path = NULL; - static int mib[] = {CTL_USER, USER_CS_PATH}; - static char def_path[] = "PATH=/usr/bin:/bin:/usr/sbin:/sbin"; - size_t len; - - if (sys_path == NULL) { - if (sysctl(mib, 2, 0, &len, 0, 0) != -1 && - (sys_path = ckmalloc(len + 5)) != NULL && - sysctl(mib, 2, sys_path + 5, &len, 0, 0) != -1) { - memcpy(sys_path, "PATH=", 5); - } else { - ckfree(sys_path); - /* something to keep things happy */ - sys_path = def_path; - } - } - return sys_path; -} - -static int -parse_command_args(int argc, char **argv, int *use_syspath) -{ - int sv_argc = argc; - char *cp, c; - - *use_syspath = 0; - - for (;;) { - argv++; - if (--argc == 0) - break; - cp = *argv; - if (*cp++ != '-') - break; - if (*cp == '-' && cp[1] == 0) { - argv++; - argc--; - break; - } - while ((c = *cp++)) { - switch (c) { - case 'p': - *use_syspath = 1; - break; - default: - /* run 'typecmd' for other options */ - return 0; - } - } - } - return sv_argc - argc; -} - -int vforked = 0; -extern char *trap[]; - -/* - * Execute a simple command. - */ - -STATIC void -evalcommand(union node *cmd, int flgs, struct backcmd *backcmd) -{ - struct stackmark smark; - union node *argp; - struct arglist arglist; - struct arglist varlist; - volatile int flags = flgs; - char ** volatile argv; - volatile int argc; - char **envp; - int varflag; - struct strlist *sp; - volatile int mode; - int pip[2]; - struct cmdentry cmdentry; - struct job * volatile jp; - struct jmploc jmploc; - struct jmploc *volatile savehandler = NULL; - const char *volatile savecmdname; - volatile struct shparam saveparam; - struct localvar *volatile savelocalvars; - volatile int e; - char * volatile lastarg; - const char * volatile path = pathval(); - volatile int temp_path; - - vforked = 0; - /* First expand the arguments. */ - TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); - setstackmark(&smark); - back_exitstatus = 0; - - arglist.lastp = &arglist.list; - varflag = 1; - /* Expand arguments, ignoring the initial 'name=value' ones */ - for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { - char *p = argp->narg.text; - if (varflag && is_name(*p)) { - do { - p++; - } while (is_in_name(*p)); - if (*p == '=') - continue; - } - expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); - varflag = 0; - } - *arglist.lastp = NULL; - - expredir(cmd->ncmd.redirect); - - /* Now do the initial 'name=value' ones we skipped above */ - varlist.lastp = &varlist.list; - for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { - char *p = argp->narg.text; - if (!is_name(*p)) - break; - do - p++; - while (is_in_name(*p)); - if (*p != '=') - break; - expandarg(argp, &varlist, EXP_VARTILDE); - } - *varlist.lastp = NULL; - - argc = 0; - for (sp = arglist.list ; sp ; sp = sp->next) - argc++; - argv = stalloc(sizeof (char *) * (argc + 1)); - - for (sp = arglist.list ; sp ; sp = sp->next) { - TRACE(("evalcommand arg: %s\n", sp->text)); - *argv++ = sp->text; - } - *argv = NULL; - lastarg = NULL; - if (iflag && funcnest == 0 && argc > 0) - lastarg = argv[-1]; - argv -= argc; - - /* Print the command if xflag is set. */ - if (xflag) { - char sep = 0; - out2str(ps4val()); - for (sp = varlist.list ; sp ; sp = sp->next) { - if (sep != 0) - outc(sep, &errout); - out2shstr(sp->text); - sep = ' '; - } - for (sp = arglist.list ; sp ; sp = sp->next) { - if (sep != 0) - outc(sep, &errout); - out2shstr(sp->text); - sep = ' '; - } - outc('\n', &errout); - flushout(&errout); - } - - /* Now locate the command. */ - if (argc == 0) { - cmdentry.cmdtype = CMDSPLBLTIN; - cmdentry.u.bltin = bltincmd; - } else { - static const char PATH[] = "PATH="; - int cmd_flags = DO_ERR; - - /* - * Modify the command lookup path, if a PATH= assignment - * is present - */ - for (sp = varlist.list; sp; sp = sp->next) - if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) - path = sp->text + sizeof(PATH) - 1; - - do { - int argsused, use_syspath; - find_command(argv[0], &cmdentry, cmd_flags, path); - if (cmdentry.cmdtype == CMDUNKNOWN) { - exitstatus = 127; - flushout(&errout); - goto out; - } - - /* implement the 'command' builtin here */ - if (cmdentry.cmdtype != CMDBUILTIN || - cmdentry.u.bltin != bltincmd) - break; - cmd_flags |= DO_NOFUNC; - argsused = parse_command_args(argc, argv, &use_syspath); - if (argsused == 0) { - /* use 'type' builting to display info */ - cmdentry.u.bltin = typecmd; - break; - } - argc -= argsused; - argv += argsused; - if (use_syspath) - path = syspath() + 5; - } while (argc != 0); - if (cmdentry.cmdtype == CMDSPLBLTIN && cmd_flags & DO_NOFUNC) - /* posix mandates that 'command ' act as if - was a normal builtin */ - cmdentry.cmdtype = CMDBUILTIN; - } - - /* Fork off a child process if necessary. */ - if (cmd->ncmd.backgnd || (trap[0] && (flags & EV_EXIT) != 0) - || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0) - || ((flags & EV_BACKCMD) != 0 - && ((cmdentry.cmdtype != CMDBUILTIN && cmdentry.cmdtype != CMDSPLBLTIN) - || cmdentry.u.bltin == dotcmd - || cmdentry.u.bltin == evalcmd))) { - INTOFF; - jp = makejob(cmd, 1); - mode = cmd->ncmd.backgnd; - if (flags & EV_BACKCMD) { - mode = FORK_NOJOB; - if (sh_pipe(pip) < 0) - error("Pipe call failed"); - } -#ifdef DO_SHAREDVFORK - /* It is essential that if DO_SHAREDVFORK is defined that the - * child's address space is actually shared with the parent as - * we rely on this. - */ - if (usefork == 0 && cmdentry.cmdtype == CMDNORMAL) { - pid_t pid; - int serrno; - - savelocalvars = localvars; - localvars = NULL; - vforked = 1; - switch (pid = vfork()) { - case -1: - serrno = errno; - TRACE(("Vfork failed, errno=%d\n", serrno)); - INTON; - error("Cannot vfork (%s)", strerror(serrno)); - break; - case 0: - /* Make sure that exceptions only unwind to - * after the vfork(2) - */ - if (setjmp(jmploc.loc)) { - if (exception == EXSHELLPROC) { - /* We can't progress with the vfork, - * so, set vforked = 2 so the parent - * knows, and _exit(); - */ - vforked = 2; - _exit(0); - } else { - _exit(exerrno); - } - } - savehandler = handler; - handler = &jmploc; - listmklocal(varlist.list, VEXPORT | VNOFUNC); - forkchild(jp, cmd, mode, vforked); - break; - default: - handler = savehandler; /* restore from vfork(2) */ - poplocalvars(); - localvars = savelocalvars; - if (vforked == 2) { - vforked = 0; - - (void)waitpid(pid, NULL, 0); - /* We need to progress in a normal fork fashion */ - goto normal_fork; - } - vforked = 0; - forkparent(jp, cmd, mode, pid); - goto parent; - } - } else { -normal_fork: -#endif - if (forkshell(jp, cmd, mode) != 0) - goto parent; /* at end of routine */ - FORCEINTON; -#ifdef DO_SHAREDVFORK - } -#endif - if (flags & EV_BACKCMD) { - if (!vforked) { - FORCEINTON; - } - close(pip[0]); - if (pip[1] != 1) { - close(1); - copyfd(pip[1], 1, 1); - close(pip[1]); - } - } - flags |= EV_EXIT; - } - - /* This is the child process if a fork occurred. */ - /* Execute the command. */ - switch (cmdentry.cmdtype) { - case CMDFUNCTION: -#ifdef DEBUG - trputs("Shell function: "); trargs(argv); -#endif - redirect(cmd->ncmd.redirect, REDIR_PUSH); - saveparam = shellparam; - shellparam.malloc = 0; - shellparam.reset = 1; - shellparam.nparam = argc - 1; - shellparam.p = argv + 1; - shellparam.optnext = NULL; - INTOFF; - savelocalvars = localvars; - localvars = NULL; - INTON; - if (setjmp(jmploc.loc)) { - if (exception == EXSHELLPROC) { - freeparam((volatile struct shparam *) - &saveparam); - } else { - freeparam(&shellparam); - shellparam = saveparam; - } - poplocalvars(); - localvars = savelocalvars; - handler = savehandler; - longjmp(handler->loc, 1); - } - savehandler = handler; - handler = &jmploc; - listmklocal(varlist.list, VEXPORT); - /* stop shell blowing its stack */ - if (++funcnest > 1000) - error("too many nested function calls"); - evaltree(cmdentry.u.func, flags & EV_TESTED); - funcnest--; - INTOFF; - poplocalvars(); - localvars = savelocalvars; - freeparam(&shellparam); - shellparam = saveparam; - handler = savehandler; - popredir(); - INTON; - if (evalskip == SKIPFUNC) { - evalskip = SKIPNONE; - skipcount = 0; - } - if (flags & EV_EXIT) - exitshell(exitstatus); - break; - - case CMDBUILTIN: - case CMDSPLBLTIN: -#ifdef DEBUG - trputs("builtin command: "); trargs(argv); -#endif - mode = (cmdentry.u.bltin == execcmd) ? 0 : REDIR_PUSH; - if (flags == EV_BACKCMD) { - memout.nleft = 0; - memout.nextc = memout.buf; - memout.bufsize = 64; - mode |= REDIR_BACKQ; - } - e = -1; - savehandler = handler; - savecmdname = commandname; - handler = &jmploc; - temp_path = 0; - if (!setjmp(jmploc.loc)) { - /* We need to ensure the command hash table isn't - * corruped by temporary PATH assignments. - * However we must ensure the 'local' command works! - */ - if (path != pathval() && (cmdentry.u.bltin == hashcmd || - cmdentry.u.bltin == typecmd)) { - savelocalvars = localvars; - localvars = 0; - temp_path = 1; - mklocal(path - 5 /* PATH= */, 0); - } - redirect(cmd->ncmd.redirect, mode); - - /* exec is a special builtin, but needs this list... */ - cmdenviron = varlist.list; - /* we must check 'readonly' flag for all builtins */ - listsetvar(varlist.list, - cmdentry.cmdtype == CMDSPLBLTIN ? 0 : VNOSET); - commandname = argv[0]; - /* initialize nextopt */ - argptr = argv + 1; - optptr = NULL; - /* and getopt */ - optreset = 1; - optind = 1; - builtin_flags = flags; - exitstatus = cmdentry.u.bltin(argc, argv); - } else { - e = exception; - exitstatus = e == EXINT ? SIGINT + 128 : - e == EXEXEC ? exerrno : 2; - } - handler = savehandler; - flushall(); - out1 = &output; - out2 = &errout; - freestdout(); - if (temp_path) { - poplocalvars(); - localvars = savelocalvars; - } - cmdenviron = NULL; - if (e != EXSHELLPROC) { - commandname = savecmdname; - if (flags & EV_EXIT) - exitshell(exitstatus); - } - if (e != -1) { - if ((e != EXERROR && e != EXEXEC) - || cmdentry.cmdtype == CMDSPLBLTIN) - exraise(e); - FORCEINTON; - } - if (cmdentry.u.bltin != execcmd) - popredir(); - if (flags == EV_BACKCMD) { - backcmd->buf = memout.buf; - backcmd->nleft = memout.nextc - memout.buf; - memout.buf = NULL; - } - break; - - default: -#ifdef DEBUG - trputs("normal command: "); trargs(argv); -#endif - redirect(cmd->ncmd.redirect, vforked ? REDIR_VFORK : 0); - if (!vforked) - for (sp = varlist.list ; sp ; sp = sp->next) - setvareq(sp->text, VEXPORT|VSTACK); - envp = environment(); - shellexec(argv, envp, path, cmdentry.u.index, vforked); - break; - } - goto out; - -parent: /* parent process gets here (if we forked) */ - if (mode == FORK_FG) { /* argument to fork */ - exitstatus = waitforjob(jp); - } else if (mode == FORK_NOJOB) { - backcmd->fd = pip[0]; - close(pip[1]); - backcmd->jp = jp; - } - FORCEINTON; - -out: - if (lastarg) - /* dsl: I think this is intended to be used to support - * '_' in 'vi' command mode during line editing... - * However I implemented that within libedit itself. - */ - setvar("_", lastarg, 0); - popstackmark(&smark); -} - - -/* - * Search for a command. This is called before we fork so that the - * location of the command will be available in the parent as well as - * the child. The check for "goodname" is an overly conservative - * check that the name will not be subject to expansion. - */ - -STATIC void -prehash(union node *n) -{ - struct cmdentry entry; - - if (n && n->type == NCMD && n->ncmd.args) - if (goodname(n->ncmd.args->narg.text)) - find_command(n->ncmd.args->narg.text, &entry, 0, - pathval()); -} - -STATIC int -in_function(void) -{ - return funcnest; -} - -STATIC enum skipstate -current_skipstate(void) -{ - return evalskip; -} - -STATIC void -stop_skipping(void) -{ - evalskip = SKIPNONE; - skipcount = 0; -} - -/* - * Builtin commands. Builtin commands whose functions are closely - * tied to evaluation are implemented here. - */ - -/* - * No command given. - */ - -int -bltincmd(int argc, char **argv) -{ - /* - * Preserve exitstatus of a previous possible redirection - * as POSIX mandates - */ - return back_exitstatus; -} - - -/* - * Handle break and continue commands. Break, continue, and return are - * all handled by setting the evalskip flag. The evaluation routines - * above all check this flag, and if it is set they start skipping - * commands rather than executing them. The variable skipcount is - * the number of loops to break/continue, or the number of function - * levels to return. (The latter is always 1.) It should probably - * be an error to break out of more loops than exist, but it isn't - * in the standard shell so we don't make it one here. - */ - -int -breakcmd(int argc, char **argv) -{ - int n = argc > 1 ? number(argv[1]) : 1; - - if (n > loopnest) - n = loopnest; - if (n > 0) { - evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK; - skipcount = n; - } - return 0; -} - -int -dotcmd(int argc, char **argv) -{ - exitstatus = 0; - - if (argc >= 2) { /* That's what SVR2 does */ - char *fullname; - /* - * dot_funcnest needs to be 0 when not in a dotcmd, so it - * cannot be restored with (funcnest + 1). - */ - int dot_funcnest_old; - struct stackmark smark; - - setstackmark(&smark); - fullname = find_dot_file(argv[1]); - setinputfile(fullname, 1); - commandname = fullname; - dot_funcnest_old = dot_funcnest; - dot_funcnest = funcnest + 1; - cmdloop(0); - dot_funcnest = dot_funcnest_old; - popfile(); - popstackmark(&smark); - } - return exitstatus; -} - -/* - * Take commands from a file. To be compatible we should do a path - * search for the file, which is necessary to find sub-commands. - */ - -STATIC char * -find_dot_file(char *basename) -{ - char *fullname; - const char *path = pathval(); - struct stat statb; - - /* don't try this for absolute or relative paths */ - if (strchr(basename, '/')) - return basename; - - while ((fullname = padvance(&path, basename)) != NULL) { - if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) { - /* - * Don't bother freeing here, since it will - * be freed by the caller. - */ - return fullname; - } - stunalloc(fullname); - } - - /* not found in the PATH */ - error("%s: not found", basename); - /* NOTREACHED */ -} - - - -/* - * The return command. - * - * Quoth the POSIX standard: - * The return utility shall cause the shell to stop executing the current - * function or dot script. If the shell is not currently executing - * a function or dot script, the results are unspecified. - * - * As for the unspecified part, there seems to be no de-facto standard: bash - * ignores the return with a warning, zsh ignores the return in interactive - * mode but seems to liken it to exit in a script. (checked May 2014) - * - * We choose to silently ignore the return. Older versions of this shell - * set evalskip to SKIPFILE causing the shell to (indirectly) exit. This - * had at least the problem of circumventing the check for stopped jobs, - * which would occur for exit or ^D. - */ - -int -returncmd(int argc, char **argv) -{ - int ret = argc > 1 ? number(argv[1]) : exitstatus; - - if ((dot_funcnest == 0 && funcnest) - || (dot_funcnest > 0 && funcnest - (dot_funcnest - 1) > 0)) { - evalskip = SKIPFUNC; - skipcount = 1; - } else if (dot_funcnest > 0) { - evalskip = SKIPFILE; - skipcount = 1; - } else { - /* XXX: should a warning be issued? */ - ret = 0; - } - - return ret; -} - - -int -falsecmd(int argc, char **argv) -{ - return 1; -} - - -int -truecmd(int argc, char **argv) -{ - return 0; -} - - -int -execcmd(int argc, char **argv) -{ - if (argc > 1) { - struct strlist *sp; - - iflag = 0; /* exit on error */ - mflag = 0; - optschanged(); - for (sp = cmdenviron; sp; sp = sp->next) - setvareq(sp->text, VEXPORT|VSTACK); - shellexec(argv + 1, environment(), pathval(), 0, 0); - } - return 0; -} - -static int -conv_time(clock_t ticks, char *seconds, size_t l) -{ - static clock_t tpm = 0; - clock_t mins; - int i; - - if (!tpm) - tpm = sysconf(_SC_CLK_TCK) * 60; - - mins = ticks / tpm; - snprintf(seconds, l, "%.4f", (ticks - mins * tpm) * 60.0 / tpm ); - - if (seconds[0] == '6' && seconds[1] == '0') { - /* 59.99995 got rounded up... */ - mins++; - strlcpy(seconds, "0.0", l); - return mins; - } - - /* suppress trailing zeros */ - i = strlen(seconds) - 1; - for (; seconds[i] == '0' && seconds[i - 1] != '.'; i--) - seconds[i] = 0; - return mins; -} - -int -timescmd(int argc, char **argv) -{ - struct tms tms; - int u, s, cu, cs; - char us[8], ss[8], cus[8], css[8]; - - nextopt(""); - - times(&tms); - - u = conv_time(tms.tms_utime, us, sizeof(us)); - s = conv_time(tms.tms_stime, ss, sizeof(ss)); - cu = conv_time(tms.tms_cutime, cus, sizeof(cus)); - cs = conv_time(tms.tms_cstime, css, sizeof(css)); - - outfmt(out1, "%dm%ss %dm%ss\n%dm%ss %dm%ss\n", - u, us, s, ss, cu, cus, cs, css); - - return 0; -} diff --git a/bin/sh/eval.h b/bin/sh/eval.h deleted file mode 100644 index 151a0b7e6..000000000 --- a/bin/sh/eval.h +++ /dev/null @@ -1,73 +0,0 @@ -/* $NetBSD: eval.h,v 1.16 2014/05/31 14:42:18 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)eval.h 8.2 (Berkeley) 5/4/95 - */ - -extern const char *commandname; /* currently executing command */ -extern int exitstatus; /* exit status of last command */ -extern int back_exitstatus; /* exit status of backquoted command */ -extern struct strlist *cmdenviron; /* environment for builtin command */ - - -struct backcmd { /* result of evalbackcmd */ - int fd; /* file descriptor to read from */ - char *buf; /* buffer */ - int nleft; /* number of chars in buffer */ - struct job *jp; /* job structure for command */ -}; - -void evalstring(char *, int); -union node; /* BLETCH for ansi C */ -void evaltree(union node *, int); -void evalbackcmd(union node *, struct backcmd *); - -/* in_function returns nonzero if we are currently evaluating a function */ -int in_function(void); /* return non-zero, if evaluating a function */ - -/* reasons for skipping commands (see comment on breakcmd routine) */ -enum skipstate { - SKIPNONE = 0, /* not skipping */ - SKIPBREAK, /* break */ - SKIPCONT, /* continue */ - SKIPFUNC, /* return in a function */ - SKIPFILE /* return in a dot command */ -}; - -enum skipstate current_skipstate(void); -void stop_skipping(void); /* reset internal skipping state to SKIPNONE */ - -/* - * Only for use by reset() in init.c! - */ -void reset_eval(void); diff --git a/bin/sh/exec.c b/bin/sh/exec.c deleted file mode 100644 index 739f51b7a..000000000 --- a/bin/sh/exec.c +++ /dev/null @@ -1,1071 +0,0 @@ -/* $NetBSD: exec.c,v 1.45 2013/11/01 16:49:02 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95"; -#else -__RCSID("$NetBSD: exec.c,v 1.45 2013/11/01 16:49:02 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * When commands are first encountered, they are entered in a hash table. - * This ensures that a full path search will not have to be done for them - * on each invocation. - * - * We should investigate converting to a linear search, even though that - * would make the command name "hash" a misnomer. - */ - -#include "shell.h" -#include "main.h" -#include "nodes.h" -#include "parser.h" -#include "redir.h" -#include "eval.h" -#include "exec.h" -#include "builtins.h" -#include "var.h" -#include "options.h" -#include "input.h" -#include "output.h" -#include "syntax.h" -#include "memalloc.h" -#include "error.h" -#include "init.h" -#include "mystring.h" -#include "show.h" -#include "jobs.h" -#include "alias.h" - - -#define CMDTABLESIZE 31 /* should be prime */ -#define ARB 1 /* actual size determined at run time */ - - - -struct tblentry { - struct tblentry *next; /* next entry in hash chain */ - union param param; /* definition of builtin function */ - short cmdtype; /* index identifying command */ - char rehash; /* if set, cd done since entry created */ - char cmdname[ARB]; /* name of command */ -}; - - -STATIC struct tblentry *cmdtable[CMDTABLESIZE]; -STATIC int builtinloc = -1; /* index in path of %builtin, or -1 */ -int exerrno = 0; /* Last exec error */ - - -STATIC void tryexec(char *, char **, char **, int); -STATIC void printentry(struct tblentry *, int); -STATIC void clearcmdentry(int); -STATIC struct tblentry *cmdlookup(const char *, int); -STATIC void delete_cmd_entry(void); - -#ifndef BSD -STATIC void execinterp(char **, char **); -#endif - - -extern const char *const parsekwd[]; - -/* - * Exec a program. Never returns. If you change this routine, you may - * have to change the find_command routine as well. - */ - -void -shellexec(char **argv, char **envp, const char *path, int idx, int vforked) -{ - char *cmdname; - int e; - - if (strchr(argv[0], '/') != NULL) { - tryexec(argv[0], argv, envp, vforked); - e = errno; - } else { - e = ENOENT; - while ((cmdname = padvance(&path, argv[0])) != NULL) { - if (--idx < 0 && pathopt == NULL) { - tryexec(cmdname, argv, envp, vforked); - if (errno != ENOENT && errno != ENOTDIR) - e = errno; - } - stunalloc(cmdname); - } - } - - /* Map to POSIX errors */ - switch (e) { - case EACCES: - exerrno = 126; - break; - case ENOENT: - exerrno = 127; - break; - default: - exerrno = 2; - break; - } - TRACE(("shellexec failed for %s, errno %d, vforked %d, suppressint %d\n", - argv[0], e, vforked, suppressint )); - exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC)); - /* NOTREACHED */ -} - - -STATIC void -tryexec(char *cmd, char **argv, char **envp, int vforked) -{ - int e; -#ifndef BSD - char *p; -#endif - -#ifdef SYSV - do { - execve(cmd, argv, envp); - } while (errno == EINTR); -#else - execve(cmd, argv, envp); -#endif - e = errno; - if (e == ENOEXEC) { - if (vforked) { - /* We are currently vfork(2)ed, so raise an - * exception, and evalcommand will try again - * with a normal fork(2). - */ - exraise(EXSHELLPROC); - } -#ifdef DEBUG - TRACE(("execve(cmd=%s) returned ENOEXEC\n", cmd)); -#endif - initshellproc(); - setinputfile(cmd, 0); - commandname = arg0 = savestr(argv[0]); -#ifndef BSD - pgetc(); pungetc(); /* fill up input buffer */ - p = parsenextc; - if (parsenleft > 2 && p[0] == '#' && p[1] == '!') { - argv[0] = cmd; - execinterp(argv, envp); - } -#endif - setparam(argv + 1); - exraise(EXSHELLPROC); - } - errno = e; -} - - -#ifndef BSD -/* - * Execute an interpreter introduced by "#!", for systems where this - * feature has not been built into the kernel. If the interpreter is - * the shell, return (effectively ignoring the "#!"). If the execution - * of the interpreter fails, exit. - * - * This code peeks inside the input buffer in order to avoid actually - * reading any input. It would benefit from a rewrite. - */ - -#define NEWARGS 5 - -STATIC void -execinterp(char **argv, char **envp) -{ - int n; - char *inp; - char *outp; - char c; - char *p; - char **ap; - char *newargs[NEWARGS]; - int i; - char **ap2; - char **new; - - n = parsenleft - 2; - inp = parsenextc + 2; - ap = newargs; - for (;;) { - while (--n >= 0 && (*inp == ' ' || *inp == '\t')) - inp++; - if (n < 0) - goto bad; - if ((c = *inp++) == '\n') - break; - if (ap == &newargs[NEWARGS]) -bad: error("Bad #! line"); - STARTSTACKSTR(outp); - do { - STPUTC(c, outp); - } while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n'); - STPUTC('\0', outp); - n++, inp--; - *ap++ = grabstackstr(outp); - } - if (ap == newargs + 1) { /* if no args, maybe no exec is needed */ - p = newargs[0]; - for (;;) { - if (equal(p, "sh") || equal(p, "ash")) { - return; - } - while (*p != '/') { - if (*p == '\0') - goto break2; - p++; - } - p++; - } -break2:; - } - i = (char *)ap - (char *)newargs; /* size in bytes */ - if (i == 0) - error("Bad #! line"); - for (ap2 = argv ; *ap2++ != NULL ; ); - new = ckmalloc(i + ((char *)ap2 - (char *)argv)); - ap = newargs, ap2 = new; - while ((i -= sizeof (char **)) >= 0) - *ap2++ = *ap++; - ap = argv; - while (*ap2++ = *ap++); - shellexec(new, envp, pathval(), 0); - /* NOTREACHED */ -} -#endif - - - -/* - * Do a path search. The variable path (passed by reference) should be - * set to the start of the path before the first call; padvance will update - * this value as it proceeds. Successive calls to padvance will return - * the possible path expansions in sequence. If an option (indicated by - * a percent sign) appears in the path entry then the global variable - * pathopt will be set to point to it; otherwise pathopt will be set to - * NULL. - */ - -const char *pathopt; - -char * -padvance(const char **path, const char *name) -{ - const char *p; - char *q; - const char *start; - int len; - - if (*path == NULL) - return NULL; - start = *path; - for (p = start ; *p && *p != ':' && *p != '%' ; p++); - len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */ - while (stackblocksize() < len) - growstackblock(); - q = stackblock(); - if (p != start) { - memcpy(q, start, p - start); - q += p - start; - *q++ = '/'; - } - strcpy(q, name); - pathopt = NULL; - if (*p == '%') { - pathopt = ++p; - while (*p && *p != ':') p++; - } - if (*p == ':') - *path = p + 1; - else - *path = NULL; - return stalloc(len); -} - - - -/*** Command hashing code ***/ - - -int -hashcmd(int argc, char **argv) -{ - struct tblentry **pp; - struct tblentry *cmdp; - int c; - int verbose; - struct cmdentry entry; - char *name; - - verbose = 0; - while ((c = nextopt("rv")) != '\0') { - if (c == 'r') { - clearcmdentry(0); - } else if (c == 'v') { - verbose++; - } - } - if (*argptr == NULL) { - for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) { - for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { - if (verbose || cmdp->cmdtype == CMDNORMAL) - printentry(cmdp, verbose); - } - } - return 0; - } - while ((name = *argptr) != NULL) { - if ((cmdp = cmdlookup(name, 0)) != NULL - && (cmdp->cmdtype == CMDNORMAL - || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))) - delete_cmd_entry(); - find_command(name, &entry, DO_ERR, pathval()); - if (verbose) { - if (entry.cmdtype != CMDUNKNOWN) { /* if no error msg */ - cmdp = cmdlookup(name, 0); - if (cmdp != NULL) - printentry(cmdp, verbose); - } - flushall(); - } - argptr++; - } - return 0; -} - - -STATIC void -printentry(struct tblentry *cmdp, int verbose) -{ - int idx; - const char *path; - char *name; - - switch (cmdp->cmdtype) { - case CMDNORMAL: - idx = cmdp->param.index; - path = pathval(); - do { - name = padvance(&path, cmdp->cmdname); - stunalloc(name); - } while (--idx >= 0); - out1str(name); - break; - case CMDSPLBLTIN: - out1fmt("special builtin %s", cmdp->cmdname); - break; - case CMDBUILTIN: - out1fmt("builtin %s", cmdp->cmdname); - break; - case CMDFUNCTION: - out1fmt("function %s", cmdp->cmdname); - if (verbose) { - struct procstat ps; - INTOFF; - commandtext(&ps, cmdp->param.func); - INTON; - out1str("() { "); - out1str(ps.cmd); - out1str("; }"); - } - break; - default: - error("internal error: %s cmdtype %d", cmdp->cmdname, cmdp->cmdtype); - } - if (cmdp->rehash) - out1c('*'); - out1c('\n'); -} - - - -/* - * Resolve a command name. If you change this routine, you may have to - * change the shellexec routine as well. - */ - -void -find_command(char *name, struct cmdentry *entry, int act, const char *path) -{ - struct tblentry *cmdp, loc_cmd; - int idx; - int prev; - char *fullname; - struct stat statb; - int e; - int (*bltin)(int,char **); - - /* If name contains a slash, don't use PATH or hash table */ - if (strchr(name, '/') != NULL) { - if (act & DO_ABS) { - while (stat(name, &statb) < 0) { -#ifdef SYSV - if (errno == EINTR) - continue; -#endif - if (errno != ENOENT && errno != ENOTDIR) - e = errno; - entry->cmdtype = CMDUNKNOWN; - entry->u.index = -1; - return; - } - entry->cmdtype = CMDNORMAL; - entry->u.index = -1; - return; - } - entry->cmdtype = CMDNORMAL; - entry->u.index = 0; - return; - } - - if (path != pathval()) - act |= DO_ALTPATH; - - if (act & DO_ALTPATH && strstr(path, "%builtin") != NULL) - act |= DO_ALTBLTIN; - - /* If name is in the table, check answer will be ok */ - if ((cmdp = cmdlookup(name, 0)) != NULL) { - do { - switch (cmdp->cmdtype) { - case CMDNORMAL: - if (act & DO_ALTPATH) { - cmdp = NULL; - continue; - } - break; - case CMDFUNCTION: - if (act & DO_NOFUNC) { - cmdp = NULL; - continue; - } - break; - case CMDBUILTIN: - if ((act & DO_ALTBLTIN) || builtinloc >= 0) { - cmdp = NULL; - continue; - } - break; - } - /* if not invalidated by cd, we're done */ - if (cmdp->rehash == 0) - goto success; - } while (0); - } - - /* If %builtin not in path, check for builtin next */ - if ((act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc < 0) && - (bltin = find_builtin(name)) != 0) - goto builtin_success; - - /* We have to search path. */ - prev = -1; /* where to start */ - if (cmdp) { /* doing a rehash */ - if (cmdp->cmdtype == CMDBUILTIN) - prev = builtinloc; - else - prev = cmdp->param.index; - } - - e = ENOENT; - idx = -1; -loop: - while ((fullname = padvance(&path, name)) != NULL) { - stunalloc(fullname); - idx++; - if (pathopt) { - if (prefix("builtin", pathopt)) { - if ((bltin = find_builtin(name)) == 0) - goto loop; - goto builtin_success; - } else if (prefix("func", pathopt)) { - /* handled below */ - } else { - /* ignore unimplemented options */ - goto loop; - } - } - /* if rehash, don't redo absolute path names */ - if (fullname[0] == '/' && idx <= prev) { - if (idx < prev) - goto loop; - TRACE(("searchexec \"%s\": no change\n", name)); - goto success; - } - while (stat(fullname, &statb) < 0) { -#ifdef SYSV - if (errno == EINTR) - continue; -#endif - if (errno != ENOENT && errno != ENOTDIR) - e = errno; - goto loop; - } - e = EACCES; /* if we fail, this will be the error */ - if (!S_ISREG(statb.st_mode)) - goto loop; - if (pathopt) { /* this is a %func directory */ - if (act & DO_NOFUNC) - goto loop; - stalloc(strlen(fullname) + 1); - readcmdfile(fullname); - if ((cmdp = cmdlookup(name, 0)) == NULL || - cmdp->cmdtype != CMDFUNCTION) - error("%s not defined in %s", name, fullname); - stunalloc(fullname); - goto success; - } -#ifdef notdef - /* XXX this code stops root executing stuff, and is buggy - if you need a group from the group list. */ - if (statb.st_uid == geteuid()) { - if ((statb.st_mode & 0100) == 0) - goto loop; - } else if (statb.st_gid == getegid()) { - if ((statb.st_mode & 010) == 0) - goto loop; - } else { - if ((statb.st_mode & 01) == 0) - goto loop; - } -#endif - TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname)); - INTOFF; - if (act & DO_ALTPATH) { - stalloc(strlen(fullname) + 1); - cmdp = &loc_cmd; - } else - cmdp = cmdlookup(name, 1); - cmdp->cmdtype = CMDNORMAL; - cmdp->param.index = idx; - INTON; - goto success; - } - - /* We failed. If there was an entry for this command, delete it */ - if (cmdp) - delete_cmd_entry(); - if (act & DO_ERR) - outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC)); - entry->cmdtype = CMDUNKNOWN; - return; - -builtin_success: - INTOFF; - if (act & DO_ALTPATH) - cmdp = &loc_cmd; - else - cmdp = cmdlookup(name, 1); - if (cmdp->cmdtype == CMDFUNCTION) - /* DO_NOFUNC must have been set */ - cmdp = &loc_cmd; - cmdp->cmdtype = CMDBUILTIN; - cmdp->param.bltin = bltin; - INTON; -success: - if (cmdp) { - cmdp->rehash = 0; - entry->cmdtype = cmdp->cmdtype; - entry->u = cmdp->param; - } else - entry->cmdtype = CMDUNKNOWN; -} - - - -/* - * Search the table of builtin commands. - */ - -int -(*find_builtin(char *name))(int, char **) -{ - const struct builtincmd *bp; - - for (bp = builtincmd ; bp->name ; bp++) { - if (*bp->name == *name - && (*name == '%' || equal(bp->name, name))) - return bp->builtin; - } - return 0; -} - -int -(*find_splbltin(char *name))(int, char **) -{ - const struct builtincmd *bp; - - for (bp = splbltincmd ; bp->name ; bp++) { - if (*bp->name == *name && equal(bp->name, name)) - return bp->builtin; - } - return 0; -} - -/* - * At shell startup put special builtins into hash table. - * ensures they are executed first (see posix). - * We stop functions being added with the same name - * (as they are impossible to call) - */ - -void -hash_special_builtins(void) -{ - const struct builtincmd *bp; - struct tblentry *cmdp; - - for (bp = splbltincmd ; bp->name ; bp++) { - cmdp = cmdlookup(bp->name, 1); - cmdp->cmdtype = CMDSPLBLTIN; - cmdp->param.bltin = bp->builtin; - } -} - - - -/* - * Called when a cd is done. Marks all commands so the next time they - * are executed they will be rehashed. - */ - -void -hashcd(void) -{ - struct tblentry **pp; - struct tblentry *cmdp; - - for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) { - for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { - if (cmdp->cmdtype == CMDNORMAL - || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)) - cmdp->rehash = 1; - } - } -} - - - -/* - * Fix command hash table when PATH changed. - * Called before PATH is changed. The argument is the new value of PATH; - * pathval() still returns the old value at this point. - * Called with interrupts off. - */ - -void -changepath(const char *newval) -{ - const char *old, *new; - int idx; - int firstchange; - int bltin; - - old = pathval(); - new = newval; - firstchange = 9999; /* assume no change */ - idx = 0; - bltin = -1; - for (;;) { - if (*old != *new) { - firstchange = idx; - if ((*old == '\0' && *new == ':') - || (*old == ':' && *new == '\0')) - firstchange++; - old = new; /* ignore subsequent differences */ - } - if (*new == '\0') - break; - if (*new == '%' && bltin < 0 && prefix("builtin", new + 1)) - bltin = idx; - if (*new == ':') { - idx++; - } - new++, old++; - } - if (builtinloc < 0 && bltin >= 0) - builtinloc = bltin; /* zap builtins */ - if (builtinloc >= 0 && bltin < 0) - firstchange = 0; - clearcmdentry(firstchange); - builtinloc = bltin; -} - - -/* - * Clear out command entries. The argument specifies the first entry in - * PATH which has changed. - */ - -STATIC void -clearcmdentry(int firstchange) -{ - struct tblentry **tblp; - struct tblentry **pp; - struct tblentry *cmdp; - - INTOFF; - for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) { - pp = tblp; - while ((cmdp = *pp) != NULL) { - if ((cmdp->cmdtype == CMDNORMAL && - cmdp->param.index >= firstchange) - || (cmdp->cmdtype == CMDBUILTIN && - builtinloc >= firstchange)) { - *pp = cmdp->next; - ckfree(cmdp); - } else { - pp = &cmdp->next; - } - } - } - INTON; -} - - -/* - * Delete all functions. - */ - -#ifdef mkinit -MKINIT void deletefuncs(void); -MKINIT void hash_special_builtins(void); - -INIT { - hash_special_builtins(); -} - -SHELLPROC { - deletefuncs(); -} -#endif - -void -deletefuncs(void) -{ - struct tblentry **tblp; - struct tblentry **pp; - struct tblentry *cmdp; - - INTOFF; - for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) { - pp = tblp; - while ((cmdp = *pp) != NULL) { - if (cmdp->cmdtype == CMDFUNCTION) { - *pp = cmdp->next; - freefunc(cmdp->param.func); - ckfree(cmdp); - } else { - pp = &cmdp->next; - } - } - } - INTON; -} - - - -/* - * Locate a command in the command hash table. If "add" is nonzero, - * add the command to the table if it is not already present. The - * variable "lastcmdentry" is set to point to the address of the link - * pointing to the entry, so that delete_cmd_entry can delete the - * entry. - */ - -struct tblentry **lastcmdentry; - - -STATIC struct tblentry * -cmdlookup(const char *name, int add) -{ - int hashval; - const char *p; - struct tblentry *cmdp; - struct tblentry **pp; - - p = name; - hashval = *p << 4; - while (*p) - hashval += *p++; - hashval &= 0x7FFF; - pp = &cmdtable[hashval % CMDTABLESIZE]; - for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { - if (equal(cmdp->cmdname, name)) - break; - pp = &cmdp->next; - } - if (add && cmdp == NULL) { - INTOFF; - cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB - + strlen(name) + 1); - cmdp->next = NULL; - cmdp->cmdtype = CMDUNKNOWN; - cmdp->rehash = 0; - strcpy(cmdp->cmdname, name); - INTON; - } - lastcmdentry = pp; - return cmdp; -} - -/* - * Delete the command entry returned on the last lookup. - */ - -STATIC void -delete_cmd_entry(void) -{ - struct tblentry *cmdp; - - INTOFF; - cmdp = *lastcmdentry; - *lastcmdentry = cmdp->next; - ckfree(cmdp); - INTON; -} - - - -#ifdef notdef -void -getcmdentry(char *name, struct cmdentry *entry) -{ - struct tblentry *cmdp = cmdlookup(name, 0); - - if (cmdp) { - entry->u = cmdp->param; - entry->cmdtype = cmdp->cmdtype; - } else { - entry->cmdtype = CMDUNKNOWN; - entry->u.index = 0; - } -} -#endif - - -/* - * Add a new command entry, replacing any existing command entry for - * the same name - except special builtins. - */ - -STATIC void -addcmdentry(char *name, struct cmdentry *entry) -{ - struct tblentry *cmdp; - - INTOFF; - cmdp = cmdlookup(name, 1); - if (cmdp->cmdtype != CMDSPLBLTIN) { - if (cmdp->cmdtype == CMDFUNCTION) { - freefunc(cmdp->param.func); - } - cmdp->cmdtype = entry->cmdtype; - cmdp->param = entry->u; - } - INTON; -} - - -/* - * Define a shell function. - */ - -void -defun(char *name, union node *func) -{ - struct cmdentry entry; - - INTOFF; - entry.cmdtype = CMDFUNCTION; - entry.u.func = copyfunc(func); - addcmdentry(name, &entry); - INTON; -} - - -/* - * Delete a function if it exists. - */ - -int -unsetfunc(char *name) -{ - struct tblentry *cmdp; - - if ((cmdp = cmdlookup(name, 0)) != NULL && - cmdp->cmdtype == CMDFUNCTION) { - freefunc(cmdp->param.func); - delete_cmd_entry(); - } - return 0; -} - -/* - * Locate and print what a word is... - * also used for 'command -[v|V]' - */ - -int -typecmd(int argc, char **argv) -{ - struct cmdentry entry; - struct tblentry *cmdp; - const char * const *pp; - struct alias *ap; - int err = 0; - char *arg; - int c; - int V_flag = 0; - int v_flag = 0; - int p_flag = 0; - - while ((c = nextopt("vVp")) != 0) { - switch (c) { - case 'v': v_flag = 1; break; - case 'V': V_flag = 1; break; - case 'p': p_flag = 1; break; - } - } - - if (p_flag && (v_flag || V_flag)) - error("cannot specify -p with -v or -V"); - - while ((arg = *argptr++)) { - if (!v_flag) - out1str(arg); - /* First look at the keywords */ - for (pp = parsekwd; *pp; pp++) - if (**pp == *arg && equal(*pp, arg)) - break; - - if (*pp) { - if (v_flag) - err = 1; - else - out1str(" is a shell keyword\n"); - continue; - } - - /* Then look at the aliases */ - if ((ap = lookupalias(arg, 1)) != NULL) { - if (!v_flag) - out1fmt(" is an alias for \n"); - out1fmt("%s\n", ap->val); - continue; - } - - /* Then check if it is a tracked alias */ - if ((cmdp = cmdlookup(arg, 0)) != NULL) { - entry.cmdtype = cmdp->cmdtype; - entry.u = cmdp->param; - } else { - /* Finally use brute force */ - find_command(arg, &entry, DO_ABS, pathval()); - } - - switch (entry.cmdtype) { - case CMDNORMAL: { - if (strchr(arg, '/') == NULL) { - const char *path = pathval(); - char *name; - int j = entry.u.index; - do { - name = padvance(&path, arg); - stunalloc(name); - } while (--j >= 0); - if (!v_flag) - out1fmt(" is%s ", - cmdp ? " a tracked alias for" : ""); - out1fmt("%s\n", name); - } else { - if (access(arg, X_OK) == 0) { - if (!v_flag) - out1fmt(" is "); - out1fmt("%s\n", arg); - } else { - if (!v_flag) - out1fmt(": %s\n", - strerror(errno)); - else - err = 126; - } - } - break; - } - case CMDFUNCTION: - if (!v_flag) - out1str(" is a shell function\n"); - else - out1fmt("%s\n", arg); - break; - - case CMDBUILTIN: - if (!v_flag) - out1str(" is a shell builtin\n"); - else - out1fmt("%s\n", arg); - break; - - case CMDSPLBLTIN: - if (!v_flag) - out1str(" is a special shell builtin\n"); - else - out1fmt("%s\n", arg); - break; - - default: - if (!v_flag) - out1str(": not found\n"); - err = 127; - break; - } - } - return err; -} diff --git a/bin/sh/exec.h b/bin/sh/exec.h deleted file mode 100644 index c0fbd51ba..000000000 --- a/bin/sh/exec.h +++ /dev/null @@ -1,76 +0,0 @@ -/* $NetBSD: exec.h,v 1.23 2012/03/15 02:02:20 joerg Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)exec.h 8.3 (Berkeley) 6/8/95 - */ - -/* values of cmdtype */ -#define CMDUNKNOWN -1 /* no entry in table for command */ -#define CMDNORMAL 0 /* command is an executable program */ -#define CMDFUNCTION 1 /* command is a shell function */ -#define CMDBUILTIN 2 /* command is a shell builtin */ -#define CMDSPLBLTIN 3 /* command is a special shell builtin */ - - -struct cmdentry { - int cmdtype; - union param { - int index; - int (*bltin)(int, char**); - union node *func; - } u; -}; - - -/* action to find_command() */ -#define DO_ERR 0x01 /* prints errors */ -#define DO_ABS 0x02 /* checks absolute paths */ -#define DO_NOFUNC 0x04 /* don't return shell functions, for command */ -#define DO_ALTPATH 0x08 /* using alternate path */ -#define DO_ALTBLTIN 0x20 /* %builtin in alt. path */ - -extern const char *pathopt; /* set by padvance */ - -void shellexec(char **, char **, const char *, int, int) __dead; -char *padvance(const char **, const char *); -void find_command(char *, struct cmdentry *, int, const char *); -int (*find_builtin(char *))(int, char **); -int (*find_splbltin(char *))(int, char **); -void hashcd(void); -void changepath(const char *); -void deletefuncs(void); -void getcmdentry(char *, struct cmdentry *); -void addcmdentry(char *, struct cmdentry *); -void defun(char *, union node *); -int unsetfunc(char *); -void hash_special_builtins(void); diff --git a/bin/sh/expand.c b/bin/sh/expand.c deleted file mode 100644 index c8576492f..000000000 --- a/bin/sh/expand.c +++ /dev/null @@ -1,1640 +0,0 @@ -/* $NetBSD: expand.c,v 1.93 2015/08/27 07:46:47 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95"; -#else -__RCSID("$NetBSD: expand.c,v 1.93 2015/08/27 07:46:47 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Routines to expand arguments to commands. We have to deal with - * backquotes, shell variables, and file metacharacters. - */ - -#include "shell.h" -#include "main.h" -#include "nodes.h" -#include "eval.h" -#include "expand.h" -#include "syntax.h" -#include "parser.h" -#include "jobs.h" -#include "options.h" -#include "builtins.h" -#include "var.h" -#include "input.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" -#include "mystring.h" -#include "show.h" - -/* - * Structure specifying which parts of the string should be searched - * for IFS characters. - */ - -struct ifsregion { - struct ifsregion *next; /* next region in list */ - int begoff; /* offset of start of region */ - int endoff; /* offset of end of region */ - int inquotes; /* search for nul bytes only */ -}; - - -char *expdest; /* output of current string */ -struct nodelist *argbackq; /* list of back quote expressions */ -struct ifsregion ifsfirst; /* first struct in list of ifs regions */ -struct ifsregion *ifslastp; /* last struct in list */ -struct arglist exparg; /* holds expanded arg list */ - -STATIC void argstr(char *, int); -STATIC char *exptilde(char *, int); -STATIC void expbackq(union node *, int, int); -STATIC int subevalvar(char *, char *, int, int, int, int, int); -STATIC char *evalvar(char *, int); -STATIC int varisset(char *, int); -STATIC void varvalue(char *, int, int, int); -STATIC void recordregion(int, int, int); -STATIC void removerecordregions(int); -STATIC void ifsbreakup(char *, struct arglist *); -STATIC void ifsfree(void); -STATIC void expandmeta(struct strlist *, int); -STATIC void expmeta(char *, char *); -STATIC void addfname(char *); -STATIC struct strlist *expsort(struct strlist *); -STATIC struct strlist *msort(struct strlist *, int); -STATIC int pmatch(char *, char *, int); -STATIC char *cvtnum(int, char *); - -/* - * Expand shell variables and backquotes inside a here document. - */ - -void -expandhere(union node *arg, int fd) -{ - herefd = fd; - expandarg(arg, NULL, 0); - xwrite(fd, stackblock(), expdest - stackblock()); -} - - -/* - * Perform variable substitution and command substitution on an argument, - * placing the resulting list of arguments in arglist. If EXP_FULL is true, - * perform splitting and file name expansion. When arglist is NULL, perform - * here document expansion. - */ - -void -expandarg(union node *arg, struct arglist *arglist, int flag) -{ - struct strlist *sp; - char *p; - - argbackq = arg->narg.backquote; - STARTSTACKSTR(expdest); - ifsfirst.next = NULL; - ifslastp = NULL; - argstr(arg->narg.text, flag); - if (arglist == NULL) { - return; /* here document expanded */ - } - STPUTC('\0', expdest); - p = grabstackstr(expdest); - exparg.lastp = &exparg.list; - /* - * TODO - EXP_REDIR - */ - if (flag & EXP_FULL) { - ifsbreakup(p, &exparg); - *exparg.lastp = NULL; - exparg.lastp = &exparg.list; - expandmeta(exparg.list, flag); - } else { - if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */ - rmescapes(p); - sp = (struct strlist *)stalloc(sizeof (struct strlist)); - sp->text = p; - *exparg.lastp = sp; - exparg.lastp = &sp->next; - } - ifsfree(); - *exparg.lastp = NULL; - if (exparg.list) { - *arglist->lastp = exparg.list; - arglist->lastp = exparg.lastp; - } -} - - - -/* - * Perform variable and command substitution. - * If EXP_FULL is set, output CTLESC characters to allow for further processing. - * Otherwise treat $@ like $* since no splitting will be performed. - */ - -STATIC void -argstr(char *p, int flag) -{ - char c; - int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */ - int firsteq = 1; - const char *ifs = NULL; - int ifs_split = EXP_IFS_SPLIT; - - if (flag & EXP_IFS_SPLIT) - ifs = ifsset() ? ifsval() : " \t\n"; - - if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE))) - p = exptilde(p, flag); - for (;;) { - switch (c = *p++) { - case '\0': - case CTLENDVAR: /* end of expanding yyy in ${xxx-yyy} */ - return; - case CTLQUOTEMARK: - /* "$@" syntax adherence hack */ - if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=') - break; - if ((flag & EXP_FULL) != 0) - STPUTC(c, expdest); - ifs_split = 0; - break; - case CTLQUOTEEND: - ifs_split = EXP_IFS_SPLIT; - break; - case CTLESC: - if (quotes) - STPUTC(c, expdest); - c = *p++; - STPUTC(c, expdest); - break; - case CTLVAR: - p = evalvar(p, (flag & ~EXP_IFS_SPLIT) | (flag & ifs_split)); - break; - case CTLBACKQ: - case CTLBACKQ|CTLQUOTE: - expbackq(argbackq->n, c & CTLQUOTE, flag); - argbackq = argbackq->next; - break; - case CTLENDARI: - expari(flag); - break; - case ':': - case '=': - /* - * sort of a hack - expand tildes in variable - * assignments (after the first '=' and after ':'s). - */ - STPUTC(c, expdest); - if (flag & EXP_VARTILDE && *p == '~') { - if (c == '=') { - if (firsteq) - firsteq = 0; - else - break; - } - p = exptilde(p, flag); - } - break; - default: - STPUTC(c, expdest); - if (flag & ifs_split && strchr(ifs, c) != NULL) { - /* We need to get the output split here... */ - recordregion(expdest - stackblock() - 1, - expdest - stackblock(), 0); - } - break; - } - } -} - -STATIC char * -exptilde(char *p, int flag) -{ - char c, *startp = p; - struct passwd *pw; - const char *home; - int quotes = flag & (EXP_FULL | EXP_CASE); - - while ((c = *p) != '\0') { - switch(c) { - case CTLESC: - return (startp); - case CTLQUOTEMARK: - return (startp); - case ':': - if (flag & EXP_VARTILDE) - goto done; - break; - case '/': - goto done; - } - p++; - } -done: - *p = '\0'; - if (*(startp+1) == '\0') { - if ((home = lookupvar("HOME")) == NULL) - goto lose; - } else { - if ((pw = getpwnam(startp+1)) == NULL) - goto lose; - home = pw->pw_dir; - } - if (*home == '\0') - goto lose; - *p = c; - while ((c = *home++) != '\0') { - if (quotes && SQSYNTAX[(int)c] == CCTL) - STPUTC(CTLESC, expdest); - STPUTC(c, expdest); - } - return (p); -lose: - *p = c; - return (startp); -} - - -STATIC void -removerecordregions(int endoff) -{ - if (ifslastp == NULL) - return; - - if (ifsfirst.endoff > endoff) { - while (ifsfirst.next != NULL) { - struct ifsregion *ifsp; - INTOFF; - ifsp = ifsfirst.next->next; - ckfree(ifsfirst.next); - ifsfirst.next = ifsp; - INTON; - } - if (ifsfirst.begoff > endoff) - ifslastp = NULL; - else { - ifslastp = &ifsfirst; - ifsfirst.endoff = endoff; - } - return; - } - - ifslastp = &ifsfirst; - while (ifslastp->next && ifslastp->next->begoff < endoff) - ifslastp=ifslastp->next; - while (ifslastp->next != NULL) { - struct ifsregion *ifsp; - INTOFF; - ifsp = ifslastp->next->next; - ckfree(ifslastp->next); - ifslastp->next = ifsp; - INTON; - } - if (ifslastp->endoff > endoff) - ifslastp->endoff = endoff; -} - - -/* - * Expand arithmetic expression. Backup to start of expression, - * evaluate, place result in (backed up) result, adjust string position. - */ -void -expari(int flag) -{ - char *p, *start; - intmax_t result; - int adjustment; - int begoff; - int quotes = flag & (EXP_FULL | EXP_CASE); - int quoted; - - /* ifsfree(); */ - - /* - * This routine is slightly over-complicated for - * efficiency. First we make sure there is - * enough space for the result, which may be bigger - * than the expression if we add exponentation. Next we - * scan backwards looking for the start of arithmetic. If the - * next previous character is a CTLESC character, then we - * have to rescan starting from the beginning since CTLESC - * characters have to be processed left to right. - */ -/* SPACE_NEEDED is enough for all digits, plus possible "-", plus 2 (why?) */ -#define SPACE_NEEDED ((sizeof(intmax_t) * CHAR_BIT + 2) / 3 + 1 + 2) - CHECKSTRSPACE((int)(SPACE_NEEDED - 2), expdest); - USTPUTC('\0', expdest); - start = stackblock(); - p = expdest - 1; - while (*p != CTLARI && p >= start) - --p; - if (*p != CTLARI) - error("missing CTLARI (shouldn't happen)"); - if (p > start && *(p-1) == CTLESC) - for (p = start; *p != CTLARI; p++) - if (*p == CTLESC) - p++; - - if (p[1] == '"') - quoted=1; - else - quoted=0; - begoff = p - start; - removerecordregions(begoff); - if (quotes) - rmescapes(p+2); - result = arith(p+2); - fmtstr(p, SPACE_NEEDED, "%"PRIdMAX, result); - - while (*p++) - ; - - if (quoted == 0) - recordregion(begoff, p - 1 - start, 0); - adjustment = expdest - p + 1; - STADJUST(-adjustment, expdest); -} - - -/* - * Expand stuff in backwards quotes. - */ - -STATIC void -expbackq(union node *cmd, int quoted, int flag) -{ - struct backcmd in; - int i; - char buf[128]; - char *p; - char *dest = expdest; - struct ifsregion saveifs, *savelastp; - struct nodelist *saveargbackq; - char lastc; - int startloc = dest - stackblock(); - char const *syntax = quoted? DQSYNTAX : BASESYNTAX; - int saveherefd; - int quotes = flag & (EXP_FULL | EXP_CASE); - int nnl; - - INTOFF; - saveifs = ifsfirst; - savelastp = ifslastp; - saveargbackq = argbackq; - saveherefd = herefd; - herefd = -1; - p = grabstackstr(dest); - evalbackcmd(cmd, &in); - ungrabstackstr(p, dest); - ifsfirst = saveifs; - ifslastp = savelastp; - argbackq = saveargbackq; - herefd = saveherefd; - - p = in.buf; - lastc = '\0'; - nnl = 0; - for (;;) { - if (--in.nleft < 0) { - if (in.fd < 0) - break; - while ((i = read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR) - continue; - TRACE(("expbackq: read returns %d\n", i)); - if (i <= 0) - break; - p = buf; - in.nleft = i - 1; - } - lastc = *p++; - if (lastc != '\0') { - if (lastc == '\n') - nnl++; - else { - CHECKSTRSPACE(nnl + 2, dest); - while (nnl > 0) { - nnl--; - USTPUTC('\n', dest); - } - if (quotes && syntax[(int)lastc] == CCTL) - USTPUTC(CTLESC, dest); - USTPUTC(lastc, dest); - } - } - } - - if (in.fd >= 0) - close(in.fd); - if (in.buf) - ckfree(in.buf); - if (in.jp) - back_exitstatus = waitforjob(in.jp); - if (quoted == 0) - recordregion(startloc, dest - stackblock(), 0); - TRACE(("evalbackq: size=%d: \"%.*s\"\n", - (int)((dest - stackblock()) - startloc), - (int)((dest - stackblock()) - startloc), - stackblock() + startloc)); - expdest = dest; - INTON; -} - - - -STATIC int -subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes) -{ - char *startp; - char *loc = NULL; - char *q; - int c = 0; - int saveherefd = herefd; - struct nodelist *saveargbackq = argbackq; - int amount, how; - - herefd = -1; - switch (subtype) { - case VSTRIMLEFT: - case VSTRIMLEFTMAX: - case VSTRIMRIGHT: - case VSTRIMRIGHTMAX: - how = (varflags & VSQUOTE) ? 0 : EXP_CASE; - break; - default: - how = 0; - break; - } - argstr(p, how); - STACKSTRNUL(expdest); - herefd = saveherefd; - argbackq = saveargbackq; - startp = stackblock() + startloc; - if (str == NULL) - str = stackblock() + strloc; - - switch (subtype) { - case VSASSIGN: - setvar(str, startp, 0); - amount = startp - expdest; - STADJUST(amount, expdest); - varflags &= ~VSNUL; - return 1; - - case VSQUESTION: - if (*p != CTLENDVAR) { - outfmt(&errout, "%s\n", startp); - error(NULL); - } - error("%.*s: parameter %snot set", - (int)(p - str - 1), - str, (varflags & VSNUL) ? "null or " - : nullstr); - /* NOTREACHED */ - - case VSTRIMLEFT: - for (loc = startp; loc < str; loc++) { - c = *loc; - *loc = '\0'; - if (patmatch(str, startp, quotes)) - goto recordleft; - *loc = c; - if (quotes && *loc == CTLESC) - loc++; - } - return 0; - - case VSTRIMLEFTMAX: - for (loc = str - 1; loc >= startp;) { - c = *loc; - *loc = '\0'; - if (patmatch(str, startp, quotes)) - goto recordleft; - *loc = c; - loc--; - if (quotes && loc > startp && - *(loc - 1) == CTLESC) { - for (q = startp; q < loc; q++) - if (*q == CTLESC) - q++; - if (q > loc) - loc--; - } - } - return 0; - - case VSTRIMRIGHT: - for (loc = str - 1; loc >= startp;) { - if (patmatch(str, loc, quotes)) - goto recordright; - loc--; - if (quotes && loc > startp && - *(loc - 1) == CTLESC) { - for (q = startp; q < loc; q++) - if (*q == CTLESC) - q++; - if (q > loc) - loc--; - } - } - return 0; - - case VSTRIMRIGHTMAX: - for (loc = startp; loc < str - 1; loc++) { - if (patmatch(str, loc, quotes)) - goto recordright; - if (quotes && *loc == CTLESC) - loc++; - } - return 0; - - default: - abort(); - } - -recordleft: - *loc = c; - amount = ((str - 1) - (loc - startp)) - expdest; - STADJUST(amount, expdest); - while (loc != str - 1) - *startp++ = *loc++; - return 1; - -recordright: - amount = loc - expdest; - STADJUST(amount, expdest); - STPUTC('\0', expdest); - STADJUST(-1, expdest); - return 1; -} - - -/* - * Expand a variable, and return a pointer to the next character in the - * input string. - */ - -STATIC char * -evalvar(char *p, int flag) -{ - int subtype; - int varflags; - char *var; - char *val; - int patloc; - int c; - int set; - int special; - int startloc; - int varlen; - int apply_ifs; - int quotes = flag & (EXP_FULL | EXP_CASE); - - varflags = (unsigned char)*p++; - subtype = varflags & VSTYPE; - var = p; - special = !is_name(*p); - p = strchr(p, '=') + 1; - -again: /* jump here after setting a variable with ${var=text} */ - if (varflags & VSLINENO) { - set = 1; - special = 0; - val = var; - p[-1] = '\0'; - } else if (special) { - set = varisset(var, varflags & VSNUL); - val = NULL; - } else { - val = lookupvar(var); - if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) { - val = NULL; - set = 0; - } else - set = 1; - } - - varlen = 0; - startloc = expdest - stackblock(); - - if (!set && uflag && *var != '@' && *var != '*') { - switch (subtype) { - case VSNORMAL: - case VSTRIMLEFT: - case VSTRIMLEFTMAX: - case VSTRIMRIGHT: - case VSTRIMRIGHTMAX: - case VSLENGTH: - error("%.*s: parameter not set", - (int)(p - var - 1), var); - /* NOTREACHED */ - } - } - - if (set && subtype != VSPLUS) { - /* insert the value of the variable */ - if (special) { - varvalue(var, varflags & VSQUOTE, subtype, flag); - if (subtype == VSLENGTH) { - varlen = expdest - stackblock() - startloc; - STADJUST(-varlen, expdest); - } - } else { - char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX - : BASESYNTAX; - - if (subtype == VSLENGTH) { - for (;*val; val++) - varlen++; - } else { - while (*val) { - if (quotes && syntax[(int)*val] == CCTL) - STPUTC(CTLESC, expdest); - STPUTC(*val++, expdest); - } - - } - } - } - - - if (flag & EXP_IN_QUOTES) - apply_ifs = 0; - else if (varflags & VSQUOTE) { - if (*var == '@' && shellparam.nparam != 1) - apply_ifs = 1; - else { - /* - * Mark so that we don't apply IFS if we recurse through - * here expanding $bar from "${foo-$bar}". - */ - flag |= EXP_IN_QUOTES; - apply_ifs = 0; - } - } else - apply_ifs = 1; - - switch (subtype) { - case VSLENGTH: - expdest = cvtnum(varlen, expdest); - break; - - case VSNORMAL: - break; - - case VSPLUS: - set = !set; - /* FALLTHROUGH */ - case VSMINUS: - if (!set) { - argstr(p, flag | (apply_ifs ? EXP_IFS_SPLIT : 0)); - /* - * ${x-a b c} doesn't get split, but removing the - * 'apply_ifs = 0' apparently breaks ${1+"$@"}.. - * ${x-'a b' c} should generate 2 args. - */ - /* We should have marked stuff already */ - apply_ifs = 0; - } - break; - - case VSTRIMLEFT: - case VSTRIMLEFTMAX: - case VSTRIMRIGHT: - case VSTRIMRIGHTMAX: - if (!set) - break; - /* - * Terminate the string and start recording the pattern - * right after it - */ - STPUTC('\0', expdest); - patloc = expdest - stackblock(); - if (subevalvar(p, NULL, patloc, subtype, - startloc, varflags, quotes) == 0) { - int amount = (expdest - stackblock() - patloc) + 1; - STADJUST(-amount, expdest); - } - /* Remove any recorded regions beyond start of variable */ - removerecordregions(startloc); - apply_ifs = 1; - break; - - case VSASSIGN: - case VSQUESTION: - if (set) - break; - if (subevalvar(p, var, 0, subtype, startloc, varflags, quotes)) { - varflags &= ~VSNUL; - /* - * Remove any recorded regions beyond - * start of variable - */ - removerecordregions(startloc); - goto again; - } - apply_ifs = 0; - break; - - default: - abort(); - } - p[-1] = '='; /* recover overwritten '=' */ - - if (apply_ifs) - recordregion(startloc, expdest - stackblock(), - varflags & VSQUOTE); - - if (subtype != VSNORMAL) { /* skip to end of alternative */ - int nesting = 1; - for (;;) { - if ((c = *p++) == CTLESC) - p++; - else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) { - if (set) - argbackq = argbackq->next; - } else if (c == CTLVAR) { - if ((*p++ & VSTYPE) != VSNORMAL) - nesting++; - } else if (c == CTLENDVAR) { - if (--nesting == 0) - break; - } - } - } - return p; -} - - - -/* - * Test whether a specialized variable is set. - */ - -STATIC int -varisset(char *name, int nulok) -{ - if (*name == '!') - return backgndpid != -1; - else if (*name == '@' || *name == '*') { - if (*shellparam.p == NULL) - return 0; - - if (nulok) { - char **av; - - for (av = shellparam.p; *av; av++) - if (**av != '\0') - return 1; - return 0; - } - } else if (is_digit(*name)) { - char *ap; - int num = atoi(name); - - if (num > shellparam.nparam) - return 0; - - if (num == 0) - ap = arg0; - else - ap = shellparam.p[num - 1]; - - if (nulok && (ap == NULL || *ap == '\0')) - return 0; - } - return 1; -} - - - -/* - * Add the value of a specialized variable to the stack string. - */ - -STATIC void -varvalue(char *name, int quoted, int subtype, int flag) -{ - int num; - char *p; - int i; - char sep; - char **ap; - char const *syntax; - -#define STRTODEST(p) \ - do {\ - if (flag & (EXP_FULL | EXP_CASE) && subtype != VSLENGTH) { \ - syntax = quoted? DQSYNTAX : BASESYNTAX; \ - while (*p) { \ - if (syntax[(int)*p] == CCTL) \ - STPUTC(CTLESC, expdest); \ - STPUTC(*p++, expdest); \ - } \ - } else \ - while (*p) \ - STPUTC(*p++, expdest); \ - } while (0) - - - switch (*name) { - case '$': - num = rootpid; - goto numvar; - case '?': - num = exitstatus; - goto numvar; - case '#': - num = shellparam.nparam; - goto numvar; - case '!': - num = backgndpid; -numvar: - expdest = cvtnum(num, expdest); - break; - case '-': - for (i = 0; optlist[i].name; i++) { - if (optlist[i].val && optlist[i].letter) - STPUTC(optlist[i].letter, expdest); - } - break; - case '@': - if (flag & EXP_FULL && quoted) { - for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { - STRTODEST(p); - if (*ap) - /* A NUL separates args inside "" */ - STPUTC('\0', expdest); - } - break; - } - /* fall through */ - case '*': - if (ifsset() != 0) - sep = ifsval()[0]; - else - sep = ' '; - for (ap = shellparam.p ; (p = *ap++) != NULL ; ) { - STRTODEST(p); - if (*ap && sep) - STPUTC(sep, expdest); - } - break; - case '0': - p = arg0; - STRTODEST(p); - break; - default: - if (is_digit(*name)) { - num = atoi(name); - if (num > 0 && num <= shellparam.nparam) { - p = shellparam.p[num - 1]; - STRTODEST(p); - } - } - break; - } -} - - - -/* - * Record the fact that we have to scan this region of the - * string for IFS characters. - */ - -STATIC void -recordregion(int start, int end, int inquotes) -{ - struct ifsregion *ifsp; - - if (ifslastp == NULL) { - ifsp = &ifsfirst; - } else { - if (ifslastp->endoff == start - && ifslastp->inquotes == inquotes) { - /* extend previous area */ - ifslastp->endoff = end; - return; - } - ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion)); - ifslastp->next = ifsp; - } - ifslastp = ifsp; - ifslastp->next = NULL; - ifslastp->begoff = start; - ifslastp->endoff = end; - ifslastp->inquotes = inquotes; -} - - - -/* - * Break the argument string into pieces based upon IFS and add the - * strings to the argument list. The regions of the string to be - * searched for IFS characters have been stored by recordregion. - */ -STATIC void -ifsbreakup(char *string, struct arglist *arglist) -{ - struct ifsregion *ifsp; - struct strlist *sp; - char *start; - char *p; - char *q; - const char *ifs; - const char *ifsspc; - int had_param_ch = 0; - - start = string; - - if (ifslastp == NULL) { - /* Return entire argument, IFS doesn't apply to any of it */ - sp = (struct strlist *)stalloc(sizeof *sp); - sp->text = start; - *arglist->lastp = sp; - arglist->lastp = &sp->next; - return; - } - - ifs = ifsset() ? ifsval() : " \t\n"; - - for (ifsp = &ifsfirst; ifsp != NULL; ifsp = ifsp->next) { - p = string + ifsp->begoff; - while (p < string + ifsp->endoff) { - had_param_ch = 1; - q = p; - if (*p == CTLESC) - p++; - if (ifsp->inquotes) { - /* Only NULs (should be from "$@") end args */ - if (*p != 0) { - p++; - continue; - } - ifsspc = NULL; - } else { - if (!strchr(ifs, *p)) { - p++; - continue; - } - had_param_ch = 0; - ifsspc = strchr(" \t\n", *p); - - /* Ignore IFS whitespace at start */ - if (q == start && ifsspc != NULL) { - p++; - start = p; - continue; - } - } - - /* Save this argument... */ - *q = '\0'; - sp = (struct strlist *)stalloc(sizeof *sp); - sp->text = start; - *arglist->lastp = sp; - arglist->lastp = &sp->next; - p++; - - if (ifsspc != NULL) { - /* Ignore further trailing IFS whitespace */ - for (; p < string + ifsp->endoff; p++) { - q = p; - if (*p == CTLESC) - p++; - if (strchr(ifs, *p) == NULL) { - p = q; - break; - } - if (strchr(" \t\n", *p) == NULL) { - p++; - break; - } - } - } - start = p; - } - } - - /* - * Save anything left as an argument. - * Traditionally we have treated 'IFS=':'; set -- x$IFS' as - * generating 2 arguments, the second of which is empty. - * Some recent clarification of the Posix spec say that it - * should only generate one.... - */ - if (had_param_ch || *start != 0) { - sp = (struct strlist *)stalloc(sizeof *sp); - sp->text = start; - *arglist->lastp = sp; - arglist->lastp = &sp->next; - } -} - -STATIC void -ifsfree(void) -{ - while (ifsfirst.next != NULL) { - struct ifsregion *ifsp; - INTOFF; - ifsp = ifsfirst.next->next; - ckfree(ifsfirst.next); - ifsfirst.next = ifsp; - INTON; - } - ifslastp = NULL; - ifsfirst.next = NULL; -} - - - -/* - * Expand shell metacharacters. At this point, the only control characters - * should be escapes. The results are stored in the list exparg. - */ - -char *expdir; - - -STATIC void -expandmeta(struct strlist *str, int flag) -{ - char *p; - struct strlist **savelastp; - struct strlist *sp; - char c; - /* TODO - EXP_REDIR */ - - while (str) { - if (fflag) - goto nometa; - p = str->text; - for (;;) { /* fast check for meta chars */ - if ((c = *p++) == '\0') - goto nometa; - if (c == '*' || c == '?' || c == '[' || c == '!') - break; - } - savelastp = exparg.lastp; - INTOFF; - if (expdir == NULL) { - int i = strlen(str->text); - expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */ - } - - expmeta(expdir, str->text); - ckfree(expdir); - expdir = NULL; - INTON; - if (exparg.lastp == savelastp) { - /* - * no matches - */ -nometa: - *exparg.lastp = str; - rmescapes(str->text); - exparg.lastp = &str->next; - } else { - *exparg.lastp = NULL; - *savelastp = sp = expsort(*savelastp); - while (sp->next != NULL) - sp = sp->next; - exparg.lastp = &sp->next; - } - str = str->next; - } -} - - -/* - * Do metacharacter (i.e. *, ?, [...]) expansion. - */ - -STATIC void -expmeta(char *enddir, char *name) -{ - char *p; - const char *cp; - char *q; - char *start; - char *endname; - int metaflag; - struct stat statb; - DIR *dirp; - struct dirent *dp; - int atend; - int matchdot; - - metaflag = 0; - start = name; - for (p = name ; ; p++) { - if (*p == '*' || *p == '?') - metaflag = 1; - else if (*p == '[') { - q = p + 1; - if (*q == '!') - q++; - for (;;) { - while (*q == CTLQUOTEMARK) - q++; - if (*q == CTLESC) - q++; - if (*q == '/' || *q == '\0') - break; - if (*++q == ']') { - metaflag = 1; - break; - } - } - } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) { - metaflag = 1; - } else if (*p == '\0') - break; - else if (*p == CTLQUOTEMARK) - continue; - else if (*p == CTLESC) - p++; - if (*p == '/') { - if (metaflag) - break; - start = p + 1; - } - } - if (metaflag == 0) { /* we've reached the end of the file name */ - if (enddir != expdir) - metaflag++; - for (p = name ; ; p++) { - if (*p == CTLQUOTEMARK) - continue; - if (*p == CTLESC) - p++; - *enddir++ = *p; - if (*p == '\0') - break; - } - if (metaflag == 0 || lstat(expdir, &statb) >= 0) - addfname(expdir); - return; - } - endname = p; - if (start != name) { - p = name; - while (p < start) { - while (*p == CTLQUOTEMARK) - p++; - if (*p == CTLESC) - p++; - *enddir++ = *p++; - } - } - if (enddir == expdir) { - cp = "."; - } else if (enddir == expdir + 1 && *expdir == '/') { - cp = "/"; - } else { - cp = expdir; - enddir[-1] = '\0'; - } - if ((dirp = opendir(cp)) == NULL) - return; - if (enddir != expdir) - enddir[-1] = '/'; - if (*endname == 0) { - atend = 1; - } else { - atend = 0; - *endname++ = '\0'; - } - matchdot = 0; - p = start; - while (*p == CTLQUOTEMARK) - p++; - if (*p == CTLESC) - p++; - if (*p == '.') - matchdot++; - while (! int_pending() && (dp = readdir(dirp)) != NULL) { - if (dp->d_name[0] == '.' && ! matchdot) - continue; - if (patmatch(start, dp->d_name, 0)) { - if (atend) { - scopy(dp->d_name, enddir); - addfname(expdir); - } else { - for (p = enddir, cp = dp->d_name; - (*p++ = *cp++) != '\0';) - continue; - p[-1] = '/'; - expmeta(p, endname); - } - } - } - closedir(dirp); - if (! atend) - endname[-1] = '/'; -} - - -/* - * Add a file name to the list. - */ - -STATIC void -addfname(char *name) -{ - char *p; - struct strlist *sp; - - p = stalloc(strlen(name) + 1); - scopy(name, p); - sp = (struct strlist *)stalloc(sizeof *sp); - sp->text = p; - *exparg.lastp = sp; - exparg.lastp = &sp->next; -} - - -/* - * Sort the results of file name expansion. It calculates the number of - * strings to sort and then calls msort (short for merge sort) to do the - * work. - */ - -STATIC struct strlist * -expsort(struct strlist *str) -{ - int len; - struct strlist *sp; - - len = 0; - for (sp = str ; sp ; sp = sp->next) - len++; - return msort(str, len); -} - - -STATIC struct strlist * -msort(struct strlist *list, int len) -{ - struct strlist *p, *q = NULL; - struct strlist **lpp; - int half; - int n; - - if (len <= 1) - return list; - half = len >> 1; - p = list; - for (n = half ; --n >= 0 ; ) { - q = p; - p = p->next; - } - q->next = NULL; /* terminate first half of list */ - q = msort(list, half); /* sort first half of list */ - p = msort(p, len - half); /* sort second half */ - lpp = &list; - for (;;) { - if (strcmp(p->text, q->text) < 0) { - *lpp = p; - lpp = &p->next; - if ((p = *lpp) == NULL) { - *lpp = q; - break; - } - } else { - *lpp = q; - lpp = &q->next; - if ((q = *lpp) == NULL) { - *lpp = p; - break; - } - } - } - return list; -} - - -/* - * See if a character matches a character class, starting at the first colon - * of "[:class:]". - * If a valid character class is recognized, a pointer to the next character - * after the final closing bracket is stored into *end, otherwise a null - * pointer is stored into *end. - */ -static int -match_charclass(char *p, wchar_t chr, char **end) -{ - char name[20]; - char *nameend; - wctype_t cclass; - - *end = NULL; - p++; - nameend = strstr(p, ":]"); - if (nameend == NULL || (size_t)(nameend - p) >= sizeof(name) || - nameend == p) - return 0; - memcpy(name, p, nameend - p); - name[nameend - p] = '\0'; - *end = nameend + 2; - cclass = wctype(name); - /* An unknown class matches nothing but is valid nevertheless. */ - if (cclass == 0) - return 0; - return iswctype(chr, cclass); -} - - - -/* - * Returns true if the pattern matches the string. - */ - -int -patmatch(char *pattern, char *string, int squoted) -{ -#ifdef notdef - if (pattern[0] == '!' && pattern[1] == '!') - return 1 - pmatch(pattern + 2, string); - else -#endif - return pmatch(pattern, string, squoted); -} - - -STATIC int -pmatch(char *pattern, char *string, int squoted) -{ - char *p, *q, *end; - char c; - - p = pattern; - q = string; - for (;;) { - switch (c = *p++) { - case '\0': - goto breakloop; - case CTLESC: - if (squoted && *q == CTLESC) - q++; - if (*q++ != *p++) - return 0; - break; - case CTLQUOTEMARK: - continue; - case '?': - if (squoted && *q == CTLESC) - q++; - if (*q++ == '\0') - return 0; - break; - case '*': - c = *p; - while (c == CTLQUOTEMARK || c == '*') - c = *++p; - if (c != CTLESC && c != CTLQUOTEMARK && - c != '?' && c != '*' && c != '[') { - while (*q != c) { - if (squoted && *q == CTLESC && - q[1] == c) - break; - if (*q == '\0') - return 0; - if (squoted && *q == CTLESC) - q++; - q++; - } - } - do { - if (pmatch(p, q, squoted)) - return 1; - if (squoted && *q == CTLESC) - q++; - } while (*q++ != '\0'); - return 0; - case '[': { - char *endp; - int invert, found; - char chr; - - endp = p; - if (*endp == '!') - endp++; - for (;;) { - while (*endp == CTLQUOTEMARK) - endp++; - if (*endp == '\0') - goto dft; /* no matching ] */ - if (*endp == CTLESC) - endp++; - if (*++endp == ']') - break; - } - invert = 0; - if (*p == '!') { - invert++; - p++; - } - found = 0; - chr = *q++; - if (squoted && chr == CTLESC) - chr = *q++; - if (chr == '\0') - return 0; - c = *p++; - do { - if (c == CTLQUOTEMARK) - continue; - if (c == '[' && *p == ':') { - found |= match_charclass(p, chr, &end); - if (end != NULL) - p = end; - } - if (c == CTLESC) - c = *p++; - if (*p == '-' && p[1] != ']') { - p++; - while (*p == CTLQUOTEMARK) - p++; - if (*p == CTLESC) - p++; - if (chr >= c && chr <= *p) - found = 1; - p++; - } else { - if (chr == c) - found = 1; - } - } while ((c = *p++) != ']'); - if (found == invert) - return 0; - break; - } -dft: default: - if (squoted && *q == CTLESC) - q++; - if (*q++ != c) - return 0; - break; - } - } -breakloop: - if (*q != '\0') - return 0; - return 1; -} - - - -/* - * Remove any CTLESC characters from a string. - */ - -void -rmescapes(char *str) -{ - char *p, *q; - - p = str; - while (*p != CTLESC && *p != CTLQUOTEMARK) { - if (*p++ == '\0') - return; - } - q = p; - while (*p) { - if (*p == CTLQUOTEMARK) { - p++; - continue; - } - if (*p == CTLESC) - p++; - *q++ = *p++; - } - *q = '\0'; -} - - - -/* - * See if a pattern matches in a case statement. - */ - -int -casematch(union node *pattern, char *val) -{ - struct stackmark smark; - int result; - char *p; - - setstackmark(&smark); - argbackq = pattern->narg.backquote; - STARTSTACKSTR(expdest); - ifslastp = NULL; - argstr(pattern->narg.text, EXP_TILDE | EXP_CASE); - STPUTC('\0', expdest); - p = grabstackstr(expdest); - result = patmatch(p, val, 0); - popstackmark(&smark); - return result; -} - -/* - * Our own itoa(). - */ - -STATIC char * -cvtnum(int num, char *buf) -{ - char temp[32]; - int neg = num < 0; - char *p = temp + 31; - - temp[31] = '\0'; - - do { - *--p = num % 10 + '0'; - } while ((num /= 10) != 0); - - if (neg) - *--p = '-'; - - while (*p) - STPUTC(*p++, buf); - return buf; -} - -/* - * Do most of the work for wordexp(3). - */ - -int -wordexpcmd(int argc, char **argv) -{ - size_t len; - int i; - - out1fmt("%d", argc - 1); - out1c('\0'); - for (i = 1, len = 0; i < argc; i++) - len += strlen(argv[i]); - out1fmt("%zu", len); - out1c('\0'); - for (i = 1; i < argc; i++) { - out1str(argv[i]); - out1c('\0'); - } - return (0); -} diff --git a/bin/sh/expand.h b/bin/sh/expand.h deleted file mode 100644 index 76a012aa9..000000000 --- a/bin/sh/expand.h +++ /dev/null @@ -1,73 +0,0 @@ -/* $NetBSD: expand.h,v 1.19 2012/12/22 20:15:22 dsl Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)expand.h 8.2 (Berkeley) 5/4/95 - */ - -#include - -struct strlist { - struct strlist *next; - char *text; -}; - - -struct arglist { - struct strlist *list; - struct strlist **lastp; -}; - -/* - * expandarg() flags - */ -#define EXP_FULL 0x1 /* perform word splitting & file globbing */ -#define EXP_TILDE 0x2 /* do normal tilde expansion */ -#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */ -#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */ -#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */ -#define EXP_IFS_SPLIT 0x20 /* need to record arguments for ifs breakup */ -#define EXP_IN_QUOTES 0x40 /* don't set EXP_IFS_SPLIT again */ - - -union node; -void expandhere(union node *, int); -void expandarg(union node *, struct arglist *, int); -void expari(int); -int patmatch(char *, char *, int); -void rmescapes(char *); -int casematch(union node *, char *); - -/* From arith.y */ -intmax_t arith(const char *); -void arith_lex_reset(void); -int yylex(void); diff --git a/bin/sh/funcs/cmv b/bin/sh/funcs/cmv deleted file mode 100644 index 667f846e0..000000000 --- a/bin/sh/funcs/cmv +++ /dev/null @@ -1,50 +0,0 @@ -# $NetBSD: cmv,v 1.7 1995/05/11 21:31:05 christos Exp $ -# Copyright (c) 1991, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Kenneth Almquist. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. All advertising materials mentioning features or use of this software -# must display the following acknowledgement: -# This product includes software developed by the University of -# California, Berkeley and its contributors. -# 4. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)cmv 8.2 (Berkeley) 5/4/95 - -# Conditional move--don't replace an existing file. - -cmv() { - if test $# != 2 - then echo "cmv: arg count" - return 2 - fi - if test -f "$2" -o -w "$2" - then echo "$2 exists" - return 2 - fi - /bin/mv "$1" "$2" -} diff --git a/bin/sh/funcs/dirs b/bin/sh/funcs/dirs deleted file mode 100644 index 68bb317bb..000000000 --- a/bin/sh/funcs/dirs +++ /dev/null @@ -1,74 +0,0 @@ -# $NetBSD: dirs,v 1.7 1995/05/11 21:31:08 christos Exp $ -# Copyright (c) 1991, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Kenneth Almquist. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. All advertising materials mentioning features or use of this software -# must display the following acknowledgement: -# This product includes software developed by the University of -# California, Berkeley and its contributors. -# 4. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)dirs 8.2 (Berkeley) 5/4/95 - -# pushd, popd, and dirs --- written by Chris Bertin -# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris -# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW - -pushd () { - SAVE=`pwd` - if [ "$1" = "" ] - then if [ "$DSTACK" = "" ] - then echo "pushd: directory stack empty." - return 1 - fi - set $DSTACK - cd $1 || return - shift 1 - DSTACK="$*" - else cd $1 > /dev/null || return - fi - DSTACK="$SAVE $DSTACK" - dirs -} - -popd () { - if [ "$DSTACK" = "" ] - then echo "popd: directory stack empty." - return 1 - fi - set $DSTACK - cd $1 - shift - DSTACK=$* - dirs -} - -dirs () { - echo "`pwd` $DSTACK" - return 0 -} diff --git a/bin/sh/funcs/kill b/bin/sh/funcs/kill deleted file mode 100644 index 75b0180bf..000000000 --- a/bin/sh/funcs/kill +++ /dev/null @@ -1,50 +0,0 @@ -# $NetBSD: kill,v 1.7 1995/05/11 21:31:10 christos Exp $ -# Copyright (c) 1991, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Kenneth Almquist. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. All advertising materials mentioning features or use of this software -# must display the following acknowledgement: -# This product includes software developed by the University of -# California, Berkeley and its contributors. -# 4. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)kill 8.2 (Berkeley) 5/4/95 - -# Convert job names to process ids and then run /bin/kill. - -kill() { - local args x - args= - for x in "$@" - do case $x in - %*) x=`jobid "$x"` ;; - esac - args="$args $x" - done - /bin/kill $args -} diff --git a/bin/sh/funcs/login b/bin/sh/funcs/login deleted file mode 100644 index 7ae08b2b0..000000000 --- a/bin/sh/funcs/login +++ /dev/null @@ -1,39 +0,0 @@ -# $NetBSD: login,v 1.7 1995/05/11 21:31:11 christos Exp $ -# Copyright (c) 1991, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Kenneth Almquist. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. All advertising materials mentioning features or use of this software -# must display the following acknowledgement: -# This product includes software developed by the University of -# California, Berkeley and its contributors. -# 4. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)login 8.2 (Berkeley) 5/4/95 - -# replaces the login builtin in the BSD shell -login () exec login "$@" diff --git a/bin/sh/funcs/newgrp b/bin/sh/funcs/newgrp deleted file mode 100644 index 796a4f184..000000000 --- a/bin/sh/funcs/newgrp +++ /dev/null @@ -1,38 +0,0 @@ -# $NetBSD: newgrp,v 1.7 1995/05/11 21:31:12 christos Exp $ -# Copyright (c) 1991, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Kenneth Almquist. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. All advertising materials mentioning features or use of this software -# must display the following acknowledgement: -# This product includes software developed by the University of -# California, Berkeley and its contributors. -# 4. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)newgrp 8.2 (Berkeley) 5/4/95 - -newgrp() exec newgrp "$@" diff --git a/bin/sh/funcs/popd b/bin/sh/funcs/popd deleted file mode 100644 index b2b65d5c2..000000000 --- a/bin/sh/funcs/popd +++ /dev/null @@ -1,74 +0,0 @@ -# $NetBSD: popd,v 1.7 1995/05/11 21:31:13 christos Exp $ -# Copyright (c) 1991, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Kenneth Almquist. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. All advertising materials mentioning features or use of this software -# must display the following acknowledgement: -# This product includes software developed by the University of -# California, Berkeley and its contributors. -# 4. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)popd 8.2 (Berkeley) 5/4/95 - -# pushd, popd, and dirs --- written by Chris Bertin -# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris -# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW - -pushd () { - SAVE=`pwd` - if [ "$1" = "" ] - then if [ "$DSTACK" = "" ] - then echo "pushd: directory stack empty." - return 1 - fi - set $DSTACK - cd $1 || return - shift 1 - DSTACK="$*" - else cd $1 > /dev/null || return - fi - DSTACK="$SAVE $DSTACK" - dirs -} - -popd () { - if [ "$DSTACK" = "" ] - then echo "popd: directory stack empty." - return 1 - fi - set $DSTACK - cd $1 - shift - DSTACK=$* - dirs -} - -dirs () { - echo "`pwd` $DSTACK" - return 0 -} diff --git a/bin/sh/funcs/pushd b/bin/sh/funcs/pushd deleted file mode 100644 index b3930380c..000000000 --- a/bin/sh/funcs/pushd +++ /dev/null @@ -1,74 +0,0 @@ -# $NetBSD: pushd,v 1.7 1995/05/11 21:31:15 christos Exp $ -# Copyright (c) 1991, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Kenneth Almquist. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. All advertising materials mentioning features or use of this software -# must display the following acknowledgement: -# This product includes software developed by the University of -# California, Berkeley and its contributors. -# 4. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)pushd 8.2 (Berkeley) 5/4/95 - -# pushd, popd, and dirs --- written by Chris Bertin -# Pixel Computer Inc. ...!wjh12!pixel!pixutl!chris -# as modified by Patrick Elam of GTRI and Kenneth Almquist at UW - -pushd () { - SAVE=`pwd` - if [ "$1" = "" ] - then if [ "$DSTACK" = "" ] - then echo "pushd: directory stack empty." - return 1 - fi - set $DSTACK - cd $1 || return - shift 1 - DSTACK="$*" - else cd $1 > /dev/null || return - fi - DSTACK="$SAVE $DSTACK" - dirs -} - -popd () { - if [ "$DSTACK" = "" ] - then echo "popd: directory stack empty." - return 1 - fi - set $DSTACK - cd $1 - shift - DSTACK=$* - dirs -} - -dirs () { - echo "`pwd` $DSTACK" - return 0 -} diff --git a/bin/sh/funcs/suspend b/bin/sh/funcs/suspend deleted file mode 100644 index 8a4197dfe..000000000 --- a/bin/sh/funcs/suspend +++ /dev/null @@ -1,42 +0,0 @@ -# $NetBSD: suspend,v 1.7 1995/05/11 21:31:17 christos Exp $ -# Copyright (c) 1991, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Kenneth Almquist. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. All advertising materials mentioning features or use of this software -# must display the following acknowledgement: -# This product includes software developed by the University of -# California, Berkeley and its contributors. -# 4. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)suspend 8.2 (Berkeley) 5/4/95 - -suspend() { - local - - set +j - kill -TSTP 0 -} diff --git a/bin/sh/histedit.c b/bin/sh/histedit.c deleted file mode 100644 index 7c93c5466..000000000 --- a/bin/sh/histedit.c +++ /dev/null @@ -1,549 +0,0 @@ -/* $NetBSD: histedit.c,v 1.47 2014/06/18 18:17:30 christos Exp $ */ - -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: histedit.c,v 1.47 2014/06/18 18:17:30 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include -/* - * Editline and history functions (and glue). - */ -#include "shell.h" -#include "parser.h" -#include "var.h" -#include "options.h" -#include "builtins.h" -#include "main.h" -#include "output.h" -#include "mystring.h" -#include "myhistedit.h" -#include "error.h" -#include "alias.h" -#ifndef SMALL -#include "eval.h" -#include "memalloc.h" - -#define MAXHISTLOOPS 4 /* max recursions through fc */ -#define DEFEDITOR "ed" /* default editor *should* be $EDITOR */ - -History *hist; /* history cookie */ -EditLine *el; /* editline cookie */ -int displayhist; -static FILE *el_in, *el_out; -unsigned char _el_fn_complete(EditLine *, int); - -STATIC const char *fc_replace(const char *, char *, char *); - -#ifdef DEBUG -extern FILE *tracefile; -#endif - -/* - * Set history and editing status. Called whenever the status may - * have changed (figures out what to do). - */ -void -histedit(void) -{ - FILE *el_err; - -#define editing (Eflag || Vflag) - - if (iflag == 1) { - if (!hist) { - /* - * turn history on - */ - INTOFF; - hist = history_init(); - INTON; - - if (hist != NULL) - sethistsize(histsizeval()); - else - out2str("sh: can't initialize history\n"); - } - if (editing && !el && isatty(0)) { /* && isatty(2) ??? */ - /* - * turn editing on - */ - char *term, *shname; - - INTOFF; - if (el_in == NULL) - el_in = fdopen(0, "r"); - if (el_out == NULL) - el_out = fdopen(2, "w"); - if (el_in == NULL || el_out == NULL) - goto bad; - el_err = el_out; -#if DEBUG - if (tracefile) - el_err = tracefile; -#endif - term = lookupvar("TERM"); - if (term) - setenv("TERM", term, 1); - else - unsetenv("TERM"); - shname = arg0; - if (shname[0] == '-') - shname++; - el = el_init(shname, el_in, el_out, el_err); - if (el != NULL) { - if (hist) - el_set(el, EL_HIST, history, hist); - el_set(el, EL_PROMPT, getprompt); - el_set(el, EL_SIGNAL, 1); - el_set(el, EL_ALIAS_TEXT, alias_text, NULL); - el_set(el, EL_ADDFN, "rl-complete", - "ReadLine compatible completion function", - _el_fn_complete); - } else { -bad: - out2str("sh: can't initialize editing\n"); - } - INTON; - } else if (!editing && el) { - INTOFF; - el_end(el); - el = NULL; - INTON; - } - if (el) { - el_source(el, NULL); - if (Vflag) - el_set(el, EL_EDITOR, "vi"); - else if (Eflag) - el_set(el, EL_EDITOR, "emacs"); - el_set(el, EL_BIND, "^I", - tabcomplete ? "rl-complete" : "ed-insert", NULL); - } - } else { - INTOFF; - if (el) { /* no editing if not interactive */ - el_end(el); - el = NULL; - } - if (hist) { - history_end(hist); - hist = NULL; - } - INTON; - } -} - - -void -sethistsize(const char *hs) -{ - int histsize; - HistEvent he; - - if (hist != NULL) { - if (hs == NULL || *hs == '\0' || - (histsize = atoi(hs)) < 0) - histsize = 100; - history(hist, &he, H_SETSIZE, histsize); - history(hist, &he, H_SETUNIQUE, 1); - } -} - -void -setterm(const char *term) -{ - if (el != NULL && term != NULL) - if (el_set(el, EL_TERMINAL, term) != 0) { - outfmt(out2, "sh: Can't set terminal type %s\n", term); - outfmt(out2, "sh: Using dumb terminal settings.\n"); - } -} - -int -inputrc(int argc, char **argv) -{ - if (argc != 2) { - out2str("usage: inputrc file\n"); - return 1; - } - if (el != NULL) { - if (el_source(el, argv[1])) { - out2str("inputrc: failed\n"); - return 1; - } else - return 0; - } else { - out2str("sh: inputrc ignored, not editing\n"); - return 1; - } -} - -/* - * This command is provided since POSIX decided to standardize - * the Korn shell fc command. Oh well... - */ -int -histcmd(int argc, char **argv) -{ - int ch; - const char * volatile editor = NULL; - HistEvent he; - int lflg = 0; - volatile int nflg = 0, rflg = 0, sflg = 0; - int i, retval; - const char *firststr, *laststr; - int first, last, direction; - char *pat = NULL, *repl; /* ksh "fc old=new" crap */ - static int active = 0; - struct jmploc jmploc; - struct jmploc *volatile savehandler; - char editfile[MAXPATHLEN + 1]; - FILE *efp; -#ifdef __GNUC__ - repl = NULL; /* XXX gcc4 */ - efp = NULL; /* XXX gcc4 */ -#endif - - if (hist == NULL) - error("history not active"); - - if (argc == 1) - error("missing history argument"); - - optreset = 1; optind = 1; /* initialize getopt */ - while (not_fcnumber(argv[optind]) && - (ch = getopt(argc, argv, ":e:lnrs")) != -1) - switch ((char)ch) { - case 'e': - editor = optionarg; - break; - case 'l': - lflg = 1; - break; - case 'n': - nflg = 1; - break; - case 'r': - rflg = 1; - break; - case 's': - sflg = 1; - break; - case ':': - error("option -%c expects argument", optopt); - /* NOTREACHED */ - case '?': - default: - error("unknown option: -%c", optopt); - /* NOTREACHED */ - } - argc -= optind, argv += optind; - - /* - * If executing... - */ - if (lflg == 0 || editor || sflg) { - lflg = 0; /* ignore */ - editfile[0] = '\0'; - /* - * Catch interrupts to reset active counter and - * cleanup temp files. - */ - savehandler = handler; - if (setjmp(jmploc.loc)) { - active = 0; - if (*editfile) - unlink(editfile); - handler = savehandler; - longjmp(handler->loc, 1); - } - handler = &jmploc; - if (++active > MAXHISTLOOPS) { - active = 0; - displayhist = 0; - error("called recursively too many times"); - } - /* - * Set editor. - */ - if (sflg == 0) { - if (editor == NULL && - (editor = bltinlookup("FCEDIT", 1)) == NULL && - (editor = bltinlookup("EDITOR", 1)) == NULL) - editor = DEFEDITOR; - if (editor[0] == '-' && editor[1] == '\0') { - sflg = 1; /* no edit */ - editor = NULL; - } - } - } - - /* - * If executing, parse [old=new] now - */ - if (lflg == 0 && argc > 0 && - ((repl = strchr(argv[0], '=')) != NULL)) { - pat = argv[0]; - *repl++ = '\0'; - argc--, argv++; - } - - /* - * If -s is specified, accept only one operand - */ - if (sflg && argc >= 2) - error("too many args"); - - /* - * determine [first] and [last] - */ - switch (argc) { - case 0: - firststr = lflg ? "-16" : "-1"; - laststr = "-1"; - break; - case 1: - firststr = argv[0]; - laststr = lflg ? "-1" : argv[0]; - break; - case 2: - firststr = argv[0]; - laststr = argv[1]; - break; - default: - error("too many args"); - /* NOTREACHED */ - } - /* - * Turn into event numbers. - */ - first = str_to_event(firststr, 0); - last = str_to_event(laststr, 1); - - if (rflg) { - i = last; - last = first; - first = i; - } - /* - * XXX - this should not depend on the event numbers - * always increasing. Add sequence numbers or offset - * to the history element in next (diskbased) release. - */ - direction = first < last ? H_PREV : H_NEXT; - - /* - * If editing, grab a temp file. - */ - if (editor) { - int fd; - INTOFF; /* easier */ - snprintf(editfile, sizeof(editfile), "%s_shXXXXXX", _PATH_TMP); - if ((fd = mkstemp(editfile)) < 0) - error("can't create temporary file %s", editfile); - if ((efp = fdopen(fd, "w")) == NULL) { - close(fd); - error("can't allocate stdio buffer for temp"); - } - } - - /* - * Loop through selected history events. If listing or executing, - * do it now. Otherwise, put into temp file and call the editor - * after. - * - * The history interface needs rethinking, as the following - * convolutions will demonstrate. - */ - history(hist, &he, H_FIRST); - retval = history(hist, &he, H_NEXT_EVENT, first); - for (;retval != -1; retval = history(hist, &he, direction)) { - if (lflg) { - if (!nflg) - out1fmt("%5d ", he.num); - out1str(he.str); - } else { - const char *s = pat ? - fc_replace(he.str, pat, repl) : he.str; - - if (sflg) { - if (displayhist) { - out2str(s); - } - - evalstring(strcpy(stalloc(strlen(s) + 1), s), 0); - if (displayhist && hist) { - /* - * XXX what about recursive and - * relative histnums. - */ - history(hist, &he, H_ENTER, s); - } - - break; - } else - fputs(s, efp); - } - /* - * At end? (if we were to lose last, we'd sure be - * messed up). - */ - if (he.num == last) - break; - } - if (editor) { - char *editcmd; - size_t cmdlen; - - fclose(efp); - cmdlen = strlen(editor) + strlen(editfile) + 2; - editcmd = stalloc(cmdlen); - snprintf(editcmd, cmdlen, "%s %s", editor, editfile); - evalstring(editcmd, 0); /* XXX - should use no JC command */ - INTON; - readcmdfile(editfile); /* XXX - should read back - quick tst */ - unlink(editfile); - } - - if (lflg == 0 && active > 0) - --active; - if (displayhist) - displayhist = 0; - return 0; -} - -STATIC const char * -fc_replace(const char *s, char *p, char *r) -{ - char *dest; - int plen = strlen(p); - - STARTSTACKSTR(dest); - while (*s) { - if (*s == *p && strncmp(s, p, plen) == 0) { - while (*r) - STPUTC(*r++, dest); - s += plen; - *p = '\0'; /* so no more matches */ - } else - STPUTC(*s++, dest); - } - STACKSTRNUL(dest); - dest = grabstackstr(dest); - - return (dest); -} - -int -not_fcnumber(char *s) -{ - if (s == NULL) - return 0; - if (*s == '-') - s++; - return (!is_number(s)); -} - -int -str_to_event(const char *str, int last) -{ - HistEvent he; - const char *s = str; - int relative = 0; - int i, retval; - - retval = history(hist, &he, H_FIRST); - switch (*s) { - case '-': - relative = 1; - /*FALLTHROUGH*/ - case '+': - s++; - } - if (is_number(s)) { - i = atoi(s); - if (relative) { - while (retval != -1 && i--) { - retval = history(hist, &he, H_NEXT); - } - if (retval == -1) - retval = history(hist, &he, H_LAST); - } else { - retval = history(hist, &he, H_NEXT_EVENT, i); - if (retval == -1) { - /* - * the notion of first and last is - * backwards to that of the history package - */ - retval = history(hist, &he, - last ? H_FIRST : H_LAST); - } - } - if (retval == -1) - error("history number %s not found (internal error)", - str); - } else { - /* - * pattern - */ - retval = history(hist, &he, H_PREV_STR, str); - if (retval == -1) - error("history pattern not found: %s", str); - } - return (he.num); -} -#else -int -histcmd(int argc, char **argv) -{ - error("not compiled with history support"); - /* NOTREACHED */ -} -int -inputrc(int argc, char **argv) -{ - error("not compiled with history support"); - /* NOTREACHED */ -} -#endif diff --git a/bin/sh/init.h b/bin/sh/init.h deleted file mode 100644 index 60d924e99..000000000 --- a/bin/sh/init.h +++ /dev/null @@ -1,39 +0,0 @@ -/* $NetBSD: init.h,v 1.10 2003/08/07 09:05:32 agc Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)init.h 8.2 (Berkeley) 5/4/95 - */ - -void init(void); -void reset(void); -void initshellproc(void); diff --git a/bin/sh/input.c b/bin/sh/input.c deleted file mode 100644 index 50e5cfdaf..000000000 --- a/bin/sh/input.c +++ /dev/null @@ -1,550 +0,0 @@ -/* $NetBSD: input.c,v 1.46 2013/10/30 08:38:40 mrg Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95"; -#else -__RCSID("$NetBSD: input.c,v 1.46 2013/10/30 08:38:40 mrg Exp $"); -#endif -#endif /* not lint */ - -#include /* defines BUFSIZ */ -#include -#include -#include -#include -#include -#include - -/* - * This file implements the input routines used by the parser. - */ - -#include "shell.h" -#include "redir.h" -#include "syntax.h" -#include "input.h" -#include "output.h" -#include "options.h" -#include "memalloc.h" -#include "error.h" -#include "alias.h" -#include "parser.h" -#include "myhistedit.h" - -#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ - -MKINIT -struct strpush { - struct strpush *prev; /* preceding string on stack */ - char *prevstring; - int prevnleft; - int prevlleft; - struct alias *ap; /* if push was associated with an alias */ -}; - -/* - * The parsefile structure pointed to by the global variable parsefile - * contains information about the current file being read. - */ - -MKINIT -struct parsefile { - struct parsefile *prev; /* preceding file on stack */ - int linno; /* current line */ - int fd; /* file descriptor (or -1 if string) */ - int nleft; /* number of chars left in this line */ - int lleft; /* number of chars left in this buffer */ - char *nextc; /* next char in buffer */ - char *buf; /* input buffer */ - struct strpush *strpush; /* for pushing strings at this level */ - struct strpush basestrpush; /* so pushing one is fast */ -}; - - -int plinno = 1; /* input line number */ -int parsenleft; /* copy of parsefile->nleft */ -MKINIT int parselleft; /* copy of parsefile->lleft */ -char *parsenextc; /* copy of parsefile->nextc */ -MKINIT struct parsefile basepf; /* top level input file */ -MKINIT char basebuf[BUFSIZ]; /* buffer for top level input file */ -struct parsefile *parsefile = &basepf; /* current input file */ -int init_editline = 0; /* editline library initialized? */ -int whichprompt; /* 1 == PS1, 2 == PS2 */ - -STATIC void pushfile(void); -static int preadfd(void); - -#ifdef mkinit -INCLUDE -INCLUDE "input.h" -INCLUDE "error.h" - -INIT { - basepf.nextc = basepf.buf = basebuf; -} - -RESET { - if (exception != EXSHELLPROC) - parselleft = parsenleft = 0; /* clear input buffer */ - popallfiles(); -} - -SHELLPROC { - popallfiles(); -} -#endif - - -/* - * Read a line from the script. - */ - -char * -pfgets(char *line, int len) -{ - char *p = line; - int nleft = len; - int c; - - while (--nleft > 0) { - c = pgetc_macro(); - if (c == PEOF) { - if (p == line) - return NULL; - break; - } - *p++ = c; - if (c == '\n') - break; - } - *p = '\0'; - return line; -} - - - -/* - * Read a character from the script, returning PEOF on end of file. - * Nul characters in the input are silently discarded. - */ - -int -pgetc(void) -{ - return pgetc_macro(); -} - - -static int -preadfd(void) -{ - int nr; - char *buf = parsefile->buf; - parsenextc = buf; - -retry: -#ifndef SMALL - if (parsefile->fd == 0 && el) { - static const char *rl_cp; - static int el_len; - - if (rl_cp == NULL) - rl_cp = el_gets(el, &el_len); - if (rl_cp == NULL) - nr = el_len == 0 ? 0 : -1; - else { - nr = el_len; - if (nr > BUFSIZ - 8) - nr = BUFSIZ - 8; - memcpy(buf, rl_cp, nr); - if (nr != el_len) { - el_len -= nr; - rl_cp += nr; - } else - rl_cp = 0; - } - - } else -#endif - nr = read(parsefile->fd, buf, BUFSIZ - 8); - - - if (nr <= 0) { - if (nr < 0) { - if (errno == EINTR) - goto retry; - if (parsefile->fd == 0 && errno == EWOULDBLOCK) { - int flags = fcntl(0, F_GETFL, 0); - if (flags >= 0 && flags & O_NONBLOCK) { - flags &=~ O_NONBLOCK; - if (fcntl(0, F_SETFL, flags) >= 0) { - out2str("sh: turning off NDELAY mode\n"); - goto retry; - } - } - } - } - nr = -1; - } - return nr; -} - -/* - * Refill the input buffer and return the next input character: - * - * 1) If a string was pushed back on the input, pop it; - * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading - * from a string so we can't refill the buffer, return EOF. - * 3) If the is more stuff in this buffer, use it else call read to fill it. - * 4) Process input up to the next newline, deleting nul characters. - */ - -int -preadbuffer(void) -{ - char *p, *q; - int more; -#ifndef SMALL - int something; -#endif - char savec; - - if (parsefile->strpush) { - popstring(); - if (--parsenleft >= 0) - return (*parsenextc++); - } - if (parsenleft == EOF_NLEFT || parsefile->buf == NULL) - return PEOF; - flushout(&output); - flushout(&errout); - -again: - if (parselleft <= 0) { - if ((parselleft = preadfd()) == -1) { - parselleft = parsenleft = EOF_NLEFT; - return PEOF; - } - } - - q = p = parsenextc; - - /* delete nul characters */ -#ifndef SMALL - something = 0; -#endif - for (more = 1; more;) { - switch (*p) { - case '\0': - p++; /* Skip nul */ - goto check; - - case '\t': - case ' ': - break; - - case '\n': - parsenleft = q - parsenextc; - more = 0; /* Stop processing here */ - break; - - default: -#ifndef SMALL - something = 1; -#endif - break; - } - - *q++ = *p++; -check: - if (--parselleft <= 0) { - parsenleft = q - parsenextc - 1; - if (parsenleft < 0) - goto again; - *q = '\0'; - more = 0; - } - } - - savec = *q; - *q = '\0'; - -#ifndef SMALL - if (parsefile->fd == 0 && hist && something) { - HistEvent he; - INTOFF; - history(hist, &he, whichprompt == 1? H_ENTER : H_APPEND, - parsenextc); - INTON; - } -#endif - - if (vflag) { - out2str(parsenextc); - flushout(out2); - } - - *q = savec; - - return *parsenextc++; -} - -/* - * Undo the last call to pgetc. Only one character may be pushed back. - * PEOF may be pushed back. - */ - -void -pungetc(void) -{ - parsenleft++; - parsenextc--; -} - -/* - * Push a string back onto the input at this current parsefile level. - * We handle aliases this way. - */ -void -pushstring(char *s, int len, void *ap) -{ - struct strpush *sp; - - INTOFF; -/*debugprintf("*** calling pushstring: %s, %d\n", s, len);*/ - if (parsefile->strpush) { - sp = ckmalloc(sizeof (struct strpush)); - sp->prev = parsefile->strpush; - parsefile->strpush = sp; - } else - sp = parsefile->strpush = &(parsefile->basestrpush); - sp->prevstring = parsenextc; - sp->prevnleft = parsenleft; - sp->prevlleft = parselleft; - sp->ap = (struct alias *)ap; - if (ap) - ((struct alias *)ap)->flag |= ALIASINUSE; - parsenextc = s; - parsenleft = len; - INTON; -} - -void -popstring(void) -{ - struct strpush *sp = parsefile->strpush; - - INTOFF; - parsenextc = sp->prevstring; - parsenleft = sp->prevnleft; - parselleft = sp->prevlleft; -/*debugprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/ - if (sp->ap) - sp->ap->flag &= ~ALIASINUSE; - parsefile->strpush = sp->prev; - if (sp != &(parsefile->basestrpush)) - ckfree(sp); - INTON; -} - -/* - * Set the input to take input from a file. If push is set, push the - * old input onto the stack first. - */ - -void -setinputfile(const char *fname, int push) -{ - unsigned char magic[4]; - int fd; - int fd2; - - INTOFF; - if ((fd = open(fname, O_RDONLY)) < 0) - error("Can't open %s", fname); - - /* Since the message "Syntax error: "(" unexpected" is not very - * helpful, we check if the file starts with the ELF magic to - * avoid that message. The first lseek tries to make sure that - * we can later rewind the file. - */ - if (lseek(fd, 0, SEEK_SET) == 0) { - if (read(fd, magic, 4) == 4) { - if (memcmp(magic, "\177ELF", 4) == 0) - error("Cannot execute ELF binary %s", fname); - } - if (lseek(fd, 0, SEEK_SET) != 0) - error("Cannot rewind the file %s", fname); - } - - if (fd < 10) { - fd2 = copyfd(fd, 10, 0); - close(fd); - if (fd2 < 0) - error("Out of file descriptors"); - fd = fd2; - } - setinputfd(fd, push); - INTON; -} - - -/* - * Like setinputfile, but takes an open file descriptor. Call this with - * interrupts off. - */ - -void -setinputfd(int fd, int push) -{ - (void) fcntl(fd, F_SETFD, FD_CLOEXEC); - if (push) { - pushfile(); - parsefile->buf = ckmalloc(BUFSIZ); - } - if (parsefile->fd > 0) - close(parsefile->fd); - parsefile->fd = fd; - if (parsefile->buf == NULL) - parsefile->buf = ckmalloc(BUFSIZ); - parselleft = parsenleft = 0; - plinno = 1; -} - - -/* - * Like setinputfile, but takes input from a string. - */ - -void -setinputstring(char *string, int push) -{ - INTOFF; - if (push) - pushfile(); - parsenextc = string; - parselleft = parsenleft = strlen(string); - parsefile->buf = NULL; - plinno = 1; - INTON; -} - - - -/* - * To handle the "." command, a stack of input files is used. Pushfile - * adds a new entry to the stack and popfile restores the previous level. - */ - -STATIC void -pushfile(void) -{ - struct parsefile *pf; - - parsefile->nleft = parsenleft; - parsefile->lleft = parselleft; - parsefile->nextc = parsenextc; - parsefile->linno = plinno; - pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile)); - pf->prev = parsefile; - pf->fd = -1; - pf->strpush = NULL; - pf->basestrpush.prev = NULL; - parsefile = pf; -} - - -void -popfile(void) -{ - struct parsefile *pf = parsefile; - - INTOFF; - if (pf->fd >= 0) - close(pf->fd); - if (pf->buf) - ckfree(pf->buf); - while (pf->strpush) - popstring(); - parsefile = pf->prev; - ckfree(pf); - parsenleft = parsefile->nleft; - parselleft = parsefile->lleft; - parsenextc = parsefile->nextc; - plinno = parsefile->linno; - INTON; -} - - -/* - * Return to top level. - */ - -void -popallfiles(void) -{ - while (parsefile != &basepf) - popfile(); -} - - - -/* - * Close the file(s) that the shell is reading commands from. Called - * after a fork is done. - * - * Takes one arg, vfork, which tells it to not modify its global vars - * as it is still running in the parent. - * - * This code is (probably) unnecessary as the 'close on exec' flag is - * set and should be enough. In the vfork case it is definitely wrong - * to close the fds as another fork() may be done later to feed data - * from a 'here' document into a pipe and we don't want to close the - * pipe! - */ - -void -closescript(int vforked) -{ - if (vforked) - return; - popallfiles(); - if (parsefile->fd > 0) { - close(parsefile->fd); - parsefile->fd = 0; - } -} diff --git a/bin/sh/input.h b/bin/sh/input.h deleted file mode 100644 index a9d3a12b4..000000000 --- a/bin/sh/input.h +++ /dev/null @@ -1,62 +0,0 @@ -/* $NetBSD: input.h,v 1.15 2003/08/07 09:05:33 agc Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)input.h 8.2 (Berkeley) 5/4/95 - */ - -/* PEOF (the end of file marker) is defined in syntax.h */ - -/* - * The input line number. Input.c just defines this variable, and saves - * and restores it when files are pushed and popped. The user of this - * package must set its value. - */ -extern int plinno; -extern int parsenleft; /* number of characters left in input buffer */ -extern char *parsenextc; /* next character in input buffer */ -extern int init_editline; /* 0 == not setup, 1 == OK, -1 == failed */ - -char *pfgets(char *, int); -int pgetc(void); -int preadbuffer(void); -void pungetc(void); -void pushstring(char *, int, void *); -void popstring(void); -void setinputfile(const char *, int); -void setinputfd(int, int); -void setinputstring(char *, int); -void popfile(void); -void popallfiles(void); -void closescript(int); - -#define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer()) diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c deleted file mode 100644 index 377f8ead0..000000000 --- a/bin/sh/jobs.c +++ /dev/null @@ -1,1532 +0,0 @@ -/* $NetBSD: jobs.c,v 1.75 2015/08/22 12:12:47 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: jobs.c,v 1.75 2015/08/22 12:12:47 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef BSD -#include -#include -#include -#endif -#include - -#include "shell.h" -#if JOBS -#if OLD_TTY_DRIVER -#include "sgtty.h" -#else -#include -#endif -#undef CEOF /* syntax.h redefines this */ -#endif -#include "redir.h" -#include "show.h" -#include "main.h" -#include "parser.h" -#include "nodes.h" -#include "jobs.h" -#include "options.h" -#include "builtins.h" -#include "trap.h" -#include "syntax.h" -#include "input.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" -#include "mystring.h" - - -static struct job *jobtab; /* array of jobs */ -static int njobs; /* size of array */ -static int jobs_invalid; /* set in child */ -MKINIT pid_t backgndpid = -1; /* pid of last background process */ -#if JOBS -int initialpgrp; /* pgrp of shell on invocation */ -static int curjob = -1; /* current job */ -#endif -#if JOBS && defined(__minix) -static int ttyfd = -1; -#endif /* JOBS && defined(__minix) */ - -STATIC void restartjob(struct job *); -STATIC void freejob(struct job *); -STATIC struct job *getjob(const char *, int); -STATIC int dowait(int, struct job *); -#define WBLOCK 1 -#define WNOFREE 2 -STATIC int waitproc(int, struct job *, int *); -STATIC void cmdtxt(union node *); -STATIC void cmdlist(union node *, int); -STATIC void cmdputs(const char *); - -#ifdef SYSV -STATIC int onsigchild(void); -#endif - -#ifdef OLD_TTY_DRIVER -static pid_t tcgetpgrp(int fd); -static int tcsetpgrp(int fd, pid_t pgrp); - -static pid_t -tcgetpgrp(int fd) -{ - pid_t pgrp; - if (ioctl(fd, TIOCGPGRP, (char *)&pgrp) == -1) - return -1; - else - return pgrp; -} - -static int -tcsetpgrp(int fd, pid_tpgrp) -{ - return ioctl(fd, TIOCSPGRP, (char *)&pgrp); -} -#endif - -/* - * Turn job control on and off. - * - * Note: This code assumes that the third arg to ioctl is a character - * pointer, which is true on Berkeley systems but not System V. Since - * System V doesn't have job control yet, this isn't a problem now. - */ - -MKINIT int jobctl; - -#if JOBS /* Minix setjobctl is defined to empty, compilation error */ -void -setjobctl(int on) -{ -#ifdef OLD_TTY_DRIVER - int ldisc; -#endif - - if (on == jobctl || rootshell == 0) - return; - if (on) { -#if defined(FIOCLEX) || defined(FD_CLOEXEC) - int err; - int i; - if (ttyfd != -1) - close(ttyfd); - if ((ttyfd = open("/dev/tty", O_RDWR)) == -1) { - for (i = 0; i < 3; i++) { - if (isatty(i) && (ttyfd = dup(i)) != -1) - break; - } - if (i == 3) - goto out; - } - /* Move to a high fd */ - for (i = 10; i > 2; i--) { - if ((err = fcntl(ttyfd, F_DUPFD, (1 << i) - 1)) != -1) - break; - } - if (err != -1) { - close(ttyfd); - ttyfd = err; - } -#ifdef FIOCLEX - err = ioctl(ttyfd, FIOCLEX, 0); -#elif FD_CLOEXEC - err = fcntl(ttyfd, F_SETFD, - fcntl(ttyfd, F_GETFD, 0) | FD_CLOEXEC); -#endif - if (err == -1) { - close(ttyfd); - ttyfd = -1; - goto out; - } -#else - out2str("sh: Need FIOCLEX or FD_CLOEXEC to support job control"); - goto out; -#endif - do { /* while we are in the background */ - if ((initialpgrp = tcgetpgrp(ttyfd)) < 0) { -out: - out2str("sh: can't access tty; job control turned off\n"); - mflag = 0; - return; - } - if (initialpgrp == -1) - initialpgrp = getpgrp(); - else if (initialpgrp != getpgrp()) { - killpg(0, SIGTTIN); - continue; - } - } while (0); - -#ifdef OLD_TTY_DRIVER - if (ioctl(ttyfd, TIOCGETD, (char *)&ldisc) < 0 - || ldisc != NTTYDISC) { - out2str("sh: need new tty driver to run job control; job control turned off\n"); - mflag = 0; - return; - } -#endif - setsignal(SIGTSTP, 0); - setsignal(SIGTTOU, 0); - setsignal(SIGTTIN, 0); - if (getpgrp() != rootpid && setpgid(0, rootpid) == -1) - error("Cannot set process group (%s) at %d", - strerror(errno), __LINE__); - if (tcsetpgrp(ttyfd, rootpid) == -1) - error("Cannot set tty process group (%s) at %d", - strerror(errno), __LINE__); - } else { /* turning job control off */ - if (getpgrp() != initialpgrp && setpgid(0, initialpgrp) == -1) - error("Cannot set process group (%s) at %d", - strerror(errno), __LINE__); - if (tcsetpgrp(ttyfd, initialpgrp) == -1) - error("Cannot set tty process group (%s) at %d", - strerror(errno), __LINE__); - close(ttyfd); - ttyfd = -1; - setsignal(SIGTSTP, 0); - setsignal(SIGTTOU, 0); - setsignal(SIGTTIN, 0); - } - jobctl = on; -} -#endif /* JOBS */ - - -#ifdef mkinit -INCLUDE - -SHELLPROC { - backgndpid = -1; -#if JOBS - jobctl = 0; -#endif -} - -#endif - - - -#if JOBS -static int -do_fgcmd(const char *arg_ptr) -{ - struct job *jp; - int i; - int status; - - jp = getjob(arg_ptr, 0); - if (jp->jobctl == 0) - error("job not created under job control"); - out1fmt("%s", jp->ps[0].cmd); - for (i = 1; i < jp->nprocs; i++) - out1fmt(" | %s", jp->ps[i].cmd ); - out1c('\n'); - flushall(); - - for (i = 0; i < jp->nprocs; i++) - if (tcsetpgrp(ttyfd, jp->ps[i].pid) != -1) - break; - - if (i >= jp->nprocs) { - error("Cannot set tty process group (%s) at %d", - strerror(errno), __LINE__); - } - restartjob(jp); - INTOFF; - status = waitforjob(jp); - INTON; - return status; -} - -int -fgcmd(int argc, char **argv) -{ - nextopt(""); - return do_fgcmd(*argptr); -} - -int -fgcmd_percent(int argc, char **argv) -{ - nextopt(""); - return do_fgcmd(*argv); -} - -static void -set_curjob(struct job *jp, int mode) -{ - struct job *jp1, *jp2; - int i, ji; - - ji = jp - jobtab; - - /* first remove from list */ - if (ji == curjob) - curjob = jp->prev_job; - else { - for (i = 0; i < njobs; i++) { - if (jobtab[i].prev_job != ji) - continue; - jobtab[i].prev_job = jp->prev_job; - break; - } - } - - /* Then re-insert in correct position */ - switch (mode) { - case 0: /* job being deleted */ - jp->prev_job = -1; - break; - case 1: /* newly created job or backgrounded job, - put after all stopped jobs. */ - if (curjob != -1 && jobtab[curjob].state == JOBSTOPPED) { - for (jp1 = jobtab + curjob; ; jp1 = jp2) { - if (jp1->prev_job == -1) - break; - jp2 = jobtab + jp1->prev_job; - if (jp2->state != JOBSTOPPED) - break; - } - jp->prev_job = jp1->prev_job; - jp1->prev_job = ji; - break; - } - /* FALLTHROUGH */ - case 2: /* newly stopped job - becomes curjob */ - jp->prev_job = curjob; - curjob = ji; - break; - } -} - -int -bgcmd(int argc, char **argv) -{ - struct job *jp; - int i; - - nextopt(""); - do { - jp = getjob(*argptr, 0); - if (jp->jobctl == 0) - error("job not created under job control"); - set_curjob(jp, 1); - out1fmt("[%ld] %s", (long)(jp - jobtab + 1), jp->ps[0].cmd); - for (i = 1; i < jp->nprocs; i++) - out1fmt(" | %s", jp->ps[i].cmd ); - out1c('\n'); - flushall(); - restartjob(jp); - } while (*argptr && *++argptr); - return 0; -} - - -STATIC void -restartjob(struct job *jp) -{ - struct procstat *ps; - int i; - - if (jp->state == JOBDONE) - return; - INTOFF; - for (i = 0; i < jp->nprocs; i++) - if (killpg(jp->ps[i].pid, SIGCONT) != -1) - break; - if (i >= jp->nprocs) - error("Cannot continue job (%s)", strerror(errno)); - for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) { - if (WIFSTOPPED(ps->status)) { - ps->status = -1; - jp->state = JOBRUNNING; - } - } - INTON; -} -#else -/* LSC: For Minix add dummy functions. */ -int -fgcmd(int argc, char **argv) -{ - error("no job control in this shell."); - return 1; -} - -int -fgcmd_percent(int argc, char **argv) -{ - error("no job control in this shell."); - return 1; -} - - -int -bgcmd(int argc, char **argv) -{ - error("no job control in this shell."); - return 1; -} -#endif - -static void -showjob(struct output *out, struct job *jp, int mode) -{ - int procno; - int st; - struct procstat *ps; - int col; - char s[64]; - -#if JOBS - if (mode & SHOW_PGID) { - /* just output process (group) id of pipeline */ - outfmt(out, "%ld\n", (long)jp->ps->pid); - return; - } -#endif - - procno = jp->nprocs; - if (!procno) - return; - - if (mode & SHOW_PID) - mode |= SHOW_MULTILINE; - - if ((procno > 1 && !(mode & SHOW_MULTILINE)) - || (mode & SHOW_SIGNALLED)) { - /* See if we have more than one status to report */ - ps = jp->ps; - st = ps->status; - do { - int st1 = ps->status; - if (st1 != st) - /* yes - need multi-line output */ - mode |= SHOW_MULTILINE; - if (st1 == -1 || !(mode & SHOW_SIGNALLED) || WIFEXITED(st1)) - continue; - if (WIFSTOPPED(st1) || ((st1 = WTERMSIG(st1) & 0x7f) - && st1 != SIGINT && st1 != SIGPIPE)) - mode |= SHOW_ISSIG; - - } while (ps++, --procno); - procno = jp->nprocs; - } - - if (mode & SHOW_SIGNALLED && !(mode & SHOW_ISSIG)) { - if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE)) { - TRACE(("showjob: freeing job %d\n", jp - jobtab + 1)); - freejob(jp); - } - return; - } - - for (ps = jp->ps; --procno >= 0; ps++) { /* for each process */ - if (ps == jp->ps) - fmtstr(s, 16, "[%ld] %c ", - (long)(jp - jobtab + 1), -#if JOBS - jp == jobtab + curjob ? '+' : - curjob != -1 && jp == jobtab + - jobtab[curjob].prev_job ? '-' : -#endif - ' '); - else - fmtstr(s, 16, " " ); - col = strlen(s); - if (mode & SHOW_PID) { - fmtstr(s + col, 16, "%ld ", (long)ps->pid); - col += strlen(s + col); - } - if (ps->status == -1) { - scopy("Running", s + col); - } else if (WIFEXITED(ps->status)) { - st = WEXITSTATUS(ps->status); - if (st) - fmtstr(s + col, 16, "Done(%d)", st); - else - fmtstr(s + col, 16, "Done"); - } else { -#if JOBS - if (WIFSTOPPED(ps->status)) - st = WSTOPSIG(ps->status); - else /* WIFSIGNALED(ps->status) */ -#endif - st = WTERMSIG(ps->status); - st &= 0x7f; - if (st < NSIG && sys_siglist[st]) - scopyn(sys_siglist[st], s + col, 32); - else - fmtstr(s + col, 16, "Signal %d", st); - if (WCOREDUMP(ps->status)) { - col += strlen(s + col); - scopyn(" (core dumped)", s + col, 64 - col); - } - } - col += strlen(s + col); - outstr(s, out); - do { - outc(' ', out); - col++; - } while (col < 30); - outstr(ps->cmd, out); - if (mode & SHOW_MULTILINE) { - if (procno > 0) { - outc(' ', out); - outc('|', out); - } - } else { - while (--procno >= 0) - outfmt(out, " | %s", (++ps)->cmd ); - } - outc('\n', out); - } - flushout(out); - jp->changed = 0; - if (jp->state == JOBDONE && !(mode & SHOW_NO_FREE)) - freejob(jp); -} - - -int -jobscmd(int argc, char **argv) -{ - int mode, m; - int sv = jobs_invalid; - - jobs_invalid = 0; - mode = 0; - while ((m = nextopt("lp"))) - if (m == 'l') - mode = SHOW_PID; - else - mode = SHOW_PGID; - if (*argptr) - do - showjob(out1, getjob(*argptr,0), mode); - while (*++argptr); - else - showjobs(out1, mode); - jobs_invalid = sv; - return 0; -} - - -/* - * Print a list of jobs. If "change" is nonzero, only print jobs whose - * statuses have changed since the last call to showjobs. - * - * If the shell is interrupted in the process of creating a job, the - * result may be a job structure containing zero processes. Such structures - * will be freed here. - */ - -void -showjobs(struct output *out, int mode) -{ - int jobno; - struct job *jp; -#if JOBS /* MINIX: gotpid. */ - int silent = 0, gotpid; -#else - int silent = 0; -#endif - - TRACE(("showjobs(%x) called\n", mode)); - - /* If not even one one job changed, there is nothing to do */ -#if JOBS /* MINIX: gotpid. */ - gotpid = dowait(0, NULL); -#endif - while (dowait(0, NULL) > 0) - continue; -#if JOBS /* MINIX: #ifdef fails when JOBS = 0 */ - /* - * Check if we are not in our foreground group, and if not - * put us in it. - */ - if (mflag && gotpid != -1 && tcgetpgrp(ttyfd) != getpid()) { - if (tcsetpgrp(ttyfd, getpid()) == -1) - error("Cannot set tty process group (%s) at %d", - strerror(errno), __LINE__); - TRACE(("repaired tty process group\n")); - silent = 1; - } -#endif - if (jobs_invalid) - return; - - for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) { - if (!jp->used) - continue; - if (jp->nprocs == 0) { - freejob(jp); - continue; - } - if ((mode & SHOW_CHANGED) && !jp->changed) - continue; - if (silent && jp->changed) { - jp->changed = 0; - continue; - } - showjob(out, jp, mode); - } -} - -/* - * Mark a job structure as unused. - */ - -STATIC void -freejob(struct job *jp) -{ - INTOFF; - if (jp->ps != &jp->ps0) { - ckfree(jp->ps); - jp->ps = &jp->ps0; - } - jp->nprocs = 0; - jp->used = 0; -#if JOBS - set_curjob(jp, 0); -#endif - INTON; -} - - - -int -waitcmd(int argc, char **argv) -{ - struct job *job; - int status, retval; - struct job *jp; - - nextopt(""); - - if (!*argptr) { - /* wait for all jobs */ - jp = jobtab; - if (jobs_invalid) - return 0; - for (;;) { - if (jp >= jobtab + njobs) { - /* no running procs */ - return 0; - } - if (!jp->used || jp->state != JOBRUNNING) { - jp++; - continue; - } - if (dowait(WBLOCK, NULL) == -1) - return 128 + lastsig(); - jp = jobtab; - } - } - - retval = 127; /* XXXGCC: -Wuninitialized */ - for (; *argptr; argptr++) { - job = getjob(*argptr, 1); - if (!job) { - retval = 127; - continue; - } - /* loop until process terminated or stopped */ - while (job->state == JOBRUNNING) { - if (dowait(WBLOCK|WNOFREE, job) == -1) - return 128 + lastsig(); - } - status = job->ps[job->nprocs ? job->nprocs - 1 : 0].status; - if (WIFEXITED(status)) - retval = WEXITSTATUS(status); -#if JOBS - else if (WIFSTOPPED(status)) - retval = WSTOPSIG(status) + 128; -#endif - else { - /* XXX: limits number of signals */ - retval = WTERMSIG(status) + 128; - } - if (!iflag) - freejob(job); - } - return retval; -} - - - -int -jobidcmd(int argc, char **argv) -{ - struct job *jp; - int i; - - nextopt(""); - jp = getjob(*argptr, 0); - for (i = 0 ; i < jp->nprocs ; ) { - out1fmt("%ld", (long)jp->ps[i].pid); - out1c(++i < jp->nprocs ? ' ' : '\n'); - } - return 0; -} - -int -getjobpgrp(const char *name) -{ - struct job *jp; - - jp = getjob(name, 1); - if (jp == 0) - return 0; - return -jp->ps[0].pid; -} - -/* - * Convert a job name to a job structure. - */ - -STATIC struct job * -getjob(const char *name, int noerror) -{ - int jobno = -1; - struct job *jp; - int pid; - int i; - const char *err_msg = "No such job: %s"; - - if (name == NULL) { -#if JOBS - jobno = curjob; -#endif - err_msg = "No current job"; - } else if (name[0] == '%') { - if (is_number(name + 1)) { - jobno = number(name + 1) - 1; - } else if (!name[2]) { - switch (name[1]) { -#if JOBS - case 0: - case '+': - case '%': - jobno = curjob; - err_msg = "No current job"; - break; - case '-': - jobno = curjob; - if (jobno != -1) - jobno = jobtab[jobno].prev_job; - err_msg = "No previous job"; - break; -#endif - default: - goto check_pattern; - } - } else { - struct job *found; - check_pattern: - found = NULL; - for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { - if (!jp->used || jp->nprocs <= 0) - continue; - if ((name[1] == '?' - && strstr(jp->ps[0].cmd, name + 2)) - || prefix(name + 1, jp->ps[0].cmd)) { - if (found) { - err_msg = "%s: ambiguous"; - found = 0; - break; - } - found = jp; - } - } - if (found) - return found; - } - - } else if (is_number(name)) { - pid = number(name); - for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { - if (jp->used && jp->nprocs > 0 - && jp->ps[jp->nprocs - 1].pid == pid) - return jp; - } - } - - if (!jobs_invalid && jobno >= 0 && jobno < njobs) { - jp = jobtab + jobno; - if (jp->used) - return jp; - } - if (!noerror) - error(err_msg, name); - return 0; -} - - - -/* - * Return a new job structure, - */ - -struct job * -makejob(union node *node, int nprocs) -{ - int i; - struct job *jp; - - if (jobs_invalid) { - for (i = njobs, jp = jobtab ; --i >= 0 ; jp++) { - if (jp->used) - freejob(jp); - } - jobs_invalid = 0; - } - - for (i = njobs, jp = jobtab ; ; jp++) { - if (--i < 0) { - INTOFF; - if (njobs == 0) { - jobtab = ckmalloc(4 * sizeof jobtab[0]); - } else { - jp = ckmalloc((njobs + 4) * sizeof jobtab[0]); - memcpy(jp, jobtab, njobs * sizeof jp[0]); - /* Relocate `ps' pointers */ - for (i = 0; i < njobs; i++) - if (jp[i].ps == &jobtab[i].ps0) - jp[i].ps = &jp[i].ps0; - ckfree(jobtab); - jobtab = jp; - } - jp = jobtab + njobs; - for (i = 4 ; --i >= 0 ; ) - jobtab[njobs++].used = 0; - INTON; - break; - } - if (jp->used == 0) - break; - } - INTOFF; - jp->state = JOBRUNNING; - jp->used = 1; - jp->changed = 0; - jp->nprocs = 0; -#if JOBS - jp->jobctl = jobctl; - set_curjob(jp, 1); -#endif - if (nprocs > 1) { - jp->ps = ckmalloc(nprocs * sizeof (struct procstat)); - } else { - jp->ps = &jp->ps0; - } - INTON; - TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs, - jp - jobtab + 1)); - return jp; -} - - -/* - * Fork off a subshell. If we are doing job control, give the subshell its - * own process group. Jp is a job structure that the job is to be added to. - * N is the command that will be evaluated by the child. Both jp and n may - * be NULL. The mode parameter can be one of the following: - * FORK_FG - Fork off a foreground process. - * FORK_BG - Fork off a background process. - * FORK_NOJOB - Like FORK_FG, but don't give the process its own - * process group even if job control is on. - * - * When job control is turned off, background processes have their standard - * input redirected to /dev/null (except for the second and later processes - * in a pipeline). - */ - -int -forkshell(struct job *jp, union node *n, int mode) -{ - pid_t pid; - int serrno; - - TRACE(("forkshell(%%%d, %p, %d) called\n", jp - jobtab, n, mode)); - switch ((pid = fork())) { - case -1: - serrno = errno; - TRACE(("Fork failed, errno=%d\n", serrno)); - INTON; - error("Cannot fork (%s)", strerror(serrno)); - break; - case 0: - forkchild(jp, n, mode, 0); - return 0; - default: - return forkparent(jp, n, mode, pid); - } -} - -int -forkparent(struct job *jp, union node *n, int mode, pid_t pid) -{ - int pgrp; - - if (rootshell && mode != FORK_NOJOB && mflag) { - if (jp == NULL || jp->nprocs == 0) - pgrp = pid; - else - pgrp = jp->ps[0].pid; - /* This can fail because we are doing it in the child also */ - (void)setpgid(pid, pgrp); - } - if (mode == FORK_BG) - backgndpid = pid; /* set $! */ - if (jp) { - struct procstat *ps = &jp->ps[jp->nprocs++]; - ps->pid = pid; - ps->status = -1; - ps->cmd[0] = 0; - if (/* iflag && rootshell && */ n) - commandtext(ps, n); - } - TRACE(("In parent shell: child = %d\n", pid)); - return pid; -} - -void -forkchild(struct job *jp, union node *n, int mode, int vforked) -{ - int wasroot; -#if JOBS /* LSC: for proper compilation with JOBS == 0 */ - int pgrp; -#endif - const char *devnull = _PATH_DEVNULL; - const char *nullerr = "Can't open %s"; - - wasroot = rootshell; - TRACE(("Child shell %d\n", getpid())); - if (!vforked) - rootshell = 0; - - closescript(vforked); - clear_traps(vforked); -#if JOBS - if (!vforked) - jobctl = 0; /* do job control only in root shell */ - if (wasroot && mode != FORK_NOJOB && mflag) { - if (jp == NULL || jp->nprocs == 0) - pgrp = getpid(); - else - pgrp = jp->ps[0].pid; - /* This can fail because we are doing it in the parent also */ - (void)setpgid(0, pgrp); - if (mode == FORK_FG) { - if (tcsetpgrp(ttyfd, pgrp) == -1) - error("Cannot set tty process group (%s) at %d", - strerror(errno), __LINE__); - } - setsignal(SIGTSTP, vforked); - setsignal(SIGTTOU, vforked); - } else if (mode == FORK_BG) { - ignoresig(SIGINT, vforked); - ignoresig(SIGQUIT, vforked); - if ((jp == NULL || jp->nprocs == 0) && - ! fd0_redirected_p ()) { - close(0); - if (open(devnull, O_RDONLY) != 0) - error(nullerr, devnull); - } - } -#else - if (mode == FORK_BG) { - ignoresig(SIGINT, vforked); - ignoresig(SIGQUIT, vforked); - if ((jp == NULL || jp->nprocs == 0) && - ! fd0_redirected_p ()) { - close(0); - if (open(devnull, O_RDONLY) != 0) - error(nullerr, devnull); - } - } -#endif - if (wasroot && iflag) { - setsignal(SIGINT, vforked); - setsignal(SIGQUIT, vforked); - setsignal(SIGTERM, vforked); - } - - if (!vforked) - jobs_invalid = 1; -} - -/* - * Wait for job to finish. - * - * Under job control we have the problem that while a child process is - * running interrupts generated by the user are sent to the child but not - * to the shell. This means that an infinite loop started by an inter- - * active user may be hard to kill. With job control turned off, an - * interactive user may place an interactive program inside a loop. If - * the interactive program catches interrupts, the user doesn't want - * these interrupts to also abort the loop. The approach we take here - * is to have the shell ignore interrupt signals while waiting for a - * forground process to terminate, and then send itself an interrupt - * signal if the child process was terminated by an interrupt signal. - * Unfortunately, some programs want to do a bit of cleanup and then - * exit on interrupt; unless these processes terminate themselves by - * sending a signal to themselves (instead of calling exit) they will - * confuse this approach. - */ - -int -waitforjob(struct job *jp) -{ -#if JOBS - int mypgrp = getpgrp(); -#endif - int status; - int st; - - INTOFF; - TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1)); - while (jp->state == JOBRUNNING) { - dowait(WBLOCK, jp); - } -#if JOBS - if (jp->jobctl) { - if (tcsetpgrp(ttyfd, mypgrp) == -1) - error("Cannot set tty process group (%s) at %d", - strerror(errno), __LINE__); - } - if (jp->state == JOBSTOPPED && curjob != jp - jobtab) - set_curjob(jp, 2); -#endif - status = jp->ps[jp->nprocs - 1].status; - /* convert to 8 bits */ - if (WIFEXITED(status)) - st = WEXITSTATUS(status); -#if JOBS - else if (WIFSTOPPED(status)) - st = WSTOPSIG(status) + 128; -#endif - else - st = WTERMSIG(status) + 128; - TRACE(("waitforjob: job %d, nproc %d, status %x, st %x\n", - jp - jobtab + 1, jp->nprocs, status, st )); -#if JOBS - if (jp->jobctl) { - /* - * This is truly gross. - * If we're doing job control, then we did a TIOCSPGRP which - * caused us (the shell) to no longer be in the controlling - * session -- so we wouldn't have seen any ^C/SIGINT. So, we - * intuit from the subprocess exit status whether a SIGINT - * occurred, and if so interrupt ourselves. Yuck. - mycroft - */ - if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT) - raise(SIGINT); - } -#endif - if (! JOBS || jp->state == JOBDONE) - freejob(jp); - INTON; - return st; -} - - - -/* - * Wait for a process to terminate. - */ - -STATIC int -dowait(int flags, struct job *job) -{ - int pid; - int status; - struct procstat *sp; - struct job *jp; - struct job *thisjob; - int done; - int stopped; - - TRACE(("dowait(%x) called\n", flags)); - do { - pid = waitproc(flags & WBLOCK, job, &status); - TRACE(("wait returns pid %d, status %d\n", pid, status)); - } while (pid == -1 && errno == EINTR && pendingsigs == 0); - if (pid <= 0) - return pid; - INTOFF; - thisjob = NULL; - for (jp = jobtab ; jp < jobtab + njobs ; jp++) { - if (jp->used) { - done = 1; - stopped = 1; - for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) { - if (sp->pid == -1) - continue; - if (sp->pid == pid) { - TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jp - jobtab + 1, pid, sp->status, status)); - sp->status = status; - thisjob = jp; - } - if (sp->status == -1) - stopped = 0; - else if (WIFSTOPPED(sp->status)) - done = 0; - } - if (stopped) { /* stopped or done */ - int state = done ? JOBDONE : JOBSTOPPED; - if (jp->state != state) { - TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state)); - jp->state = state; -#if JOBS - if (done) - set_curjob(jp, 0); -#endif - } - } - } - } - - if (thisjob && thisjob->state != JOBRUNNING) { - int mode = 0; - if (!rootshell || !iflag) - mode = SHOW_SIGNALLED; - if ((job == thisjob && (flags & WNOFREE) == 0) || - (job != thisjob && (flags & WNOFREE) != 0)) - mode = SHOW_SIGNALLED | SHOW_NO_FREE; - if (mode) - showjob(out2, thisjob, mode); - else { - TRACE(("Not printing status, rootshell=%d, job=%p\n", - rootshell, job)); - thisjob->changed = 1; - } - } - - INTON; - return pid; -} - - - -/* - * Do a wait system call. If job control is compiled in, we accept - * stopped processes. If block is zero, we return a value of zero - * rather than blocking. - * - * System V doesn't have a non-blocking wait system call. It does - * have a SIGCLD signal that is sent to a process when one of its - * children dies. The obvious way to use SIGCLD would be to install - * a handler for SIGCLD which simply bumped a counter when a SIGCLD - * was received, and have waitproc bump another counter when it got - * the status of a process. Waitproc would then know that a wait - * system call would not block if the two counters were different. - * This approach doesn't work because if a process has children that - * have not been waited for, System V will send it a SIGCLD when it - * installs a signal handler for SIGCLD. What this means is that when - * a child exits, the shell will be sent SIGCLD signals continuously - * until is runs out of stack space, unless it does a wait call before - * restoring the signal handler. The code below takes advantage of - * this (mis)feature by installing a signal handler for SIGCLD and - * then checking to see whether it was called. If there are any - * children to be waited for, it will be. - * - * If neither SYSV nor BSD is defined, we don't implement nonblocking - * waits at all. In this case, the user will not be informed when - * a background process until the next time she runs a real program - * (as opposed to running a builtin command or just typing return), - * and the jobs command may give out of date information. - */ - -#ifdef SYSV -STATIC int gotsigchild; - -STATIC int onsigchild() { - gotsigchild = 1; -} -#endif - - -STATIC int -waitproc(int block, struct job *jp, int *status) -{ -#ifdef BSD - int flags = 0; - -#if JOBS - if (jp != NULL && jp->jobctl) - flags |= WUNTRACED; -#endif - if (block == 0) - flags |= WNOHANG; - return waitpid(-1, status, flags); -#else -#ifdef SYSV - int (*save)(); - - if (block == 0) { - gotsigchild = 0; - save = signal(SIGCLD, onsigchild); - signal(SIGCLD, save); - if (gotsigchild == 0) - return 0; - } - return wait(status); -#else - if (block == 0) - return 0; - return wait(status); -#endif -#endif -} - -/* - * return 1 if there are stopped jobs, otherwise 0 - */ -int job_warning = 0; -int -stoppedjobs(void) -{ - int jobno; - struct job *jp; - - if (job_warning || jobs_invalid) - return (0); - for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) { - if (jp->used == 0) - continue; - if (jp->state == JOBSTOPPED) { - out2str("You have stopped jobs.\n"); - job_warning = 2; - return (1); - } - } - - return (0); -} - -/* - * Return a string identifying a command (to be printed by the - * jobs command). - */ - -STATIC char *cmdnextc; -STATIC int cmdnleft; - -void -commandtext(struct procstat *ps, union node *n) -{ - int len; - - cmdnextc = ps->cmd; - if (iflag || mflag || sizeof ps->cmd < 100) - len = sizeof(ps->cmd); - else - len = sizeof(ps->cmd) / 10; - cmdnleft = len; - cmdtxt(n); - if (cmdnleft <= 0) { - char *p = ps->cmd + len - 4; - p[0] = '.'; - p[1] = '.'; - p[2] = '.'; - p[3] = 0; - } else - *cmdnextc = '\0'; - TRACE(("commandtext: ps->cmd %x, end %x, left %d\n\t\"%s\"\n", - ps->cmd, cmdnextc, cmdnleft, ps->cmd)); -} - - -STATIC void -cmdtxt(union node *n) -{ - union node *np; - struct nodelist *lp; - const char *p; - int i; - char s[2]; - - if (n == NULL || cmdnleft <= 0) - return; - switch (n->type) { - case NSEMI: - cmdtxt(n->nbinary.ch1); - cmdputs("; "); - cmdtxt(n->nbinary.ch2); - break; - case NAND: - cmdtxt(n->nbinary.ch1); - cmdputs(" && "); - cmdtxt(n->nbinary.ch2); - break; - case NOR: - cmdtxt(n->nbinary.ch1); - cmdputs(" || "); - cmdtxt(n->nbinary.ch2); - break; - case NPIPE: - for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { - cmdtxt(lp->n); - if (lp->next) - cmdputs(" | "); - } - break; - case NSUBSHELL: - cmdputs("("); - cmdtxt(n->nredir.n); - cmdputs(")"); - break; - case NREDIR: - case NBACKGND: - cmdtxt(n->nredir.n); - break; - case NIF: - cmdputs("if "); - cmdtxt(n->nif.test); - cmdputs("; then "); - cmdtxt(n->nif.ifpart); - if (n->nif.elsepart) { - cmdputs("; else "); - cmdtxt(n->nif.elsepart); - } - cmdputs("; fi"); - break; - case NWHILE: - cmdputs("while "); - goto until; - case NUNTIL: - cmdputs("until "); -until: - cmdtxt(n->nbinary.ch1); - cmdputs("; do "); - cmdtxt(n->nbinary.ch2); - cmdputs("; done"); - break; - case NFOR: - cmdputs("for "); - cmdputs(n->nfor.var); - cmdputs(" in "); - cmdlist(n->nfor.args, 1); - cmdputs("; do "); - cmdtxt(n->nfor.body); - cmdputs("; done"); - break; - case NCASE: - cmdputs("case "); - cmdputs(n->ncase.expr->narg.text); - cmdputs(" in "); - for (np = n->ncase.cases; np; np = np->nclist.next) { - cmdtxt(np->nclist.pattern); - cmdputs(") "); - cmdtxt(np->nclist.body); - cmdputs(";; "); - } - cmdputs("esac"); - break; - case NDEFUN: - cmdputs(n->narg.text); - cmdputs("() { ... }"); - break; - case NCMD: - cmdlist(n->ncmd.args, 1); - cmdlist(n->ncmd.redirect, 0); - break; - case NARG: - cmdputs(n->narg.text); - break; - case NTO: - p = ">"; i = 1; goto redir; - case NCLOBBER: - p = ">|"; i = 1; goto redir; - case NAPPEND: - p = ">>"; i = 1; goto redir; - case NTOFD: - p = ">&"; i = 1; goto redir; - case NFROM: - p = "<"; i = 0; goto redir; - case NFROMFD: - p = "<&"; i = 0; goto redir; - case NFROMTO: - p = "<>"; i = 0; goto redir; -redir: - if (n->nfile.fd != i) { - s[0] = n->nfile.fd + '0'; - s[1] = '\0'; - cmdputs(s); - } - cmdputs(p); - if (n->type == NTOFD || n->type == NFROMFD) { - s[0] = n->ndup.dupfd + '0'; - s[1] = '\0'; - cmdputs(s); - } else { - cmdtxt(n->nfile.fname); - } - break; - case NHERE: - case NXHERE: - cmdputs("<<..."); - break; - default: - cmdputs("???"); - break; - } -} - -STATIC void -cmdlist(union node *np, int sep) -{ - for (; np; np = np->narg.next) { - if (!sep) - cmdputs(" "); - cmdtxt(np); - if (sep && np->narg.next) - cmdputs(" "); - } -} - - -STATIC void -cmdputs(const char *s) -{ - const char *p, *str = 0; - char c, cc[2] = " "; - char *nextc; - int nleft; - int subtype = 0; - int quoted = 0; - static char vstype[16][4] = { "", "}", "-", "+", "?", "=", - "#", "##", "%", "%%" }; - - p = s; - nextc = cmdnextc; - nleft = cmdnleft; - while (nleft > 0 && (c = *p++) != 0) { - switch (c) { - case CTLESC: - c = *p++; - break; - case CTLVAR: - subtype = *p++; - if ((subtype & VSTYPE) == VSLENGTH) - str = "${#"; - else - str = "${"; - if (!(subtype & VSQUOTE) != !(quoted & 1)) { - quoted ^= 1; - c = '"'; - } else - c = *str++; - break; - case CTLENDVAR: - if (quoted & 1) { - c = '"'; - str = "}"; - } else - c = '}'; - quoted >>= 1; - subtype = 0; - break; - case CTLBACKQ: - c = '$'; - str = "(...)"; - break; - case CTLBACKQ+CTLQUOTE: - c = '"'; - str = "$(...)\""; - break; - case CTLARI: - c = '$'; - str = "(("; - break; - case CTLENDARI: - c = ')'; - str = ")"; - break; - case CTLQUOTEMARK: - quoted ^= 1; - c = '"'; - break; - case '=': - if (subtype == 0) - break; - str = vstype[subtype & VSTYPE]; - if (subtype & VSNUL) - c = ':'; - else - c = *str++; - if (c != '}') - quoted <<= 1; - break; - case '\'': - case '\\': - case '"': - case '$': - /* These can only happen inside quotes */ - cc[0] = c; - str = cc; - c = '\\'; - break; - default: - break; - } - do { - *nextc++ = c; - } while (--nleft > 0 && str && (c = *str++)); - str = 0; - } - if ((quoted & 1) && nleft) { - *nextc++ = '"'; - nleft--; - } - cmdnleft = nleft; - cmdnextc = nextc; -} diff --git a/bin/sh/jobs.h b/bin/sh/jobs.h deleted file mode 100644 index 927373619..000000000 --- a/bin/sh/jobs.h +++ /dev/null @@ -1,101 +0,0 @@ -/* $NetBSD: jobs.h,v 1.20 2011/06/18 21:18:46 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)jobs.h 8.2 (Berkeley) 5/4/95 - */ - -#include "output.h" - -/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */ -#define FORK_FG 0 -#define FORK_BG 1 -#define FORK_NOJOB 2 - -/* mode flags for showjob(s) */ -#define SHOW_PGID 0x01 /* only show pgid - for jobs -p */ -#define SHOW_MULTILINE 0x02 /* one line per process */ -#define SHOW_PID 0x04 /* include process pid */ -#define SHOW_CHANGED 0x08 /* only jobs whose state has changed */ -#define SHOW_SIGNALLED 0x10 /* only if stopped/exited on signal */ -#define SHOW_ISSIG 0x20 /* job was signalled */ -#define SHOW_NO_FREE 0x40 /* do not free job */ - - -/* - * A job structure contains information about a job. A job is either a - * single process or a set of processes contained in a pipeline. In the - * latter case, pidlist will be non-NULL, and will point to a -1 terminated - * array of pids. - */ -#define MAXCMDTEXT 200 - -struct procstat { - pid_t pid; /* process id */ - int status; /* last process status from wait() */ - char cmd[MAXCMDTEXT];/* text of command being run */ -}; - -struct job { - struct procstat ps0; /* status of process */ - struct procstat *ps; /* status or processes when more than one */ - int nprocs; /* number of processes */ - pid_t pgrp; /* process group of this job */ - char state; -#define JOBRUNNING 0 /* at least one proc running */ -#define JOBSTOPPED 1 /* all procs are stopped */ -#define JOBDONE 2 /* all procs are completed */ - char used; /* true if this entry is in used */ - char changed; /* true if status has changed */ -#if JOBS - char jobctl; /* job running under job control */ - int prev_job; /* previous job index */ -#endif -}; - -extern pid_t backgndpid; /* pid of last background process */ -extern int job_warning; /* user was warned about stopped jobs */ - -void setjobctl(int); -void showjobs(struct output *, int); -struct job *makejob(union node *, int); -int forkshell(struct job *, union node *, int); -void forkchild(struct job *, union node *, int, int); -int forkparent(struct job *, union node *, int, pid_t); -int waitforjob(struct job *); -int stoppedjobs(void); -void commandtext(struct procstat *, union node *); -int getjobpgrp(const char *); - -#if ! JOBS -#define setjobctl(on) /* do nothing */ -#endif diff --git a/bin/sh/machdep.h b/bin/sh/machdep.h deleted file mode 100644 index 14e803bf7..000000000 --- a/bin/sh/machdep.h +++ /dev/null @@ -1,47 +0,0 @@ -/* $NetBSD: machdep.h,v 1.11 2003/08/07 09:05:33 agc Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)machdep.h 8.2 (Berkeley) 5/4/95 - */ - -/* - * Most machines require the value returned from malloc to be aligned - * in some way. The following macro will get this right on many machines. - */ - -#define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1) -/* - * It appears that grabstackstr() will barf with such alignments - * because stalloc() will return a string allocated in a new stackblock. - */ -#define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE) diff --git a/bin/sh/mail.c b/bin/sh/mail.c deleted file mode 100644 index 4ddd7c074..000000000 --- a/bin/sh/mail.c +++ /dev/null @@ -1,120 +0,0 @@ -/* $NetBSD: mail.c,v 1.16 2003/08/07 09:05:33 agc Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)mail.c 8.2 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: mail.c,v 1.16 2003/08/07 09:05:33 agc Exp $"); -#endif -#endif /* not lint */ - -/* - * Routines to check for mail. (Perhaps make part of main.c?) - */ -#include -#include -#include - -#include "shell.h" -#include "exec.h" /* defines padvance() */ -#include "var.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" -#include "mail.h" - - -#define MAXMBOXES 10 - - -STATIC int nmboxes; /* number of mailboxes */ -STATIC time_t mailtime[MAXMBOXES]; /* times of mailboxes */ - - - -/* - * Print appropriate message(s) if mail has arrived. If the argument is - * nozero, then the value of MAIL has changed, so we just update the - * values. - */ - -void -chkmail(int silent) -{ - int i; - const char *mpath; - char *p; - char *q; - struct stackmark smark; - struct stat statb; - - if (silent) - nmboxes = 10; - if (nmboxes == 0) - return; - setstackmark(&smark); - mpath = mpathset() ? mpathval() : mailval(); - for (i = 0 ; i < nmboxes ; i++) { - p = padvance(&mpath, nullstr); - if (p == NULL) - break; - if (*p == '\0') - continue; - for (q = p ; *q ; q++); - if (q[-1] != '/') - abort(); - q[-1] = '\0'; /* delete trailing '/' */ -#ifdef notdef /* this is what the System V shell claims to do (it lies) */ - if (stat(p, &statb) < 0) - statb.st_mtime = 0; - if (statb.st_mtime > mailtime[i] && ! silent) { - out2str(pathopt ? pathopt : "you have mail"); - out2c('\n'); - } - mailtime[i] = statb.st_mtime; -#else /* this is what it should do */ - if (stat(p, &statb) < 0) - statb.st_size = 0; - if (statb.st_size > mailtime[i] && ! silent) { - out2str(pathopt ? pathopt : "you have mail"); - out2c('\n'); - } - mailtime[i] = statb.st_size; -#endif - } - nmboxes = i; - popstackmark(&smark); -} diff --git a/bin/sh/mail.h b/bin/sh/mail.h deleted file mode 100644 index 9ea7c218b..000000000 --- a/bin/sh/mail.h +++ /dev/null @@ -1,37 +0,0 @@ -/* $NetBSD: mail.h,v 1.10 2003/08/07 09:05:34 agc Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)mail.h 8.2 (Berkeley) 5/4/95 - */ - -void chkmail(int); diff --git a/bin/sh/main.c b/bin/sh/main.c deleted file mode 100644 index 819a74575..000000000 --- a/bin/sh/main.c +++ /dev/null @@ -1,376 +0,0 @@ -/* $NetBSD: main.c,v 1.59 2015/05/26 21:35:15 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1991, 1993\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)main.c 8.7 (Berkeley) 7/19/95"; -#else -__RCSID("$NetBSD: main.c,v 1.59 2015/05/26 21:35:15 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "shell.h" -#include "main.h" -#include "mail.h" -#include "options.h" -#include "builtins.h" -#include "output.h" -#include "parser.h" -#include "nodes.h" -#include "expand.h" -#include "eval.h" -#include "jobs.h" -#include "input.h" -#include "trap.h" -#include "var.h" -#include "show.h" -#include "memalloc.h" -#include "error.h" -#include "init.h" -#include "mystring.h" -#include "exec.h" -#include "cd.h" - -#define PROFILE 0 - -int rootpid; -int rootshell; -int posix; -#if PROFILE -short profile_buf[16384]; -extern int etext(); -#endif - -STATIC void read_profile(const char *); -int main(int, char **); - -/* - * Main routine. We initialize things, parse the arguments, execute - * profiles if we're a login shell, and then call cmdloop to execute - * commands. The setjmp call sets up the location to jump to when an - * exception occurs. When an exception occurs the variable "state" - * is used to figure out how far we had gotten. - */ - -int -main(int argc, char **argv) -{ - struct jmploc jmploc; - struct stackmark smark; - volatile int state; - char *shinit; - uid_t uid; - gid_t gid; - - uid = getuid(); - gid = getgid(); - - setlocale(LC_ALL, ""); - - posix = getenv("POSIXLY_CORRECT") != NULL; -#if PROFILE - monitor(4, etext, profile_buf, sizeof profile_buf, 50); -#endif - state = 0; - if (setjmp(jmploc.loc)) { - /* - * When a shell procedure is executed, we raise the - * exception EXSHELLPROC to clean up before executing - * the shell procedure. - */ - switch (exception) { - case EXSHELLPROC: - rootpid = getpid(); - rootshell = 1; - minusc = NULL; - state = 3; - break; - - case EXEXEC: - exitstatus = exerrno; - break; - - case EXERROR: - exitstatus = 2; - break; - - default: - break; - } - - if (exception != EXSHELLPROC) { - if (state == 0 || iflag == 0 || ! rootshell) - exitshell(exitstatus); - } - reset(); - if (exception == EXINT -#if ATTY - && (! attyset() || equal(termval(), "emacs")) -#endif - ) { - out2c('\n'); - flushout(&errout); - } - popstackmark(&smark); - FORCEINTON; /* enable interrupts */ - if (state == 1) - goto state1; - else if (state == 2) - goto state2; - else if (state == 3) - goto state3; - else - goto state4; - } - handler = &jmploc; -#ifdef DEBUG -#if DEBUG == 2 - debug = 1; -#endif - opentrace(); - trputs("Shell args: "); trargs(argv); -#endif - rootpid = getpid(); - rootshell = 1; - init(); - initpwd(); - setstackmark(&smark); - procargs(argc, argv); - - /* - * Limit bogus system(3) or popen(3) calls in setuid binaries, - * by requiring the -p flag - */ - if (!pflag && (uid != geteuid() || gid != getegid())) { - setuid(uid); - setgid(gid); - /* PS1 might need to be changed accordingly. */ - choose_ps1(); - } - - if (argv[0] && argv[0][0] == '-') { - state = 1; - read_profile("/etc/profile"); -state1: - state = 2; - read_profile(".profile"); - } -state2: - state = 3; - if ((iflag || !posix) && - getuid() == geteuid() && getgid() == getegid()) { - if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') { - state = 3; - read_profile(shinit); - } - } -state3: - state = 4; - if (sflag == 0 || minusc) { - static int sigs[] = { - SIGINT, SIGQUIT, SIGHUP, -#ifdef SIGTSTP - SIGTSTP, -#endif - SIGPIPE - }; -#define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0])) - size_t i; - - for (i = 0; i < SIGSSIZE; i++) - setsignal(sigs[i], 0); - } - - if (minusc) - evalstring(minusc, 0); - - if (sflag || minusc == NULL) { -state4: /* XXX ??? - why isn't this before the "if" statement */ - cmdloop(1); - } -#if PROFILE - monitor(0); -#endif - exitshell(exitstatus); - /* NOTREACHED */ -} - - -/* - * Read and execute commands. "Top" is nonzero for the top level command - * loop; it turns on prompting if the shell is interactive. - */ - -void -cmdloop(int top) -{ - union node *n; - struct stackmark smark; - int inter; - int numeof = 0; - enum skipstate skip; - - TRACE(("cmdloop(%d) called\n", top)); - setstackmark(&smark); - for (;;) { - if (pendingsigs) - dotrap(); - inter = 0; - if (iflag == 1 && top) { - inter = 1; - showjobs(out2, SHOW_CHANGED); - chkmail(0); - flushout(&errout); - } - n = parsecmd(inter); - /* showtree(n); DEBUG */ - if (n == NEOF) { - if (!top || numeof >= 50) - break; - if (!stoppedjobs()) { - if (!Iflag) - break; - out2str("\nUse \"exit\" to leave shell.\n"); - } - numeof++; - } else if (n != NULL && nflag == 0) { - job_warning = (job_warning == 2) ? 1 : 0; - numeof = 0; - evaltree(n, 0); - } - popstackmark(&smark); - setstackmark(&smark); - - /* - * Any SKIP* can occur here! SKIP(FUNC|BREAK|CONT) occur when - * a dotcmd is in a loop or a function body and appropriate - * built-ins occurs in file scope in the sourced file. Values - * other than SKIPFILE are reset by the appropriate eval*() - * that contained the dotcmd() call. - */ - skip = current_skipstate(); - if (skip != SKIPNONE) { - if (skip == SKIPFILE) - stop_skipping(); - break; - } - } - popstackmark(&smark); -} - - - -/* - * Read /etc/profile or .profile. Return on error. - */ - -STATIC void -read_profile(const char *name) -{ - int fd; - int xflag_set = 0; - int vflag_set = 0; - - INTOFF; - if ((fd = open(name, O_RDONLY)) >= 0) - setinputfd(fd, 1); - INTON; - if (fd < 0) - return; - /* -q turns off -x and -v just when executing init files */ - if (qflag) { - if (xflag) - xflag = 0, xflag_set = 1; - if (vflag) - vflag = 0, vflag_set = 1; - } - cmdloop(0); - if (qflag) { - if (xflag_set) - xflag = 1; - if (vflag_set) - vflag = 1; - } - popfile(); -} - - - -/* - * Read a file containing shell functions. - */ - -void -readcmdfile(char *name) -{ - int fd; - - INTOFF; - if ((fd = open(name, O_RDONLY)) >= 0) - setinputfd(fd, 1); - else - error("Can't open %s", name); - INTON; - cmdloop(0); - popfile(); -} - - - -int -exitcmd(int argc, char **argv) -{ - if (stoppedjobs()) - return 0; - if (argc > 1) - exitstatus = number(argv[1]); - exitshell(exitstatus); - /* NOTREACHED */ -} diff --git a/bin/sh/main.h b/bin/sh/main.h deleted file mode 100644 index 9caa218f1..000000000 --- a/bin/sh/main.h +++ /dev/null @@ -1,41 +0,0 @@ -/* $NetBSD: main.h,v 1.11 2011/06/18 21:18:46 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)main.h 8.2 (Berkeley) 5/4/95 - */ - -extern int rootpid; /* pid of main shell */ -extern int rootshell; /* true if we aren't a child of the main shell */ - -void readcmdfile(char *); -void cmdloop(int); diff --git a/bin/sh/memalloc.c b/bin/sh/memalloc.c deleted file mode 100644 index a26348e5e..000000000 --- a/bin/sh/memalloc.c +++ /dev/null @@ -1,307 +0,0 @@ -/* $NetBSD: memalloc.c,v 1.29 2008/02/15 17:26:06 matt Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: memalloc.c,v 1.29 2008/02/15 17:26:06 matt Exp $"); -#endif -#endif /* not lint */ - -#include -#include - -#include "shell.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" -#include "machdep.h" -#include "mystring.h" - -/* - * Like malloc, but returns an error when out of space. - */ - -pointer -ckmalloc(size_t nbytes) -{ - pointer p; - - p = malloc(nbytes); - if (p == NULL) - error("Out of space"); - return p; -} - - -/* - * Same for realloc. - */ - -pointer -ckrealloc(pointer p, int nbytes) -{ - p = realloc(p, nbytes); - if (p == NULL) - error("Out of space"); - return p; -} - - -/* - * Make a copy of a string in safe storage. - */ - -char * -savestr(const char *s) -{ - char *p; - - p = ckmalloc(strlen(s) + 1); - scopy(s, p); - return p; -} - - -/* - * Parse trees for commands are allocated in lifo order, so we use a stack - * to make this more efficient, and also to avoid all sorts of exception - * handling code to handle interrupts in the middle of a parse. - * - * The size 504 was chosen because the Ultrix malloc handles that size - * well. - */ - -#define MINSIZE 504 /* minimum size of a block */ - -struct stack_block { - struct stack_block *prev; - char space[MINSIZE]; -}; - -struct stack_block stackbase; -struct stack_block *stackp = &stackbase; -struct stackmark *markp; -char *stacknxt = stackbase.space; -int stacknleft = MINSIZE; -int sstrnleft; -int herefd = -1; - -pointer -stalloc(int nbytes) -{ - char *p; - - nbytes = SHELL_ALIGN(nbytes); - if (nbytes > stacknleft) { - int blocksize; - struct stack_block *sp; - - blocksize = nbytes; - if (blocksize < MINSIZE) - blocksize = MINSIZE; - INTOFF; - sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize); - sp->prev = stackp; - stacknxt = sp->space; - stacknleft = blocksize; - stackp = sp; - INTON; - } - p = stacknxt; - stacknxt += nbytes; - stacknleft -= nbytes; - return p; -} - - -void -stunalloc(pointer p) -{ - if (p == NULL) { /*DEBUG */ - write(2, "stunalloc\n", 10); - abort(); - } - stacknleft += stacknxt - (char *)p; - stacknxt = p; -} - - - -void -setstackmark(struct stackmark *mark) -{ - mark->stackp = stackp; - mark->stacknxt = stacknxt; - mark->stacknleft = stacknleft; - mark->marknext = markp; - markp = mark; -} - - -void -popstackmark(struct stackmark *mark) -{ - struct stack_block *sp; - - INTOFF; - markp = mark->marknext; - while (stackp != mark->stackp) { - sp = stackp; - stackp = sp->prev; - ckfree(sp); - } - stacknxt = mark->stacknxt; - stacknleft = mark->stacknleft; - INTON; -} - - -/* - * When the parser reads in a string, it wants to stick the string on the - * stack and only adjust the stack pointer when it knows how big the - * string is. Stackblock (defined in stack.h) returns a pointer to a block - * of space on top of the stack and stackblocklen returns the length of - * this block. Growstackblock will grow this space by at least one byte, - * possibly moving it (like realloc). Grabstackblock actually allocates the - * part of the block that has been used. - */ - -void -growstackblock(void) -{ - int newlen = SHELL_ALIGN(stacknleft * 2 + 100); - - if (stacknxt == stackp->space && stackp != &stackbase) { - struct stack_block *oldstackp; - struct stackmark *xmark; - struct stack_block *sp; - - INTOFF; - oldstackp = stackp; - sp = stackp; - stackp = sp->prev; - sp = ckrealloc((pointer)sp, - sizeof(struct stack_block) - MINSIZE + newlen); - sp->prev = stackp; - stackp = sp; - stacknxt = sp->space; - stacknleft = newlen; - - /* - * Stack marks pointing to the start of the old block - * must be relocated to point to the new block - */ - xmark = markp; - while (xmark != NULL && xmark->stackp == oldstackp) { - xmark->stackp = stackp; - xmark->stacknxt = stacknxt; - xmark->stacknleft = stacknleft; - xmark = xmark->marknext; - } - INTON; - } else { - char *oldspace = stacknxt; - int oldlen = stacknleft; - char *p = stalloc(newlen); - - (void)memcpy(p, oldspace, oldlen); - stacknxt = p; /* free the space */ - stacknleft += newlen; /* we just allocated */ - } -} - -void -grabstackblock(int len) -{ - len = SHELL_ALIGN(len); - stacknxt += len; - stacknleft -= len; -} - -/* - * The following routines are somewhat easier to use than the above. - * The user declares a variable of type STACKSTR, which may be declared - * to be a register. The macro STARTSTACKSTR initializes things. Then - * the user uses the macro STPUTC to add characters to the string. In - * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is - * grown as necessary. When the user is done, she can just leave the - * string there and refer to it using stackblock(). Or she can allocate - * the space for it using grabstackstr(). If it is necessary to allow - * someone else to use the stack temporarily and then continue to grow - * the string, the user should use grabstack to allocate the space, and - * then call ungrabstr(p) to return to the previous mode of operation. - * - * USTPUTC is like STPUTC except that it doesn't check for overflow. - * CHECKSTACKSPACE can be called before USTPUTC to ensure that there - * is space for at least one character. - */ - -char * -growstackstr(void) -{ - int len = stackblocksize(); - if (herefd >= 0 && len >= 1024) { - xwrite(herefd, stackblock(), len); - sstrnleft = len - 1; - return stackblock(); - } - growstackblock(); - sstrnleft = stackblocksize() - len - 1; - return stackblock() + len; -} - -/* - * Called from CHECKSTRSPACE. - */ - -char * -makestrspace(void) -{ - int len = stackblocksize() - sstrnleft; - growstackblock(); - sstrnleft = stackblocksize() - len; - return stackblock() + len; -} - -void -ungrabstackstr(char *s, char *p) -{ - stacknleft += stacknxt - s; - stacknxt = s; - sstrnleft = stacknleft - (p - s); - -} diff --git a/bin/sh/memalloc.h b/bin/sh/memalloc.h deleted file mode 100644 index 8e5b07615..000000000 --- a/bin/sh/memalloc.h +++ /dev/null @@ -1,77 +0,0 @@ -/* $NetBSD: memalloc.h,v 1.15 2008/02/15 17:26:06 matt Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)memalloc.h 8.2 (Berkeley) 5/4/95 - */ - -struct stackmark { - struct stack_block *stackp; - char *stacknxt; - int stacknleft; - struct stackmark *marknext; -}; - - -extern char *stacknxt; -extern int stacknleft; -extern int sstrnleft; -extern int herefd; - -pointer ckmalloc(size_t); -pointer ckrealloc(pointer, int); -char *savestr(const char *); -pointer stalloc(int); -void stunalloc(pointer); -void setstackmark(struct stackmark *); -void popstackmark(struct stackmark *); -void growstackblock(void); -void grabstackblock(int); -char *growstackstr(void); -char *makestrspace(void); -void ungrabstackstr(char *, char *); - - - -#define stackblock() stacknxt -#define stackblocksize() stacknleft -#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize() -#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c))) -#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(); } -#define USTPUTC(c, p) (--sstrnleft, *p++ = (c)) -#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0')) -#define STUNPUTC(p) (++sstrnleft, --p) -#define STTOPC(p) p[-1] -#define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount)) -#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft) - -#define ckfree(p) free((pointer)(p)) diff --git a/bin/sh/miscbltin.c b/bin/sh/miscbltin.c deleted file mode 100644 index a9c85e4d0..000000000 --- a/bin/sh/miscbltin.c +++ /dev/null @@ -1,458 +0,0 @@ -/* $NetBSD: miscbltin.c,v 1.43 2015/05/09 13:28:55 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: miscbltin.c,v 1.43 2015/05/09 13:28:55 christos Exp $"); -#endif -#endif /* not lint */ - -/* - * Miscelaneous builtins. - */ - -#include /* quad_t */ -#include /* BSD4_4 */ -#include -#include -#include -#include -#include -#include -#include - -#include "shell.h" -#include "options.h" -#include "var.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" -#include "builtins.h" -#include "mystring.h" - -#undef rflag - - - -/* - * The read builtin. - * Backslahes escape the next char unless -r is specified. - * - * This uses unbuffered input, which may be avoidable in some cases. - * - * Note that if IFS=' :' then read x y should work so that: - * 'a b' x='a', y='b' - * ' a b ' x='a', y='b' - * ':b' x='', y='b' - * ':' x='', y='' - * '::' x='', y='' - * ': :' x='', y='' - * ':::' x='', y='::' - * ':b c:' x='', y='b c:' - */ - -int -readcmd(int argc, char **argv) -{ - char **ap; - char c; - int rflag; - char *prompt; - const char *ifs; - char *p; - int startword; - int status; - int i; - int is_ifs; - int saveall = 0; - - rflag = 0; - prompt = NULL; - while ((i = nextopt("p:r")) != '\0') { - if (i == 'p') - prompt = optionarg; - else - rflag = 1; - } - - if (prompt && isatty(0)) { - out2str(prompt); - flushall(); - } - - if (*(ap = argptr) == NULL) - error("arg count"); - - if ((ifs = bltinlookup("IFS", 1)) == NULL) - ifs = " \t\n"; - - status = 0; - startword = 2; - STARTSTACKSTR(p); - for (;;) { - if (read(0, &c, 1) != 1) { - status = 1; - break; - } - if (c == '\0') - continue; - if (c == '\\' && !rflag) { - if (read(0, &c, 1) != 1) { - status = 1; - break; - } - if (c != '\n') - STPUTC(c, p); - continue; - } - if (c == '\n') - break; - if (strchr(ifs, c)) - is_ifs = strchr(" \t\n", c) ? 1 : 2; - else - is_ifs = 0; - - if (startword != 0) { - if (is_ifs == 1) { - /* Ignore leading IFS whitespace */ - if (saveall) - STPUTC(c, p); - continue; - } - if (is_ifs == 2 && startword == 1) { - /* Only one non-whitespace IFS per word */ - startword = 2; - if (saveall) - STPUTC(c, p); - continue; - } - } - - if (is_ifs == 0) { - /* append this character to the current variable */ - startword = 0; - if (saveall) - /* Not just a spare terminator */ - saveall++; - STPUTC(c, p); - continue; - } - - /* end of variable... */ - startword = is_ifs; - - if (ap[1] == NULL) { - /* Last variable needs all IFS chars */ - saveall++; - STPUTC(c, p); - continue; - } - - STACKSTRNUL(p); - setvar(*ap, stackblock(), 0); - ap++; - STARTSTACKSTR(p); - } - STACKSTRNUL(p); - - /* Remove trailing IFS chars */ - for (; stackblock() <= --p; *p = 0) { - if (!strchr(ifs, *p)) - break; - if (strchr(" \t\n", *p)) - /* Always remove whitespace */ - continue; - if (saveall > 1) - /* Don't remove non-whitespace unless it was naked */ - break; - } - setvar(*ap, stackblock(), 0); - - /* Set any remaining args to "" */ - while (*++ap != NULL) - setvar(*ap, nullstr, 0); - return status; -} - - - -int -umaskcmd(int argc, char **argv) -{ - char *ap; - int mask; - int i; - int symbolic_mode = 0; - - while ((i = nextopt("S")) != '\0') { - symbolic_mode = 1; - } - - INTOFF; - mask = umask(0); - umask(mask); - INTON; - - if ((ap = *argptr) == NULL) { - if (symbolic_mode) { - char u[4], g[4], o[4]; - - i = 0; - if ((mask & S_IRUSR) == 0) - u[i++] = 'r'; - if ((mask & S_IWUSR) == 0) - u[i++] = 'w'; - if ((mask & S_IXUSR) == 0) - u[i++] = 'x'; - u[i] = '\0'; - - i = 0; - if ((mask & S_IRGRP) == 0) - g[i++] = 'r'; - if ((mask & S_IWGRP) == 0) - g[i++] = 'w'; - if ((mask & S_IXGRP) == 0) - g[i++] = 'x'; - g[i] = '\0'; - - i = 0; - if ((mask & S_IROTH) == 0) - o[i++] = 'r'; - if ((mask & S_IWOTH) == 0) - o[i++] = 'w'; - if ((mask & S_IXOTH) == 0) - o[i++] = 'x'; - o[i] = '\0'; - - out1fmt("u=%s,g=%s,o=%s\n", u, g, o); - } else { - out1fmt("%.4o\n", mask); - } - } else { - if (isdigit((unsigned char)*ap)) { - mask = 0; - do { - if (*ap >= '8' || *ap < '0') - error("Illegal number: %s", argv[1]); - mask = (mask << 3) + (*ap - '0'); - } while (*++ap != '\0'); - umask(mask); - } else { - void *set; - - INTOFF; - if ((set = setmode(ap)) != 0) { - mask = getmode(set, ~mask & 0777); - ckfree(set); - } - INTON; - if (!set) - error("Cannot set mode `%s' (%s)", ap, - strerror(errno)); - - umask(~mask & 0777); - } - } - return 0; -} - -/* - * ulimit builtin - * - * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and - * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with - * ash by J.T. Conklin. - * - * Public domain. - */ - -struct limits { - const char *name; - const char *unit; - int cmd; - int factor; /* multiply by to get rlim_{cur,max} values */ - char option; -}; - -static const struct limits limits[] = { -#ifdef RLIMIT_CPU - { "time", "seconds", RLIMIT_CPU, 1, 't' }, -#endif -#ifdef RLIMIT_FSIZE - { "file", "blocks", RLIMIT_FSIZE, 512, 'f' }, -#endif -#ifdef RLIMIT_DATA - { "data", "kbytes", RLIMIT_DATA, 1024, 'd' }, -#endif -#ifdef RLIMIT_STACK - { "stack", "kbytes", RLIMIT_STACK, 1024, 's' }, -#endif -#ifdef RLIMIT_CORE - { "coredump", "blocks", RLIMIT_CORE, 512, 'c' }, -#endif -#ifdef RLIMIT_RSS - { "memory", "kbytes", RLIMIT_RSS, 1024, 'm' }, -#endif -#ifdef RLIMIT_MEMLOCK - { "locked memory","kbytes", RLIMIT_MEMLOCK, 1024, 'l' }, -#endif -#ifdef RLIMIT_NTHR - { "thread", "threads", RLIMIT_NTHR, 1, 'r' }, -#endif -#ifdef RLIMIT_NPROC - { "process", "processes", RLIMIT_NPROC, 1, 'p' }, -#endif -#ifdef RLIMIT_NOFILE - { "nofiles", "descriptors", RLIMIT_NOFILE, 1, 'n' }, -#endif -#ifdef RLIMIT_VMEM - { "vmemory", "kbytes", RLIMIT_VMEM, 1024, 'v' }, -#endif -#ifdef RLIMIT_SWAP - { "swap", "kbytes", RLIMIT_SWAP, 1024, 'w' }, -#endif -#ifdef RLIMIT_SBSIZE - { "sbsize", "bytes", RLIMIT_SBSIZE, 1, 'b' }, -#endif - { NULL, NULL, 0, 0, '\0' } -}; - -int -ulimitcmd(int argc, char **argv) -{ - int c; - rlim_t val = 0; - enum { SOFT = 0x1, HARD = 0x2 } - how = SOFT | HARD; - const struct limits *l; - int set, all = 0; - int optc, what; - struct rlimit limit; - - what = 'f'; - while ((optc = nextopt("HSabtfdscmlrpnv")) != '\0') - switch (optc) { - case 'H': - how = HARD; - break; - case 'S': - how = SOFT; - break; - case 'a': - all = 1; - break; - default: - what = optc; - } - - for (l = limits; l->name && l->option != what; l++) - ; - if (!l->name) - error("internal error (%c)", what); - - set = *argptr ? 1 : 0; - if (set) { - char *p = *argptr; - - if (all || argptr[1]) - error("too many arguments"); - if (strcmp(p, "unlimited") == 0) - val = RLIM_INFINITY; - else { - val = (rlim_t) 0; - - while ((c = *p++) >= '0' && c <= '9') - val = (val * 10) + (long)(c - '0'); - if (c) - error("bad number"); - val *= l->factor; - } - } - if (all) { - for (l = limits; l->name; l++) { - getrlimit(l->cmd, &limit); - if (how & SOFT) - val = limit.rlim_cur; - else if (how & HARD) - val = limit.rlim_max; - - out1fmt("%-13s (-%c %-11s) ", l->name, l->option, - l->unit); - if (val == RLIM_INFINITY) - out1fmt("unlimited\n"); - else - { - val /= l->factor; -#ifdef BSD4_4 - out1fmt("%lld\n", (long long) val); -#else - out1fmt("%ld\n", (long) val); -#endif - } - } - return 0; - } - - if (getrlimit(l->cmd, &limit) == -1) - error("error getting limit (%s)", strerror(errno)); - if (set) { - if (how & HARD) - limit.rlim_max = val; - if (how & SOFT) - limit.rlim_cur = val; - if (setrlimit(l->cmd, &limit) < 0) - error("error setting limit (%s)", strerror(errno)); - } else { - if (how & SOFT) - val = limit.rlim_cur; - else if (how & HARD) - val = limit.rlim_max; - - if (val == RLIM_INFINITY) - out1fmt("unlimited\n"); - else - { - val /= l->factor; -#ifdef BSD4_4 - out1fmt("%lld\n", (long long) val); -#else - out1fmt("%ld\n", (long) val); -#endif - } - } - return 0; -} diff --git a/bin/sh/miscbltin.h b/bin/sh/miscbltin.h deleted file mode 100644 index 4c12c8249..000000000 --- a/bin/sh/miscbltin.h +++ /dev/null @@ -1,31 +0,0 @@ -/* $NetBSD: miscbltin.h,v 1.3 2003/08/21 17:57:53 christos Exp $ */ - -/* - * Copyright (c) 1997 Christos Zoulas. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -int readcmd(int, char **); -int umaskcmd(int, char **); -int ulimitcmd(int, char **); diff --git a/bin/sh/mkbuiltins b/bin/sh/mkbuiltins deleted file mode 100644 index 2ebf7ac77..000000000 --- a/bin/sh/mkbuiltins +++ /dev/null @@ -1,136 +0,0 @@ -#!/bin/sh - -# $NetBSD: mkbuiltins,v 1.22 2009/10/06 19:56:58 apb Exp $ -# -# Copyright (c) 1991, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Kenneth Almquist. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)mkbuiltins 8.2 (Berkeley) 5/4/95 - -havehist=1 -if [ x"$1" = x"-h" ]; then - havehist=0 - shift -fi - -shell=$1 -builtins=$2 -objdir=$3 - -havejobs=0 -if grep '^#define JOBS[ ]*1' ${shell} > /dev/null -then - havejobs=1 -fi - -exec <$builtins 3> ${objdir}/builtins.c 4> ${objdir}/builtins.h - -echo '/* - * This file was generated by the mkbuiltins program. - */ - -#include "shell.h" -#include "builtins.h" - -const struct builtincmd builtincmd[] = { -' >&3 - -echo '/* - * This file was generated by the mkbuiltins program. - */ - -#include - -struct builtincmd { - const char *name; - int (*builtin)(int, char **); -}; - -extern const struct builtincmd builtincmd[]; -extern const struct builtincmd splbltincmd[]; - -' >&4 - -specials= - -while read line -do - set -- $line - [ -z "$1" ] && continue - case "$1" in - \#if*|\#def*|\#end*) - echo $line >&3 - echo $line >&4 - continue - ;; - \#*) - continue - ;; - esac - - func=$1 - shift - [ x"$1" = x'-j' ] && { - [ $havejobs = 0 ] && continue - shift - } - [ x"$1" = x'-h' ] && { - [ $havehist = 0 ] && continue - shift - } - echo 'int '"$func"'(int, char **);' >&4 - while - [ $# != 0 ] && [ x"$1" != x'#' ] - do - [ x"$1" = x'-s' ] && { - specials="$specials $2 $func" - shift 2 - continue; - } - [ x"$1" = x'-u' ] && shift - echo ' { "'$1'", '"$func"' },' >&3 - shift - done -done - -echo ' { 0, 0 },' >&3 -echo '};' >&3 -echo >&3 -echo 'const struct builtincmd splbltincmd[] = {' >&3 - -set -- $specials -while - [ $# != 0 ] -do - echo ' { "'$1'", '"$2"' },' >&3 - shift 2 -done - -echo ' { 0, 0 },' >&3 -echo "};" >&3 diff --git a/bin/sh/mkinit.sh b/bin/sh/mkinit.sh deleted file mode 100755 index a7dcb91f2..000000000 --- a/bin/sh/mkinit.sh +++ /dev/null @@ -1,170 +0,0 @@ -#! /bin/sh -# $NetBSD: mkinit.sh,v 1.5 2008/10/23 20:21:57 apb Exp $ - -# Copyright (c) 2003 The NetBSD Foundation, Inc. -# All rights reserved. -# -# This code is derived from software contributed to The NetBSD Foundation -# by David Laight. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS -# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -srcs="$*" - -nl=' -' -openparen='(' -backslash='\' - -includes=' "shell.h" "mystring.h" "init.h" ' -defines= -decles= -event_init= -event_reset= -event_shellproc= - -for src in $srcs; do - exec <$src - decnl="$nl" - while IFS=; read -r line; do - [ "$line" = x ] - case "$line " in - INIT["{ "]* ) event=init;; - RESET["{ "]* ) event=reset;; - SHELLPROC["{ "]* ) event=shellproc;; - INCLUDE[\ \ ]* ) - IFS=' ' - set -- $line - # ignore duplicates - [ "${includes}" != "${includes%* $2 }" ] && continue - includes="$includes$2 " - continue - ;; - MKINIT\ ) - # struct declaration - decles="$decles$nl" - while - read -r line - decles="${decles}${line}${nl}" - [ "$line" != "};" ] - do - : - done - decnl="$nl" - continue - ;; - MKINIT["{ "]* ) - # strip initialiser - def=${line#MKINIT} - comment="${def#*;}" - def="${def%;$comment}" - def="${def%%=*}" - def="${def% }" - decles="${decles}${decnl}extern${def};${comment}${nl}" - decnl= - continue - ;; - \#define[\ \ ]* ) - IFS=' ' - set -- $line - # Ignore those with arguments - [ "$2" = "${2##*$openparen}" ] || continue - # and multiline definitions - [ "$line" = "${line%$backslash}" ] || continue - defines="${defines}#undef $2${nl}${line}${nl}" - continue - ;; - * ) continue;; - esac - # code for events - ev="${nl} /* from $src: */${nl} {${nl}" - # Indent the text by an extra - while - read -r line - [ "$line" != "}" ] - do - [ -n "$line" -a "$line" = "${line###}" ] && - line=" $line" - ev="${ev}${line}${nl}" - done - ev="${ev} }${nl}" - eval event_$event=\"\$event_$event\$ev\" - done -done - -exec >init.c.tmp - -echo "/*" -echo " * This file was generated by the mkinit program." -echo " */" -echo - -IFS=' ' -for f in $includes; do - echo "#include $f" -done - -echo -echo -echo -echo "$defines" -echo -echo "$decles" -echo -echo -echo "/*" -echo " * Initialization code." -echo " */" -echo -echo "void" -echo "init(void)" -echo "{" -echo "${event_init}" -echo "}" -echo -echo -echo -echo "/*" -echo " * This routine is called when an error or an interrupt occurs in an" -echo " * interactive shell and control is returned to the main command loop." -echo " */" -echo -echo "void" -echo "reset(void)" -echo "{" -echo "${event_reset}" -echo "}" -echo -echo -echo -echo "/*" -echo " * This routine is called to initialize the shell to run a shell procedure." -echo " */" -echo -echo "void" -echo "initshellproc(void)" -echo "{" -echo "${event_shellproc}" -echo "}" - -exec >&- -mv init.c.tmp init.c diff --git a/bin/sh/mknodes.sh b/bin/sh/mknodes.sh deleted file mode 100755 index 2208fd846..000000000 --- a/bin/sh/mknodes.sh +++ /dev/null @@ -1,214 +0,0 @@ -#! /bin/sh -# $NetBSD: mknodes.sh,v 1.2 2008/04/29 06:53:00 martin Exp $ - -# Copyright (c) 2003 The NetBSD Foundation, Inc. -# All rights reserved. -# -# This code is derived from software contributed to The NetBSD Foundation -# by David Laight. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS -# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS -# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. - -nodetypes=$1 -nodes_pat=$2 -objdir="$3" - -exec <$nodetypes -exec >$objdir/nodes.h.tmp - -echo "/*" -echo " * This file was generated by mknodes.sh" -echo " */" -echo - -tagno=0 -while IFS=; read -r line; do - line="${line%%#*}" - IFS=' ' - set -- $line - IFS= - [ -z "$2" ] && continue - case "$line" in - [" "]* ) - IFS=' ' - [ $field = 0 ] && struct_list="$struct_list $struct" - eval field_${struct}_$field=\"\$*\" - eval numfld_$struct=\$field - field=$(($field + 1)) - ;; - * ) - define=$1 - struct=$2 - echo "#define $define $tagno" - tagno=$(($tagno + 1)) - eval define_$struct=\"\$define_$struct \$define\" - struct_define="$struct_define $struct" - field=0 - ;; - esac -done - -echo - -IFS=' ' -for struct in $struct_list; do - echo - echo - echo "struct $struct {" - field=0 - while - eval line=\"\$field_${struct}_$field\" - field=$(($field + 1)) - [ -n "$line" ] - do - IFS=' ' - set -- $line - name=$1 - case $2 in - nodeptr ) type="union node *";; - nodelist ) type="struct nodelist *";; - string ) type="char *";; - int ) type="int ";; - * ) name=; shift 2; type="$*";; - esac - echo " $type$name;" - done - echo "};" -done - -echo -echo -echo "union node {" -echo " int type;" -for struct in $struct_list; do - echo " struct $struct $struct;" -done -echo "};" -echo -echo -echo "struct nodelist {" -echo " struct nodelist *next;" -echo " union node *n;" -echo "};" -echo -echo -echo "union node *copyfunc(union node *);" -echo "void freefunc(union node *);" - -mv $objdir/nodes.h.tmp $objdir/nodes.h || exit 1 - -exec <$nodes_pat -exec >$objdir/nodes.c.tmp - -echo "/*" -echo " * This file was generated by mknodes.sh" -echo " */" -echo - -while IFS=; read -r line; do - IFS=' ' - set -- $line - IFS= - case "$1" in - '%SIZES' ) - echo "static const short nodesize[$tagno] = {" - IFS=' ' - for struct in $struct_define; do - echo " SHELL_ALIGN(sizeof (struct $struct))," - done - echo "};" - ;; - '%CALCSIZE' ) - echo " if (n == NULL)" - echo " return;" - echo " funcblocksize += nodesize[n->type];" - echo " switch (n->type) {" - IFS=' ' - for struct in $struct_list; do - eval defines=\"\$define_$struct\" - for define in $defines; do - echo " case $define:" - done - eval field=\$numfld_$struct - while - [ $field != 0 ] - do - eval line=\"\$field_${struct}_$field\" - field=$(($field - 1)) - IFS=' ' - set -- $line - name=$1 - cl=")" - case $2 in - nodeptr ) fn=calcsize;; - nodelist ) fn=sizenodelist;; - string ) fn="funcstringsize += strlen" - cl=") + 1";; - * ) continue;; - esac - echo " ${fn}(n->$struct.$name${cl};" - done - echo " break;" - done - echo " };" - ;; - '%COPY' ) - echo " if (n == NULL)" - echo " return NULL;" - echo " new = funcblock;" - echo " funcblock = (char *) funcblock + nodesize[n->type];" - echo " switch (n->type) {" - IFS=' ' - for struct in $struct_list; do - eval defines=\"\$define_$struct\" - for define in $defines; do - echo " case $define:" - done - eval field=\$numfld_$struct - while - [ $field != 0 ] - do - eval line=\"\$field_${struct}_$field\" - field=$(($field - 1)) - IFS=' ' - set -- $line - name=$1 - case $2 in - nodeptr ) fn="copynode(";; - nodelist ) fn="copynodelist(";; - string ) fn="nodesavestr(";; - int ) fn=;; - * ) continue;; - esac - f="$struct.$name" - echo " new->$f = ${fn}n->$f${fn:+)};" - done - echo " break;" - done - echo " };" - echo " new->type = n->type;" - ;; - * ) echo "$line";; - esac -done - -mv $objdir/nodes.c.tmp $objdir/nodes.c || exit 1 diff --git a/bin/sh/mktokens b/bin/sh/mktokens deleted file mode 100644 index d12bdee5b..000000000 --- a/bin/sh/mktokens +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/sh - -# $NetBSD: mktokens,v 1.12 2008/10/25 22:18:15 apb Exp $ -# -# Copyright (c) 1991, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Kenneth Almquist. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)mktokens 8.1 (Berkeley) 5/31/93 - -: ${AWK:=awk} -: ${SED:=sed} - -# The following is a list of tokens. The second column is nonzero if the -# token marks the end of a list. The third column is the name to print in -# error messages. - -cat > /tmp/ka$$ <<\! -TEOF 1 end of file -TNL 0 newline -TSEMI 0 ";" -TBACKGND 0 "&" -TAND 0 "&&" -TOR 0 "||" -TPIPE 0 "|" -TLP 0 "(" -TRP 1 ")" -TENDCASE 1 ";;" -TENDBQUOTE 1 "`" -TREDIR 0 redirection -TWORD 0 word -TIF 0 "if" -TTHEN 1 "then" -TELSE 1 "else" -TELIF 1 "elif" -TFI 1 "fi" -TWHILE 0 "while" -TUNTIL 0 "until" -TFOR 0 "for" -TDO 1 "do" -TDONE 1 "done" -TBEGIN 0 "{" -TEND 1 "}" -TCASE 0 "case" -TESAC 1 "esac" -TNOT 0 "!" -! -nl=`wc -l /tmp/ka$$` -exec > token.h -${AWK} '{print "#define " $1 " " NR-1}' /tmp/ka$$ -echo ' -/* Array indicating which tokens mark the end of a list */ -const char tokendlist[] = {' -${AWK} '{print "\t" $2 ","}' /tmp/ka$$ -echo '}; - -const char *const tokname[] = {' -${SED} -e 's/"/\\"/g' \ - -e 's/[^ ]*[ ][ ]*[^ ]*[ ][ ]*\(.*\)/ "\1",/' \ - /tmp/ka$$ -echo '}; -' -${SED} 's/"//g' /tmp/ka$$ | ${AWK} ' -/TIF/{print "#define KWDOFFSET " NR-1; print ""; - print "const char *const parsekwd[] = {"} -/TIF/,/neverfound/{print " \"" $3 "\","}' -echo ' 0 -};' - -rm /tmp/ka$$ diff --git a/bin/sh/myhistedit.h b/bin/sh/myhistedit.h deleted file mode 100644 index be66df04d..000000000 --- a/bin/sh/myhistedit.h +++ /dev/null @@ -1,46 +0,0 @@ -/* $NetBSD: myhistedit.h,v 1.11 2011/06/18 21:18:46 christos Exp $ */ - -/*- - * Copyright (c) 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)myhistedit.h 8.2 (Berkeley) 5/4/95 - */ - -#include - -extern History *hist; -extern EditLine *el; -extern int displayhist; - -void histedit(void); -void sethistsize(const char *); -void setterm(const char *); -int inputrc(int, char **); -int not_fcnumber(char *); -int str_to_event(const char *, int); - diff --git a/bin/sh/mystring.c b/bin/sh/mystring.c deleted file mode 100644 index d2d582552..000000000 --- a/bin/sh/mystring.c +++ /dev/null @@ -1,133 +0,0 @@ -/* $NetBSD: mystring.c,v 1.17 2013/04/28 17:01:28 dholland Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: mystring.c,v 1.17 2013/04/28 17:01:28 dholland Exp $"); -#endif -#endif /* not lint */ - -/* - * String functions. - * - * equal(s1, s2) Return true if strings are equal. - * scopy(from, to) Copy a string. - * scopyn(from, to, n) Like scopy, but checks for overflow. - * number(s) Convert a string of digits to an integer. - * is_number(s) Return true if s is a string of digits. - */ - -#include -#include "shell.h" -#include "syntax.h" -#include "error.h" -#include "mystring.h" - - -const char nullstr[1]; /* zero length string */ - -/* - * equal - #defined in mystring.h - */ - -/* - * scopy - #defined in mystring.h - */ - - -/* - * scopyn - copy a string from "from" to "to", truncating the string - * if necessary. "To" is always nul terminated, even if - * truncation is performed. "Size" is the size of "to". - */ - -void -scopyn(const char *from, char *to, int size) -{ - - while (--size > 0) { - if ((*to++ = *from++) == '\0') - return; - } - *to = '\0'; -} - - -/* - * prefix -- see if pfx is a prefix of string. - */ - -int -prefix(const char *pfx, const char *string) -{ - while (*pfx) { - if (*pfx++ != *string++) - return 0; - } - return 1; -} - - -/* - * Convert a string of digits to an integer, printing an error message on - * failure. - */ - -int -number(const char *s) -{ - - if (! is_number(s)) - error("Illegal number: %s", s); - return atoi(s); -} - - - -/* - * Check for a valid number. This should be elsewhere. - */ - -int -is_number(const char *p) -{ - do { - if (! is_digit(*p)) - return 0; - } while (*++p != '\0'); - return 1; -} diff --git a/bin/sh/mystring.h b/bin/sh/mystring.h deleted file mode 100644 index 08a73e9e5..000000000 --- a/bin/sh/mystring.h +++ /dev/null @@ -1,45 +0,0 @@ -/* $NetBSD: mystring.h,v 1.11 2003/08/07 09:05:35 agc Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)mystring.h 8.2 (Berkeley) 5/4/95 - */ - -#include - -void scopyn(const char *, char *, int); -int prefix(const char *, const char *); -int number(const char *); -int is_number(const char *); - -#define equal(s1, s2) (strcmp(s1, s2) == 0) -#define scopy(s1, s2) ((void)strcpy(s2, s1)) diff --git a/bin/sh/nodes.c.pat b/bin/sh/nodes.c.pat deleted file mode 100644 index 979e6b00e..000000000 --- a/bin/sh/nodes.c.pat +++ /dev/null @@ -1,159 +0,0 @@ -/* $NetBSD: nodes.c.pat,v 1.13 2012/03/20 18:42:29 matt Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)nodes.c.pat 8.2 (Berkeley) 5/4/95 - */ - -#include -/* - * Routine for dealing with parsed shell commands. - */ - -#include "shell.h" -#include "nodes.h" -#include "memalloc.h" -#include "machdep.h" -#include "mystring.h" - - -int funcblocksize; /* size of structures in function */ -int funcstringsize; /* size of strings in node */ -pointer funcblock; /* block to allocate function from */ -char *funcstring; /* block to allocate strings from */ - -%SIZES - - -STATIC void calcsize(union node *); -STATIC void sizenodelist(struct nodelist *); -STATIC union node *copynode(union node *); -STATIC struct nodelist *copynodelist(struct nodelist *); -STATIC char *nodesavestr(char *); - - - -/* - * Make a copy of a parse tree. - */ - -union node * -copyfunc(union node *n) -{ - if (n == NULL) - return NULL; - funcblocksize = 0; - funcstringsize = 0; - calcsize(n); - funcblock = ckmalloc(funcblocksize + funcstringsize); - funcstring = (char *) funcblock + funcblocksize; - return copynode(n); -} - - - -STATIC void -calcsize(union node *n) -{ - %CALCSIZE -} - - - -STATIC void -sizenodelist(struct nodelist *lp) -{ - while (lp) { - funcblocksize += SHELL_ALIGN(sizeof(struct nodelist)); - calcsize(lp->n); - lp = lp->next; - } -} - - - -STATIC union node * -copynode(union node *n) -{ - union node *new; - - %COPY - return new; -} - - -STATIC struct nodelist * -copynodelist(struct nodelist *lp) -{ - struct nodelist *start; - struct nodelist **lpp; - - lpp = &start; - while (lp) { - *lpp = funcblock; - funcblock = (char *) funcblock + - SHELL_ALIGN(sizeof(struct nodelist)); - (*lpp)->n = copynode(lp->n); - lp = lp->next; - lpp = &(*lpp)->next; - } - *lpp = NULL; - return start; -} - - - -STATIC char * -nodesavestr(char *s) -{ - register char *p = s; - register char *q = funcstring; - char *rtn = funcstring; - - while ((*q++ = *p++) != 0) - continue; - funcstring = q; - return rtn; -} - - - -/* - * Free a parse tree. - */ - -void -freefunc(union node *n) -{ - if (n) - ckfree(n); -} diff --git a/bin/sh/nodetypes b/bin/sh/nodetypes deleted file mode 100644 index 4bf4ae0b0..000000000 --- a/bin/sh/nodetypes +++ /dev/null @@ -1,143 +0,0 @@ -# $NetBSD: nodetypes,v 1.13 2009/05/26 07:30:51 joerg Exp $ -# Copyright (c) 1991, 1993 -# The Regents of the University of California. All rights reserved. -# -# This code is derived from software contributed to Berkeley by -# Kenneth Almquist. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# 3. Neither the name of the University nor the names of its contributors -# may be used to endorse or promote products derived from this software -# without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# @(#)nodetypes 8.2 (Berkeley) 5/4/95 - -# This file describes the nodes used in parse trees. Unindented lines -# contain a node type followed by a structure tag. Subsequent indented -# lines specify the fields of the structure. Several node types can share -# the same structure, in which case the fields of the structure should be -# specified only once. -# -# A field of a structure is described by the name of the field followed -# by a type. The currently implemented types are: -# nodeptr - a pointer to a node -# nodelist - a pointer to a list of nodes -# string - a pointer to a nul terminated string -# int - an integer -# other - any type that can be copied by assignment -# temp - a field that doesn't have to be copied when the node is copied -# The last two types should be followed by the text of a C declaration for -# the field. - -NSEMI nbinary # two commands separated by a semicolon - type int - ch1 nodeptr # the first child - ch2 nodeptr # the second child - -NCMD ncmd # a simple command - type int - backgnd int # set to run command in background - args nodeptr # the arguments - redirect nodeptr # list of file redirections - -NPIPE npipe # a pipeline - type int - backgnd int # set to run pipeline in background - cmdlist nodelist # the commands in the pipeline - -NREDIR nredir # redirection (of a complex command) - type int - n nodeptr # the command - redirect nodeptr # list of file redirections - -NBACKGND nredir # run command in background -NSUBSHELL nredir # run command in a subshell - -NAND nbinary # the && operator -NOR nbinary # the || operator - -NIF nif # the if statement. Elif clauses are handled - type int # using multiple if nodes. - test nodeptr # if test - ifpart nodeptr # then ifpart - elsepart nodeptr # else elsepart - -NWHILE nbinary # the while statement. First child is the test -NUNTIL nbinary # the until statement - -NFOR nfor # the for statement - type int - args nodeptr # for var in args - body nodeptr # do body; done - var string # the for variable - -NCASE ncase # a case statement - type int - expr nodeptr # the word to switch on - cases nodeptr # the list of cases (NCLIST nodes) - -NCLIST nclist # a case - type int - next nodeptr # the next case in list - pattern nodeptr # list of patterns for this case - body nodeptr # code to execute for this case - - -NDEFUN narg # define a function. The "next" field contains - # the body of the function. - -NARG narg # represents a word - type int - next nodeptr # next word in list - text string # the text of the word - backquote nodelist # list of commands in back quotes - -NTO nfile # fd> fname -NCLOBBER nfile # fd>| fname -NFROM nfile # fd< fname -NFROMTO nfile # fd<> fname -NAPPEND nfile # fd>> fname - type int - next nodeptr # next redirection in list - fd int # file descriptor being redirected - fname nodeptr # file name, in a NARG node - expfname temp char *expfname # actual file name - -NTOFD ndup # fd<&dupfd -NFROMFD ndup # fd>&dupfd - type int - next nodeptr # next redirection in list - fd int # file descriptor being redirected - dupfd int # file descriptor to duplicate - vname nodeptr # file name if fd>&$var - - -NHERE nhere # fd<<\! -NXHERE nhere # fd< -#ifndef lint -#if 0 -static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: options.c,v 1.43 2012/03/20 18:42:29 matt Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include - -#include "shell.h" -#define DEFINE_OPTIONS -#include "options.h" -#undef DEFINE_OPTIONS -#include "builtins.h" -#include "nodes.h" /* for other header files */ -#include "eval.h" -#include "jobs.h" -#include "input.h" -#include "output.h" -#include "trap.h" -#include "var.h" -#include "memalloc.h" -#include "error.h" -#include "mystring.h" -#ifndef SMALL -#include "myhistedit.h" -#endif -#include "show.h" - -char *arg0; /* value of $0 */ -struct shparam shellparam; /* current positional parameters */ -char **argptr; /* argument list for builtin commands */ -char *optionarg; /* set by nextopt (like getopt) */ -char *optptr; /* used by nextopt */ - -char *minusc; /* argument to -c option */ - - -STATIC void options(int); -STATIC void minus_o(char *, int); -STATIC void setoption(int, int); -STATIC int getopts(char *, char *, char **, char ***, char **); - - -/* - * Process the shell command line arguments. - */ - -void -procargs(int argc, char **argv) -{ - size_t i; - - argptr = argv; - if (argc > 0) - argptr++; - for (i = 0; i < NOPTS; i++) - optlist[i].val = 2; - options(1); - if (*argptr == NULL && minusc == NULL) - sflag = 1; - if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1)) - iflag = 1; - if (iflag == 1 && sflag == 2) - iflag = 2; - if (mflag == 2) - mflag = iflag; - for (i = 0; i < NOPTS; i++) - if (optlist[i].val == 2) - optlist[i].val = 0; -#if DEBUG == 2 - debug = 1; -#endif - arg0 = argv[0]; - if (sflag == 0 && minusc == NULL) { - commandname = argv[0]; - arg0 = *argptr++; - setinputfile(arg0, 0); - commandname = arg0; - } - /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */ - if (minusc != NULL) { - if (argptr == NULL || *argptr == NULL) - error("Bad -c option"); - minusc = *argptr++; - if (*argptr != 0) - arg0 = *argptr++; - } - - shellparam.p = argptr; - shellparam.reset = 1; - /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */ - while (*argptr) { - shellparam.nparam++; - argptr++; - } - optschanged(); -} - - -void -optschanged(void) -{ - setinteractive(iflag); -#ifndef SMALL - histedit(); -#endif - setjobctl(mflag); -} - -/* - * Process shell options. The global variable argptr contains a pointer - * to the argument list; we advance it past the options. - */ - -STATIC void -options(int cmdline) -{ - static char empty[] = ""; - char *p; - int val; - int c; - - if (cmdline) - minusc = NULL; - while ((p = *argptr) != NULL) { - argptr++; - if ((c = *p++) == '-') { - val = 1; - if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) { - if (!cmdline) { - /* "-" means turn off -x and -v */ - if (p[0] == '\0') - xflag = vflag = 0; - /* "--" means reset params */ - else if (*argptr == NULL) - setparam(argptr); - } - break; /* "-" or "--" terminates options */ - } - } else if (c == '+') { - val = 0; - } else { - argptr--; - break; - } - while ((c = *p++) != '\0') { - if (c == 'c' && cmdline) { - /* command is after shell args*/ - minusc = empty; - } else if (c == 'o') { - minus_o(*argptr, val); - if (*argptr) - argptr++; - } else { - setoption(c, val); - } - } - } -} - -static void -set_opt_val(size_t i, int val) -{ - size_t j; - int flag; - - if (val && (flag = optlist[i].opt_set)) { - /* some options (eg vi/emacs) are mutually exclusive */ - for (j = 0; j < NOPTS; j++) - if (optlist[j].opt_set == flag) - optlist[j].val = 0; - } - optlist[i].val = val; -#ifdef DEBUG - if (&optlist[i].val == &debug) - opentrace(); -#endif -} - -STATIC void -minus_o(char *name, int val) -{ - size_t i; - - if (name == NULL) { - if (val) { - out1str("Current option settings\n"); - for (i = 0; i < NOPTS; i++) { - out1fmt("%-16s%s\n", optlist[i].name, - optlist[i].val ? "on" : "off"); - } - } else { - out1str("set"); - for (i = 0; i < NOPTS; i++) { - out1fmt(" %co %s", - "+-"[optlist[i].val], optlist[i].name); - } - out1str("\n"); - } - } else { - for (i = 0; i < NOPTS; i++) - if (equal(name, optlist[i].name)) { - set_opt_val(i, val); - return; - } - error("Illegal option -o %s", name); - } -} - - -STATIC void -setoption(int flag, int val) -{ - size_t i; - - for (i = 0; i < NOPTS; i++) - if (optlist[i].letter == flag) { - set_opt_val( i, val ); - return; - } - error("Illegal option -%c", flag); - /* NOTREACHED */ -} - - - -#ifdef mkinit -INCLUDE "options.h" - -SHELLPROC { - int i; - - for (i = 0; optlist[i].name; i++) - optlist[i].val = 0; - optschanged(); - -} -#endif - - -/* - * Set the shell parameters. - */ - -void -setparam(char **argv) -{ - char **newparam; - char **ap; - int nparam; - - for (nparam = 0 ; argv[nparam] ; nparam++) - continue; - ap = newparam = ckmalloc((nparam + 1) * sizeof *ap); - while (*argv) { - *ap++ = savestr(*argv++); - } - *ap = NULL; - freeparam(&shellparam); - shellparam.malloc = 1; - shellparam.nparam = nparam; - shellparam.p = newparam; - shellparam.optnext = NULL; -} - - -/* - * Free the list of positional parameters. - */ - -void -freeparam(volatile struct shparam *param) -{ - char **ap; - - if (param->malloc) { - for (ap = param->p ; *ap ; ap++) - ckfree(*ap); - ckfree(param->p); - } -} - - - -/* - * The shift builtin command. - */ - -int -shiftcmd(int argc, char **argv) -{ - int n; - char **ap1, **ap2; - - n = 1; - if (argc > 1) - n = number(argv[1]); - if (n > shellparam.nparam) - error("can't shift that many"); - INTOFF; - shellparam.nparam -= n; - for (ap1 = shellparam.p ; --n >= 0 ; ap1++) { - if (shellparam.malloc) - ckfree(*ap1); - } - ap2 = shellparam.p; - while ((*ap2++ = *ap1++) != NULL); - shellparam.optnext = NULL; - INTON; - return 0; -} - - - -/* - * The set command builtin. - */ - -int -setcmd(int argc, char **argv) -{ - if (argc == 1) - return showvars(0, 0, 1); - INTOFF; - options(0); - optschanged(); - if (*argptr != NULL) { - setparam(argptr); - } - INTON; - return 0; -} - - -void -getoptsreset(const char *value) -{ - if (number(value) == 1) { - shellparam.optnext = NULL; - shellparam.reset = 1; - } -} - -/* - * The getopts builtin. Shellparam.optnext points to the next argument - * to be processed. Shellparam.optptr points to the next character to - * be processed in the current argument. If shellparam.optnext is NULL, - * then it's the first time getopts has been called. - */ - -int -getoptscmd(int argc, char **argv) -{ - char **optbase; - - if (argc < 3) - error("usage: getopts optstring var [arg]"); - else if (argc == 3) - optbase = shellparam.p; - else - optbase = &argv[3]; - - if (shellparam.reset == 1) { - shellparam.optnext = optbase; - shellparam.optptr = NULL; - shellparam.reset = 0; - } - - return getopts(argv[1], argv[2], optbase, &shellparam.optnext, - &shellparam.optptr); -} - -STATIC int -getopts(char *optstr, char *optvar, char **optfirst, char ***optnext, char **optpptr) -{ - char *p, *q; - char c = '?'; - int done = 0; - int ind = 0; - int err = 0; - char s[12]; - - if ((p = *optpptr) == NULL || *p == '\0') { - /* Current word is done, advance */ - if (*optnext == NULL) - return 1; - p = **optnext; - if (p == NULL || *p != '-' || *++p == '\0') { -atend: - ind = *optnext - optfirst + 1; - *optnext = NULL; - p = NULL; - done = 1; - goto out; - } - (*optnext)++; - if (p[0] == '-' && p[1] == '\0') /* check for "--" */ - goto atend; - } - - c = *p++; - for (q = optstr; *q != c; ) { - if (*q == '\0') { - if (optstr[0] == ':') { - s[0] = c; - s[1] = '\0'; - err |= setvarsafe("OPTARG", s, 0); - } else { - outfmt(&errout, "Illegal option -%c\n", c); - (void) unsetvar("OPTARG", 0); - } - c = '?'; - goto bad; - } - if (*++q == ':') - q++; - } - - if (*++q == ':') { - if (*p == '\0' && (p = **optnext) == NULL) { - if (optstr[0] == ':') { - s[0] = c; - s[1] = '\0'; - err |= setvarsafe("OPTARG", s, 0); - c = ':'; - } else { - outfmt(&errout, "No arg for -%c option\n", c); - (void) unsetvar("OPTARG", 0); - c = '?'; - } - goto bad; - } - - if (p == **optnext) - (*optnext)++; - err |= setvarsafe("OPTARG", p, 0); - p = NULL; - } else - err |= setvarsafe("OPTARG", "", 0); - ind = *optnext - optfirst + 1; - goto out; - -bad: - ind = 1; - *optnext = NULL; - p = NULL; -out: - *optpptr = p; - fmtstr(s, sizeof(s), "%d", ind); - err |= setvarsafe("OPTIND", s, VNOFUNC); - s[0] = c; - s[1] = '\0'; - err |= setvarsafe(optvar, s, 0); - if (err) { - *optnext = NULL; - *optpptr = NULL; - flushall(); - exraise(EXERROR); - } - return done; -} - -/* - * XXX - should get rid of. have all builtins use getopt(3). the - * library getopt must have the BSD extension static variable "optreset" - * otherwise it can't be used within the shell safely. - * - * Standard option processing (a la getopt) for builtin routines. The - * only argument that is passed to nextopt is the option string; the - * other arguments are unnecessary. It return the character, or '\0' on - * end of input. - */ - -int -nextopt(const char *optstring) -{ - char *p; - const char *q; - char c; - - if ((p = optptr) == NULL || *p == '\0') { - p = *argptr; - if (p == NULL || *p != '-' || *++p == '\0') - return '\0'; - argptr++; - if (p[0] == '-' && p[1] == '\0') /* check for "--" */ - return '\0'; - } - c = *p++; - for (q = optstring ; *q != c ; ) { - if (*q == '\0') - error("Illegal option -%c", c); - if (*++q == ':') - q++; - } - if (*++q == ':') { - if (*p == '\0' && (p = *argptr++) == NULL) - error("No arg for -%c option", c); - optionarg = p; - p = NULL; - } - optptr = p; - return c; -} diff --git a/bin/sh/options.h b/bin/sh/options.h deleted file mode 100644 index 465842830..000000000 --- a/bin/sh/options.h +++ /dev/null @@ -1,134 +0,0 @@ -/* $NetBSD: options.h,v 1.22 2015/05/26 21:35:15 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)options.h 8.2 (Berkeley) 5/4/95 - */ - -struct shparam { - int nparam; /* # of positional parameters (without $0) */ - unsigned char malloc; /* if parameter list dynamically allocated */ - unsigned char reset; /* if getopts has been reset */ - char **p; /* parameter list */ - char **optnext; /* next parameter to be processed by getopts */ - char *optptr; /* used by getopts */ -}; - - -struct optent { - const char *name; /* for set -o */ - const char letter; /* set [+/-] and $- */ - const char opt_set; /* mutually exclusive option set */ - unsigned char val; /* value of flag */ -}; - -/* Those marked [U] are required by posix, but have no effect! */ - -#ifdef DEFINE_OPTIONS -#define DEF_OPTS(name, letter, opt_set) {name, letter, opt_set, 0}, -struct optent optlist[] = { -#else -#define DEF_OPTS(name, letter, opt_set) -#endif -#define DEF_OPT(name,letter) DEF_OPTS(name, letter, 0) - -DEF_OPT( "errexit", 'e' ) /* exit on error */ -#define eflag optlist[0].val -DEF_OPT( "noglob", 'f' ) /* no pathname expansion */ -#define fflag optlist[1].val -DEF_OPT( "ignoreeof", 'I' ) /* do not exit on EOF */ -#define Iflag optlist[2].val -DEF_OPT( "interactive",'i' ) /* interactive shell */ -#define iflag optlist[3].val -DEF_OPT( "monitor", 'm' ) /* job control */ -#define mflag optlist[4].val -DEF_OPT( "noexec", 'n' ) /* [U] do not exec commands */ -#define nflag optlist[5].val -DEF_OPT( "stdin", 's' ) /* read from stdin */ -#define sflag optlist[6].val -DEF_OPT( "xtrace", 'x' ) /* trace after expansion */ -#define xflag optlist[7].val -DEF_OPT( "verbose", 'v' ) /* trace read input */ -#define vflag optlist[8].val -DEF_OPTS( "vi", 'V', 'V' ) /* vi style editing */ -#define Vflag optlist[9].val -DEF_OPTS( "emacs", 'E', 'V' ) /* emacs style editing */ -#define Eflag optlist[10].val -DEF_OPT( "noclobber", 'C' ) /* do not overwrite files with > */ -#define Cflag optlist[11].val -DEF_OPT( "allexport", 'a' ) /* export all variables */ -#define aflag optlist[12].val -DEF_OPT( "notify", 'b' ) /* [U] report completion of background jobs */ -#define bflag optlist[13].val -DEF_OPT( "nounset", 'u' ) /* error expansion of unset variables */ -#define uflag optlist[14].val -DEF_OPT( "quietprofile", 'q' ) -#define qflag optlist[15].val -DEF_OPT( "nolog", 0 ) /* [U] no functon defs in command history */ -#define nolog optlist[16].val -DEF_OPT( "cdprint", 0 ) /* always print result of cd */ -#define cdprint optlist[17].val -DEF_OPT( "tabcomplete", 0 ) /* causes filename expansion */ -#define tabcomplete optlist[18].val -DEF_OPT( "fork", 'F' ) /* use fork(2) instead of vfork(2) */ -#define usefork optlist[19].val -DEF_OPT( "nopriv", 'p' ) /* preserve privs even if set{u,g}id */ -#define pflag optlist[20].val -#ifdef DEBUG -DEF_OPT( "debug", 0 ) /* enable debug prints */ -#define debug optlist[21].val -#endif - -#ifdef DEFINE_OPTIONS - { 0, 0, 0, 0 }, -}; -#define NOPTS (sizeof optlist / sizeof optlist[0] - 1) -int sizeof_optlist = sizeof optlist; -#else -extern struct optent optlist[]; -extern int sizeof_optlist; -#endif - - -extern char *minusc; /* argument to -c option */ -extern char *arg0; /* $0 */ -extern struct shparam shellparam; /* $@ */ -extern char **argptr; /* argument list for builtin commands */ -extern char *optionarg; /* set by nextopt */ -extern char *optptr; /* used by nextopt */ - -void procargs(int, char **); -void optschanged(void); -void setparam(char **); -void freeparam(volatile struct shparam *); -int nextopt(const char *); -void getoptsreset(const char *); diff --git a/bin/sh/output.c b/bin/sh/output.c deleted file mode 100644 index cd33e8e0f..000000000 --- a/bin/sh/output.c +++ /dev/null @@ -1,556 +0,0 @@ -/* $NetBSD: output.c,v 1.33 2010/08/30 06:27:14 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)output.c 8.2 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: output.c,v 1.33 2010/08/30 06:27:14 christos Exp $"); -#endif -#endif /* not lint */ - -/* - * Shell output routines. We use our own output routines because: - * When a builtin command is interrupted we have to discard - * any pending output. - * When a builtin command appears in back quotes, we want to - * save the output of the command in a region obtained - * via malloc, rather than doing a fork and reading the - * output of the command via a pipe. - * Our output routines may be smaller than the stdio routines. - */ - -#include /* quad_t */ -#include /* BSD4_4 */ -#include - -#include /* defines BUFSIZ */ -#include -#include -#include -#include - -#include "shell.h" -#include "syntax.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" - - -#define OUTBUFSIZ BUFSIZ -#define BLOCK_OUT -2 /* output to a fixed block of memory */ -#define MEM_OUT -3 /* output to dynamically allocated memory */ - - -struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0}; -struct output errout = {NULL, 0, NULL, 100, 2, 0}; -struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0}; -struct output *out1 = &output; -struct output *out2 = &errout; - - - -#ifdef mkinit - -INCLUDE "output.h" -INCLUDE "memalloc.h" - -RESET { - out1 = &output; - out2 = &errout; - if (memout.buf != NULL) { - ckfree(memout.buf); - memout.buf = NULL; - } -} - -#endif - - -#ifdef notdef /* no longer used */ -/* - * Set up an output file to write to memory rather than a file. - */ - -void -open_mem(char *block, int length, struct output *file) -{ - file->nextc = block; - file->nleft = --length; - file->fd = BLOCK_OUT; - file->flags = 0; -} -#endif - - -void -out1str(const char *p) -{ - outstr(p, out1); -} - - -void -out2str(const char *p) -{ - outstr(p, out2); -} - - -void -outstr(const char *p, struct output *file) -{ - while (*p) - outc(*p++, file); - if (file == out2) - flushout(file); -} - - -void -out2shstr(const char *p) -{ - outshstr(p, out2); -} - - -void -outshstr(const char *p, struct output *file) -{ - static const char norm_chars [] \ - = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/-="; - int need_q = p[0] == 0 || p[strspn(p, norm_chars)] != 0; - char c; - - if (need_q) - outc('\'', file); - - while (c = *p++, c != 0){ - if (c != '\''){ - outc(c, file); - }else{ - outc('\'', file); - outc('\\', file); - outc(c, file); - outc('\'', file); - } - } - - if (need_q) - outc('\'', file); - - if (file == out2) - flushout(file); -} - - -char out_junk[16]; - - -void -emptyoutbuf(struct output *dest) -{ - int offset; - - if (dest->fd == BLOCK_OUT) { - dest->nextc = out_junk; - dest->nleft = sizeof out_junk; - dest->flags |= OUTPUT_ERR; - } else if (dest->buf == NULL) { - INTOFF; - dest->buf = ckmalloc(dest->bufsize); - dest->nextc = dest->buf; - dest->nleft = dest->bufsize; - INTON; - } else if (dest->fd == MEM_OUT) { - offset = dest->bufsize; - INTOFF; - dest->bufsize <<= 1; - dest->buf = ckrealloc(dest->buf, dest->bufsize); - dest->nleft = dest->bufsize - offset; - dest->nextc = dest->buf + offset; - INTON; - } else { - flushout(dest); - } - dest->nleft--; -} - - -void -flushall(void) -{ - flushout(&output); - flushout(&errout); -} - - -void -flushout(struct output *dest) -{ - - if (dest->buf == NULL || dest->nextc == dest->buf || dest->fd < 0) - return; - if (xwrite(dest->fd, dest->buf, dest->nextc - dest->buf) < 0) - dest->flags |= OUTPUT_ERR; - dest->nextc = dest->buf; - dest->nleft = dest->bufsize; -} - - -void -freestdout(void) -{ - INTOFF; - if (output.buf) { - ckfree(output.buf); - output.buf = NULL; - output.nleft = 0; - } - INTON; -} - - -void -outfmt(struct output *file, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - doformat(file, fmt, ap); - va_end(ap); -} - - -void -out1fmt(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - doformat(out1, fmt, ap); - va_end(ap); -} - -#ifdef DEBUG -void -debugprintf(const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - doformat(out2, fmt, ap); - va_end(ap); - flushout(out2); -} -#endif - -void -fmtstr(char *outbuf, size_t length, const char *fmt, ...) -{ - va_list ap; - struct output strout; - - va_start(ap, fmt); - strout.nextc = outbuf; - strout.nleft = length; - strout.fd = BLOCK_OUT; - strout.flags = 0; - doformat(&strout, fmt, ap); - outc('\0', &strout); - if (strout.flags & OUTPUT_ERR) - outbuf[length - 1] = '\0'; - va_end(ap); -} - -/* - * Formatted output. This routine handles a subset of the printf formats: - * - Formats supported: d, u, o, p, X, s, and c. - * - The x format is also accepted but is treated like X. - * - The l, ll and q modifiers are accepted. - * - The - and # flags are accepted; # only works with the o format. - * - Width and precision may be specified with any format except c. - * - An * may be given for the width or precision. - * - The obsolete practice of preceding the width with a zero to get - * zero padding is not supported; use the precision field. - * - A % may be printed by writing %% in the format string. - */ - -#define TEMPSIZE 24 - -#ifdef BSD4_4 -#define HAVE_VASPRINTF 1 -#endif - -void -doformat(struct output *dest, const char *f, va_list ap) -{ -#if HAVE_VASPRINTF - char *s; - - vasprintf(&s, f, ap); - if (s == NULL) - error("Could not allocate formatted output buffer"); - outstr(s, dest); - free(s); -#else /* !HAVE_VASPRINTF */ - static const char digit[] = "0123456789ABCDEF"; - char c; - char temp[TEMPSIZE]; - int flushleft; - int sharp; - int width; - int prec; - int islong; - int isquad; - char *p; - int sign; -#ifdef BSD4_4 - quad_t l; - u_quad_t num; -#else - long l; - u_long num; -#endif - unsigned base; - int len; - int size; - int pad; - - while ((c = *f++) != '\0') { - if (c != '%') { - outc(c, dest); - continue; - } - flushleft = 0; - sharp = 0; - width = 0; - prec = -1; - islong = 0; - isquad = 0; - for (;;) { - if (*f == '-') - flushleft++; - else if (*f == '#') - sharp++; - else - break; - f++; - } - if (*f == '*') { - width = va_arg(ap, int); - f++; - } else { - while (is_digit(*f)) { - width = 10 * width + digit_val(*f++); - } - } - if (*f == '.') { - if (*++f == '*') { - prec = va_arg(ap, int); - f++; - } else { - prec = 0; - while (is_digit(*f)) { - prec = 10 * prec + digit_val(*f++); - } - } - } - if (*f == 'l') { - f++; - if (*f == 'l') { - isquad++; - f++; - } else - islong++; - } else if (*f == 'q') { - isquad++; - f++; - } - switch (*f) { - case 'd': -#ifdef BSD4_4 - if (isquad) - l = va_arg(ap, quad_t); - else -#endif - if (islong) - l = va_arg(ap, long); - else - l = va_arg(ap, int); - sign = 0; - num = l; - if (l < 0) { - num = -l; - sign = 1; - } - base = 10; - goto number; - case 'u': - base = 10; - goto uns_number; - case 'o': - base = 8; - goto uns_number; - case 'p': - outc('0', dest); - outc('x', dest); - /*FALLTHROUGH*/ - case 'x': - /* we don't implement 'x'; treat like 'X' */ - case 'X': - base = 16; -uns_number: /* an unsigned number */ - sign = 0; -#ifdef BSD4_4 - if (isquad) - num = va_arg(ap, u_quad_t); - else -#endif - if (islong) - num = va_arg(ap, unsigned long); - else - num = va_arg(ap, unsigned int); -number: /* process a number */ - p = temp + TEMPSIZE - 1; - *p = '\0'; - while (num) { - *--p = digit[num % base]; - num /= base; - } - len = (temp + TEMPSIZE - 1) - p; - if (prec < 0) - prec = 1; - if (sharp && *f == 'o' && prec <= len) - prec = len + 1; - pad = 0; - if (width) { - size = len; - if (size < prec) - size = prec; - size += sign; - pad = width - size; - if (flushleft == 0) { - while (--pad >= 0) - outc(' ', dest); - } - } - if (sign) - outc('-', dest); - prec -= len; - while (--prec >= 0) - outc('0', dest); - while (*p) - outc(*p++, dest); - while (--pad >= 0) - outc(' ', dest); - break; - case 's': - p = va_arg(ap, char *); - pad = 0; - if (width) { - len = strlen(p); - if (prec >= 0 && len > prec) - len = prec; - pad = width - len; - if (flushleft == 0) { - while (--pad >= 0) - outc(' ', dest); - } - } - prec++; - while (--prec != 0 && *p) - outc(*p++, dest); - while (--pad >= 0) - outc(' ', dest); - break; - case 'c': - c = va_arg(ap, int); - outc(c, dest); - break; - default: - outc(*f, dest); - break; - } - f++; - } -#endif /* !HAVE_VASPRINTF */ -} - - - -/* - * Version of write which resumes after a signal is caught. - */ - -int -xwrite(int fd, char *buf, int nbytes) -{ - int ntry; - int i; - int n; - - n = nbytes; - ntry = 0; - for (;;) { - i = write(fd, buf, n); - if (i > 0) { - if ((n -= i) <= 0) - return nbytes; - buf += i; - ntry = 0; - } else if (i == 0) { - if (++ntry > 10) - return nbytes - n; - } else if (errno != EINTR) { - return -1; - } - } -} - - -/* - * Version of ioctl that retries after a signal is caught. - * XXX unused function - */ - -int -xioctl(int fd, unsigned long request, char *arg) -{ - int i; - - while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR); - return i; -} diff --git a/bin/sh/output.h b/bin/sh/output.h deleted file mode 100644 index 618a09533..000000000 --- a/bin/sh/output.h +++ /dev/null @@ -1,84 +0,0 @@ -/* $NetBSD: output.h,v 1.24 2012/03/15 02:02:20 joerg Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)output.h 8.2 (Berkeley) 5/4/95 - */ - -#ifndef OUTPUT_INCL - -#include - -struct output { - char *nextc; - int nleft; - char *buf; - int bufsize; - short fd; - short flags; -}; - -/* flags for ->flags */ -#define OUTPUT_ERR 01 /* error occurred on output */ - -extern struct output output; -extern struct output errout; -extern struct output memout; -extern struct output *out1; -extern struct output *out2; - -void open_mem(char *, int, struct output *); -void out1str(const char *); -void out2str(const char *); -void outstr(const char *, struct output *); -void out2shstr(const char *); -void outshstr(const char *, struct output *); -void emptyoutbuf(struct output *); -void flushall(void); -void flushout(struct output *); -void freestdout(void); -void outfmt(struct output *, const char *, ...) __printflike(2, 3); -void out1fmt(const char *, ...) __printflike(1, 2); -#ifdef DEBUG -void debugprintf(const char *, ...) __printflike(1, 2); -#endif -void fmtstr(char *, size_t, const char *, ...) __printflike(3, 4); -void doformat(struct output *, const char *, va_list) __printflike(2, 0); -int xwrite(int, char *, int); -int xioctl(int, unsigned long, char *); - -#define outc(c, file) (--(file)->nleft < 0? (emptyoutbuf(file), *(file)->nextc++ = (c)) : (*(file)->nextc++ = (c))) -#define out1c(c) outc(c, out1) -#define out2c(c) outc(c, out2) - -#define OUTPUT_INCL -#endif diff --git a/bin/sh/parser.c b/bin/sh/parser.c deleted file mode 100644 index e758c08e1..000000000 --- a/bin/sh/parser.c +++ /dev/null @@ -1,1686 +0,0 @@ -/* $NetBSD: parser.c,v 1.93 2014/08/29 09:35:19 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; -#else -__RCSID("$NetBSD: parser.c,v 1.93 2014/08/29 09:35:19 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include - -#include "shell.h" -#include "parser.h" -#include "nodes.h" -#include "expand.h" /* defines rmescapes() */ -#include "eval.h" /* defines commandname */ -#include "redir.h" /* defines copyfd() */ -#include "syntax.h" -#include "options.h" -#include "input.h" -#include "output.h" -#include "var.h" -#include "error.h" -#include "memalloc.h" -#include "mystring.h" -#include "alias.h" -#include "show.h" -#ifndef SMALL -#include "myhistedit.h" -#endif - -/* - * Shell command parser. - */ - -#define EOFMARKLEN 79 - -/* values returned by readtoken */ -#include "token.h" - -#define OPENBRACE '{' -#define CLOSEBRACE '}' - - -struct heredoc { - struct heredoc *next; /* next here document in list */ - union node *here; /* redirection node */ - char *eofmark; /* string indicating end of input */ - int striptabs; /* if set, strip leading tabs */ -}; - - - -static int noalias = 0; /* when set, don't handle aliases */ -struct heredoc *heredoclist; /* list of here documents to read */ -int parsebackquote; /* nonzero if we are inside backquotes */ -int doprompt; /* if set, prompt the user */ -int needprompt; /* true if interactive and at start of line */ -int lasttoken; /* last token read */ -MKINIT int tokpushback; /* last token pushed back */ -char *wordtext; /* text of last word returned by readtoken */ -MKINIT int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */ -struct nodelist *backquotelist; -union node *redirnode; -struct heredoc *heredoc; -int quoteflag; /* set if (part of) last token was quoted */ -int startlinno; /* line # where last token started */ -int funclinno; /* line # where the current function started */ - - -STATIC union node *list(int, int); -STATIC union node *andor(void); -STATIC union node *pipeline(void); -STATIC union node *command(void); -STATIC union node *simplecmd(union node **, union node *); -STATIC union node *makename(void); -STATIC void parsefname(void); -STATIC void parseheredoc(void); -STATIC int peektoken(void); -STATIC int readtoken(void); -STATIC int xxreadtoken(void); -STATIC int readtoken1(int, char const *, char *, int); -STATIC int noexpand(char *); -STATIC void synexpect(int) __dead; -STATIC void synerror(const char *) __dead; -STATIC void setprompt(int); - - -/* - * Read and parse a command. Returns NEOF on end of file. (NULL is a - * valid parse tree indicating a blank line.) - */ - -union node * -parsecmd(int interact) -{ - int t; - - tokpushback = 0; - doprompt = interact; - if (doprompt) - setprompt(1); - else - setprompt(0); - needprompt = 0; - t = readtoken(); - if (t == TEOF) - return NEOF; - if (t == TNL) - return NULL; - tokpushback++; - return list(1, 0); -} - - -STATIC union node * -list(int nlflag, int erflag) -{ - union node *n1, *n2, *n3; - int tok; - TRACE(("list: entered\n")); - - checkkwd = 2; - if (nlflag == 0 && tokendlist[peektoken()]) - return NULL; - n1 = NULL; - for (;;) { - n2 = andor(); - tok = readtoken(); - if (tok == TBACKGND) { - if (n2->type == NCMD || n2->type == NPIPE) { - n2->ncmd.backgnd = 1; - } else if (n2->type == NREDIR) { - n2->type = NBACKGND; - } else { - n3 = (union node *)stalloc(sizeof (struct nredir)); - n3->type = NBACKGND; - n3->nredir.n = n2; - n3->nredir.redirect = NULL; - n2 = n3; - } - } - if (n1 == NULL) { - n1 = n2; - } - else { - n3 = (union node *)stalloc(sizeof (struct nbinary)); - n3->type = NSEMI; - n3->nbinary.ch1 = n1; - n3->nbinary.ch2 = n2; - n1 = n3; - } - switch (tok) { - case TBACKGND: - case TSEMI: - tok = readtoken(); - /* fall through */ - case TNL: - if (tok == TNL) { - parseheredoc(); - if (nlflag) - return n1; - } else { - tokpushback++; - } - checkkwd = 2; - if (tokendlist[peektoken()]) - return n1; - break; - case TEOF: - if (heredoclist) - parseheredoc(); - else - pungetc(); /* push back EOF on input */ - return n1; - default: - if (nlflag || erflag) - synexpect(-1); - tokpushback++; - return n1; - } - } -} - - - -STATIC union node * -andor(void) -{ - union node *n1, *n2, *n3; - int t; - - TRACE(("andor: entered\n")); - n1 = pipeline(); - for (;;) { - if ((t = readtoken()) == TAND) { - t = NAND; - } else if (t == TOR) { - t = NOR; - } else { - tokpushback++; - return n1; - } - n2 = pipeline(); - n3 = (union node *)stalloc(sizeof (struct nbinary)); - n3->type = t; - n3->nbinary.ch1 = n1; - n3->nbinary.ch2 = n2; - n1 = n3; - } -} - - - -STATIC union node * -pipeline(void) -{ - union node *n1, *n2, *pipenode; - struct nodelist *lp, *prev; - int negate; - - TRACE(("pipeline: entered\n")); - - negate = 0; - checkkwd = 2; - while (readtoken() == TNOT) { - TRACE(("pipeline: TNOT recognized\n")); - negate = !negate; - } - tokpushback++; - n1 = command(); - if (readtoken() == TPIPE) { - pipenode = (union node *)stalloc(sizeof (struct npipe)); - pipenode->type = NPIPE; - pipenode->npipe.backgnd = 0; - lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); - pipenode->npipe.cmdlist = lp; - lp->n = n1; - do { - prev = lp; - lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); - lp->n = command(); - prev->next = lp; - } while (readtoken() == TPIPE); - lp->next = NULL; - n1 = pipenode; - } - tokpushback++; - if (negate) { - TRACE(("negate pipeline\n")); - n2 = (union node *)stalloc(sizeof (struct nnot)); - n2->type = NNOT; - n2->nnot.com = n1; - return n2; - } else - return n1; -} - - - -STATIC union node * -command(void) -{ - union node *n1, *n2; - union node *ap, **app; - union node *cp, **cpp; - union node *redir, **rpp; - int t, negate = 0; - - TRACE(("command: entered\n")); - - checkkwd = 2; - redir = NULL; - n1 = NULL; - rpp = &redir; - - /* Check for redirection which may precede command */ - while (readtoken() == TREDIR) { - *rpp = n2 = redirnode; - rpp = &n2->nfile.next; - parsefname(); - } - tokpushback++; - - while (readtoken() == TNOT) { - TRACE(("command: TNOT recognized\n")); - negate = !negate; - } - tokpushback++; - - switch (readtoken()) { - case TIF: - n1 = (union node *)stalloc(sizeof (struct nif)); - n1->type = NIF; - n1->nif.test = list(0, 0); - if (readtoken() != TTHEN) - synexpect(TTHEN); - n1->nif.ifpart = list(0, 0); - n2 = n1; - while (readtoken() == TELIF) { - n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif)); - n2 = n2->nif.elsepart; - n2->type = NIF; - n2->nif.test = list(0, 0); - if (readtoken() != TTHEN) - synexpect(TTHEN); - n2->nif.ifpart = list(0, 0); - } - if (lasttoken == TELSE) - n2->nif.elsepart = list(0, 0); - else { - n2->nif.elsepart = NULL; - tokpushback++; - } - if (readtoken() != TFI) - synexpect(TFI); - checkkwd = 1; - break; - case TWHILE: - case TUNTIL: { - int got; - n1 = (union node *)stalloc(sizeof (struct nbinary)); - n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL; - n1->nbinary.ch1 = list(0, 0); - if ((got=readtoken()) != TDO) { -TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); - synexpect(TDO); - } - n1->nbinary.ch2 = list(0, 0); - if (readtoken() != TDONE) - synexpect(TDONE); - checkkwd = 1; - break; - } - case TFOR: - if (readtoken() != TWORD || quoteflag || ! goodname(wordtext)) - synerror("Bad for loop variable"); - n1 = (union node *)stalloc(sizeof (struct nfor)); - n1->type = NFOR; - n1->nfor.var = wordtext; - if (readtoken() == TWORD && ! quoteflag && equal(wordtext, "in")) { - app = ≈ - while (readtoken() == TWORD) { - n2 = (union node *)stalloc(sizeof (struct narg)); - n2->type = NARG; - n2->narg.text = wordtext; - n2->narg.backquote = backquotelist; - *app = n2; - app = &n2->narg.next; - } - *app = NULL; - n1->nfor.args = ap; - if (lasttoken != TNL && lasttoken != TSEMI) - synexpect(-1); - } else { - static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE, - '@', '=', '\0'}; - n2 = (union node *)stalloc(sizeof (struct narg)); - n2->type = NARG; - n2->narg.text = argvars; - n2->narg.backquote = NULL; - n2->narg.next = NULL; - n1->nfor.args = n2; - /* - * Newline or semicolon here is optional (but note - * that the original Bourne shell only allowed NL). - */ - if (lasttoken != TNL && lasttoken != TSEMI) - tokpushback++; - } - checkkwd = 2; - if ((t = readtoken()) == TDO) - t = TDONE; - else if (t == TBEGIN) - t = TEND; - else - synexpect(-1); - n1->nfor.body = list(0, 0); - if (readtoken() != t) - synexpect(t); - checkkwd = 1; - break; - case TCASE: - n1 = (union node *)stalloc(sizeof (struct ncase)); - n1->type = NCASE; - if (readtoken() != TWORD) - synexpect(TWORD); - n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg)); - n2->type = NARG; - n2->narg.text = wordtext; - n2->narg.backquote = backquotelist; - n2->narg.next = NULL; - while (readtoken() == TNL); - if (lasttoken != TWORD || ! equal(wordtext, "in")) - synerror("expecting \"in\""); - cpp = &n1->ncase.cases; - noalias = 1; - checkkwd = 2, readtoken(); - /* - * Both ksh and bash accept 'case x in esac' - * so configure scripts started taking advantage of this. - * The page: http://pubs.opengroup.org/onlinepubs/\ - * 009695399/utilities/xcu_chap02.html contradicts itself, - * as to if this is legal; the "Case Conditional Format" - * paragraph shows one case is required, but the "Grammar" - * section shows a grammar that explicitly allows the no - * case option. - */ - while (lasttoken != TESAC) { - *cpp = cp = (union node *)stalloc(sizeof (struct nclist)); - if (lasttoken == TLP) - readtoken(); - cp->type = NCLIST; - app = &cp->nclist.pattern; - for (;;) { - *app = ap = (union node *)stalloc(sizeof (struct narg)); - ap->type = NARG; - ap->narg.text = wordtext; - ap->narg.backquote = backquotelist; - if (checkkwd = 2, readtoken() != TPIPE) - break; - app = &ap->narg.next; - readtoken(); - } - ap->narg.next = NULL; - noalias = 0; - if (lasttoken != TRP) { - synexpect(TRP); - } - cp->nclist.body = list(0, 0); - - checkkwd = 2; - if ((t = readtoken()) != TESAC) { - if (t != TENDCASE) { - noalias = 0; - synexpect(TENDCASE); - } else { - noalias = 1; - checkkwd = 2; - readtoken(); - } - } - cpp = &cp->nclist.next; - } - noalias = 0; - *cpp = NULL; - checkkwd = 1; - break; - case TLP: - n1 = (union node *)stalloc(sizeof (struct nredir)); - n1->type = NSUBSHELL; - n1->nredir.n = list(0, 0); - n1->nredir.redirect = NULL; - if (readtoken() != TRP) - synexpect(TRP); - checkkwd = 1; - break; - case TBEGIN: - n1 = list(0, 0); - if (readtoken() != TEND) - synexpect(TEND); - checkkwd = 1; - break; - /* Handle an empty command like other simple commands. */ - case TSEMI: - /* - * An empty command before a ; doesn't make much sense, and - * should certainly be disallowed in the case of `if ;'. - */ - if (!redir) - synexpect(-1); - case TAND: - case TOR: - case TNL: - case TEOF: - case TWORD: - case TRP: - tokpushback++; - n1 = simplecmd(rpp, redir); - goto checkneg; - default: - synexpect(-1); - /* NOTREACHED */ - } - - /* Now check for redirection which may follow command */ - while (readtoken() == TREDIR) { - *rpp = n2 = redirnode; - rpp = &n2->nfile.next; - parsefname(); - } - tokpushback++; - *rpp = NULL; - if (redir) { - if (n1->type != NSUBSHELL) { - n2 = (union node *)stalloc(sizeof (struct nredir)); - n2->type = NREDIR; - n2->nredir.n = n1; - n1 = n2; - } - n1->nredir.redirect = redir; - } - -checkneg: - if (negate) { - TRACE(("negate command\n")); - n2 = (union node *)stalloc(sizeof (struct nnot)); - n2->type = NNOT; - n2->nnot.com = n1; - return n2; - } - else - return n1; -} - - -STATIC union node * -simplecmd(union node **rpp, union node *redir) -{ - union node *args, **app; - union node **orig_rpp = rpp; - union node *n = NULL, *n2; - int negate = 0; - - /* If we don't have any redirections already, then we must reset */ - /* rpp to be the address of the local redir variable. */ - if (redir == 0) - rpp = &redir; - - args = NULL; - app = &args; - /* - * We save the incoming value, because we need this for shell - * functions. There can not be a redirect or an argument between - * the function name and the open parenthesis. - */ - orig_rpp = rpp; - - while (readtoken() == TNOT) { - TRACE(("simplcmd: TNOT recognized\n")); - negate = !negate; - } - tokpushback++; - - for (;;) { - if (readtoken() == TWORD) { - n = (union node *)stalloc(sizeof (struct narg)); - n->type = NARG; - n->narg.text = wordtext; - n->narg.backquote = backquotelist; - *app = n; - app = &n->narg.next; - } else if (lasttoken == TREDIR) { - *rpp = n = redirnode; - rpp = &n->nfile.next; - parsefname(); /* read name of redirection file */ - } else if (lasttoken == TLP && app == &args->narg.next - && rpp == orig_rpp) { - /* We have a function */ - if (readtoken() != TRP) - synexpect(TRP); - funclinno = plinno; - rmescapes(n->narg.text); - if (!goodname(n->narg.text)) - synerror("Bad function name"); - n->type = NDEFUN; - n->narg.next = command(); - funclinno = 0; - goto checkneg; - } else { - tokpushback++; - break; - } - } - *app = NULL; - *rpp = NULL; - n = (union node *)stalloc(sizeof (struct ncmd)); - n->type = NCMD; - n->ncmd.backgnd = 0; - n->ncmd.args = args; - n->ncmd.redirect = redir; - -checkneg: - if (negate) { - TRACE(("negate simplecmd\n")); - n2 = (union node *)stalloc(sizeof (struct nnot)); - n2->type = NNOT; - n2->nnot.com = n; - return n2; - } - else - return n; -} - -STATIC union node * -makename(void) -{ - union node *n; - - n = (union node *)stalloc(sizeof (struct narg)); - n->type = NARG; - n->narg.next = NULL; - n->narg.text = wordtext; - n->narg.backquote = backquotelist; - return n; -} - -void fixredir(union node *n, const char *text, int err) - { - TRACE(("Fix redir %s %d\n", text, err)); - if (!err) - n->ndup.vname = NULL; - - if (is_number(text)) - n->ndup.dupfd = number(text); - else if (text[0] == '-' && text[1] == '\0') - n->ndup.dupfd = -1; - else { - - if (err) - synerror("Bad fd number"); - else - n->ndup.vname = makename(); - } -} - - -STATIC void -parsefname(void) -{ - union node *n = redirnode; - - if (readtoken() != TWORD) - synexpect(-1); - if (n->type == NHERE) { - struct heredoc *here = heredoc; - struct heredoc *p; - int i; - - if (quoteflag == 0) - n->type = NXHERE; - TRACE(("Here document %d\n", n->type)); - if (here->striptabs) { - while (*wordtext == '\t') - wordtext++; - } - if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN) - synerror("Illegal eof marker for << redirection"); - rmescapes(wordtext); - here->eofmark = wordtext; - here->next = NULL; - if (heredoclist == NULL) - heredoclist = here; - else { - for (p = heredoclist ; p->next ; p = p->next) - continue; - p->next = here; - } - } else if (n->type == NTOFD || n->type == NFROMFD) { - fixredir(n, wordtext, 0); - } else { - n->nfile.fname = makename(); - } -} - - -/* - * Input any here documents. - */ - -STATIC void -parseheredoc(void) -{ - struct heredoc *here; - union node *n; - - while (heredoclist) { - here = heredoclist; - heredoclist = here->next; - if (needprompt) { - setprompt(2); - needprompt = 0; - } - readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX, - here->eofmark, here->striptabs); - n = (union node *)stalloc(sizeof (struct narg)); - n->narg.type = NARG; - n->narg.next = NULL; - n->narg.text = wordtext; - n->narg.backquote = backquotelist; - here->here->nhere.doc = n; - } -} - -STATIC int -peektoken(void) -{ - int t; - - t = readtoken(); - tokpushback++; - return (t); -} - -STATIC int -readtoken(void) -{ - int t; - int savecheckkwd = checkkwd; -#ifdef DEBUG - int alreadyseen = tokpushback; -#endif - struct alias *ap; - - top: - t = xxreadtoken(); - - if (checkkwd) { - /* - * eat newlines - */ - if (checkkwd == 2) { - checkkwd = 0; - while (t == TNL) { - parseheredoc(); - t = xxreadtoken(); - } - } else - checkkwd = 0; - /* - * check for keywords and aliases - */ - if (t == TWORD && !quoteflag) - { - const char *const *pp; - - for (pp = parsekwd; *pp; pp++) { - if (**pp == *wordtext && equal(*pp, wordtext)) - { - lasttoken = t = pp - - parsekwd + KWDOFFSET; - TRACE(("keyword %s recognized\n", tokname[t])); - goto out; - } - } - if (!noalias && - (ap = lookupalias(wordtext, 1)) != NULL) { - pushstring(ap->val, strlen(ap->val), ap); - checkkwd = savecheckkwd; - goto top; - } - } -out: - checkkwd = (t == TNOT) ? savecheckkwd : 0; - } - TRACE(("%stoken %s %s\n", alreadyseen ? "reread " : "", tokname[t], t == TWORD ? wordtext : "")); - return (t); -} - - -/* - * Read the next input token. - * If the token is a word, we set backquotelist to the list of cmds in - * backquotes. We set quoteflag to true if any part of the word was - * quoted. - * If the token is TREDIR, then we set redirnode to a structure containing - * the redirection. - * In all cases, the variable startlinno is set to the number of the line - * on which the token starts. - * - * [Change comment: here documents and internal procedures] - * [Readtoken shouldn't have any arguments. Perhaps we should make the - * word parsing code into a separate routine. In this case, readtoken - * doesn't need to have any internal procedures, but parseword does. - * We could also make parseoperator in essence the main routine, and - * have parseword (readtoken1?) handle both words and redirection.] - */ - -#define RETURN(token) return lasttoken = token - -STATIC int -xxreadtoken(void) -{ - int c; - - if (tokpushback) { - tokpushback = 0; - return lasttoken; - } - if (needprompt) { - setprompt(2); - needprompt = 0; - } - startlinno = plinno; - for (;;) { /* until token or start of word found */ - c = pgetc_macro(); - switch (c) { - case ' ': case '\t': - continue; - case '#': - while ((c = pgetc()) != '\n' && c != PEOF) - continue; - pungetc(); - continue; - case '\\': - switch (pgetc()) { - case '\n': - startlinno = ++plinno; - if (doprompt) - setprompt(2); - else - setprompt(0); - continue; - case PEOF: - RETURN(TEOF); - default: - pungetc(); - break; - } - goto breakloop; - case '\n': - plinno++; - needprompt = doprompt; - RETURN(TNL); - case PEOF: - RETURN(TEOF); - case '&': - if (pgetc() == '&') - RETURN(TAND); - pungetc(); - RETURN(TBACKGND); - case '|': - if (pgetc() == '|') - RETURN(TOR); - pungetc(); - RETURN(TPIPE); - case ';': - if (pgetc() == ';') - RETURN(TENDCASE); - pungetc(); - RETURN(TSEMI); - case '(': - RETURN(TLP); - case ')': - RETURN(TRP); - default: - goto breakloop; - } - } -breakloop: - return readtoken1(c, BASESYNTAX, NULL, 0); -#undef RETURN -} - - - -/* - * If eofmark is NULL, read a word or a redirection symbol. If eofmark - * is not NULL, read a here document. In the latter case, eofmark is the - * word which marks the end of the document and striptabs is true if - * leading tabs should be stripped from the document. The argument firstc - * is the first character of the input token or document. - * - * Because C does not have internal subroutines, I have simulated them - * using goto's to implement the subroutine linkage. The following macros - * will run code that appears at the end of readtoken1. - */ - -#define CHECKEND() {goto checkend; checkend_return:;} -#define PARSEREDIR() {goto parseredir; parseredir_return:;} -#define PARSESUB() {goto parsesub; parsesub_return:;} -#define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;} -#define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;} -#define PARSEARITH() {goto parsearith; parsearith_return:;} - -/* - * Keep track of nested doublequotes in dblquote and doublequotep. - * We use dblquote for the first 32 levels, and we expand to a malloc'ed - * region for levels above that. Usually we never need to malloc. - * This code assumes that an int is 32 bits. We don't use uint32_t, - * because the rest of the code does not. - */ -#define ISDBLQUOTE() ((varnest < 32) ? (dblquote & (1 << varnest)) : \ - (dblquotep[(varnest / 32) - 1] & (1 << (varnest % 32)))) - -#define SETDBLQUOTE() \ - if (varnest < 32) \ - dblquote |= (1 << varnest); \ - else \ - dblquotep[(varnest / 32) - 1] |= (1 << (varnest % 32)) - -#define CLRDBLQUOTE() \ - if (varnest < 32) \ - dblquote &= ~(1 << varnest); \ - else \ - dblquotep[(varnest / 32) - 1] &= ~(1 << (varnest % 32)) - -STATIC int -readtoken1(int firstc, char const *syn, char *eofmark, int striptabs) -{ - char const * volatile syntax = syn; - int c = firstc; - char * volatile out; - int len; - char line[EOFMARKLEN + 1]; - struct nodelist *bqlist; - volatile int quotef; - int * volatile dblquotep = NULL; - volatile size_t maxnest = 32; - volatile int dblquote; - volatile size_t varnest; /* levels of variables expansion */ - volatile int arinest; /* levels of arithmetic expansion */ - volatile int parenlevel; /* levels of parens in arithmetic */ - volatile int oldstyle; - char const * volatile prevsyntax; /* syntax before arithmetic */ -#ifdef __GNUC__ - prevsyntax = NULL; /* XXX gcc4 */ -#endif - - startlinno = plinno; - dblquote = 0; - varnest = 0; - if (syntax == DQSYNTAX) { - SETDBLQUOTE(); - } - quotef = 0; - bqlist = NULL; - arinest = 0; - parenlevel = 0; - - STARTSTACKSTR(out); - loop: { /* for each line, until end of word */ -#if ATTY - if (c == '\034' && doprompt - && attyset() && ! equal(termval(), "emacs")) { - attyline(); - if (syntax == BASESYNTAX) - return readtoken(); - c = pgetc(); - goto loop; - } -#endif - CHECKEND(); /* set c to PEOF if at end of here document */ - for (;;) { /* until end of line or end of word */ - CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */ - switch(syntax[c]) { - case CNL: /* '\n' */ - if (syntax == BASESYNTAX) - goto endword; /* exit outer loop */ - USTPUTC(c, out); - plinno++; - if (doprompt) - setprompt(2); - else - setprompt(0); - c = pgetc(); - goto loop; /* continue outer loop */ - case CWORD: - USTPUTC(c, out); - break; - case CCTL: - if (eofmark == NULL || ISDBLQUOTE()) - USTPUTC(CTLESC, out); - USTPUTC(c, out); - break; - case CBACK: /* backslash */ - c = pgetc(); - if (c == PEOF) { - USTPUTC('\\', out); - pungetc(); - break; - } - if (c == '\n') { - plinno++; - if (doprompt) - setprompt(2); - else - setprompt(0); - break; - } - quotef = 1; - if (ISDBLQUOTE() && c != '\\' && - c != '`' && c != '$' && - (c != '"' || eofmark != NULL)) - USTPUTC('\\', out); - if (SQSYNTAX[c] == CCTL) - USTPUTC(CTLESC, out); - else if (eofmark == NULL) { - USTPUTC(CTLQUOTEMARK, out); - USTPUTC(c, out); - if (varnest != 0) - USTPUTC(CTLQUOTEEND, out); - break; - } - USTPUTC(c, out); - break; - case CSQUOTE: - if (syntax != SQSYNTAX) { - if (eofmark == NULL) - USTPUTC(CTLQUOTEMARK, out); - quotef = 1; - syntax = SQSYNTAX; - break; - } - if (eofmark != NULL && arinest == 0 && - varnest == 0) { - /* Ignore inside quoted here document */ - USTPUTC(c, out); - break; - } - /* End of single quotes... */ - if (arinest) - syntax = ARISYNTAX; - else { - syntax = BASESYNTAX; - if (varnest != 0) - USTPUTC(CTLQUOTEEND, out); - } - break; - case CDQUOTE: - if (eofmark != NULL && arinest == 0 && - varnest == 0) { - /* Ignore inside here document */ - USTPUTC(c, out); - break; - } - quotef = 1; - if (arinest) { - if (ISDBLQUOTE()) { - syntax = ARISYNTAX; - CLRDBLQUOTE(); - } else { - syntax = DQSYNTAX; - SETDBLQUOTE(); - USTPUTC(CTLQUOTEMARK, out); - } - break; - } - if (eofmark != NULL) - break; - if (ISDBLQUOTE()) { - if (varnest != 0) - USTPUTC(CTLQUOTEEND, out); - syntax = BASESYNTAX; - CLRDBLQUOTE(); - } else { - syntax = DQSYNTAX; - SETDBLQUOTE(); - USTPUTC(CTLQUOTEMARK, out); - } - break; - case CVAR: /* '$' */ - PARSESUB(); /* parse substitution */ - break; - case CENDVAR: /* CLOSEBRACE */ - if (varnest > 0 && !ISDBLQUOTE()) { - varnest--; - USTPUTC(CTLENDVAR, out); - } else { - USTPUTC(c, out); - } - break; - case CLP: /* '(' in arithmetic */ - parenlevel++; - USTPUTC(c, out); - break; - case CRP: /* ')' in arithmetic */ - if (parenlevel > 0) { - USTPUTC(c, out); - --parenlevel; - } else { - if (pgetc() == ')') { - if (--arinest == 0) { - USTPUTC(CTLENDARI, out); - syntax = prevsyntax; - if (syntax == DQSYNTAX) - SETDBLQUOTE(); - else - CLRDBLQUOTE(); - } else - USTPUTC(')', out); - } else { - /* - * unbalanced parens - * (don't 2nd guess - no error) - */ - pungetc(); - USTPUTC(')', out); - } - } - break; - case CBQUOTE: /* '`' */ - PARSEBACKQOLD(); - break; - case CEOF: - goto endword; /* exit outer loop */ - default: - if (varnest == 0 && !ISDBLQUOTE()) - goto endword; /* exit outer loop */ - USTPUTC(c, out); - } - c = pgetc_macro(); - } - } -endword: - if (syntax == ARISYNTAX) - synerror("Missing '))'"); - if (syntax != BASESYNTAX && /* ! parsebackquote && */ eofmark == NULL) - synerror("Unterminated quoted string"); - if (varnest != 0) { - startlinno = plinno; - /* { */ - synerror("Missing '}'"); - } - USTPUTC('\0', out); - len = out - stackblock(); - out = stackblock(); - if (eofmark == NULL) { - if ((c == '>' || c == '<') - && quotef == 0 - && (*out == '\0' || is_number(out))) { - PARSEREDIR(); - return lasttoken = TREDIR; - } else { - pungetc(); - } - } - quoteflag = quotef; - backquotelist = bqlist; - grabstackblock(len); - wordtext = out; - if (dblquotep != NULL) - ckfree(dblquotep); - return lasttoken = TWORD; -/* end of readtoken routine */ - - - -/* - * Check to see whether we are at the end of the here document. When this - * is called, c is set to the first character of the next input line. If - * we are at the end of the here document, this routine sets the c to PEOF. - */ - -checkend: { - if (eofmark) { - if (striptabs) { - while (c == '\t') - c = pgetc(); - } - if (c == *eofmark) { - if (pfgets(line, sizeof line) != NULL) { - char *p, *q; - - p = line; - for (q = eofmark + 1 ; *q && *p == *q ; p++, q++) - continue; - if ((*p == '\0' || *p == '\n') && *q == '\0') { - c = PEOF; - plinno++; - needprompt = doprompt; - } else { - pushstring(line, strlen(line), NULL); - } - } - } - } - goto checkend_return; -} - - -/* - * Parse a redirection operator. The variable "out" points to a string - * specifying the fd to be redirected. The variable "c" contains the - * first character of the redirection operator. - */ - -parseredir: { - char fd[64]; - union node *np; - strlcpy(fd, out, sizeof(fd)); - - np = (union node *)stalloc(sizeof (struct nfile)); - if (c == '>') { - np->nfile.fd = 1; - c = pgetc(); - if (c == '>') - np->type = NAPPEND; - else if (c == '|') - np->type = NCLOBBER; - else if (c == '&') - np->type = NTOFD; - else { - np->type = NTO; - pungetc(); - } - } else { /* c == '<' */ - np->nfile.fd = 0; - switch (c = pgetc()) { - case '<': - if (sizeof (struct nfile) != sizeof (struct nhere)) { - np = (union node *)stalloc(sizeof (struct nhere)); - np->nfile.fd = 0; - } - np->type = NHERE; - heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc)); - heredoc->here = np; - if ((c = pgetc()) == '-') { - heredoc->striptabs = 1; - } else { - heredoc->striptabs = 0; - pungetc(); - } - break; - - case '&': - np->type = NFROMFD; - break; - - case '>': - np->type = NFROMTO; - break; - - default: - np->type = NFROM; - pungetc(); - break; - } - } - if (*fd != '\0') - np->nfile.fd = number(fd); - redirnode = np; - goto parseredir_return; -} - - -/* - * Parse a substitution. At this point, we have read the dollar sign - * and nothing else. - */ - -parsesub: { - char buf[10]; - int subtype; - int typeloc; - int flags; - char *p; - static const char types[] = "}-+?="; - int i; - int linno; - - c = pgetc(); - if (c != '(' && c != OPENBRACE && !is_name(c) && !is_special(c)) { - USTPUTC('$', out); - pungetc(); - } else if (c == '(') { /* $(command) or $((arith)) */ - if (pgetc() == '(') { - PARSEARITH(); - } else { - pungetc(); - PARSEBACKQNEW(); - } - } else { - USTPUTC(CTLVAR, out); - typeloc = out - stackblock(); - USTPUTC(VSNORMAL, out); - subtype = VSNORMAL; - flags = 0; - if (c == OPENBRACE) { - c = pgetc(); - if (c == '#') { - if ((c = pgetc()) == CLOSEBRACE) - c = '#'; - else - subtype = VSLENGTH; - } - else - subtype = 0; - } - if (is_name(c)) { - p = out; - do { - STPUTC(c, out); - c = pgetc(); - } while (is_in_name(c)); - if (out - p == 6 && strncmp(p, "LINENO", 6) == 0) { - /* Replace the variable name with the - * current line number. */ - linno = plinno; - if (funclinno != 0) - linno -= funclinno - 1; - snprintf(buf, sizeof(buf), "%d", linno); - STADJUST(-6, out); - for (i = 0; buf[i] != '\0'; i++) - STPUTC(buf[i], out); - flags |= VSLINENO; - } - } else if (is_digit(c)) { - do { - USTPUTC(c, out); - c = pgetc(); - } while (is_digit(c)); - } - else if (is_special(c)) { - USTPUTC(c, out); - c = pgetc(); - } - else -badsub: synerror("Bad substitution"); - - STPUTC('=', out); - if (subtype == 0) { - switch (c) { - case ':': - flags |= VSNUL; - c = pgetc(); - /*FALLTHROUGH*/ - default: - p = strchr(types, c); - if (p == NULL) - goto badsub; - subtype = p - types + VSNORMAL; - break; - case '%': - case '#': - { - int cc = c; - subtype = c == '#' ? VSTRIMLEFT : - VSTRIMRIGHT; - c = pgetc(); - if (c == cc) - subtype++; - else - pungetc(); - break; - } - } - } else { - pungetc(); - } - if (ISDBLQUOTE() || arinest) - flags |= VSQUOTE; - *(stackblock() + typeloc) = subtype | flags; - if (subtype != VSNORMAL) { - varnest++; - if (varnest >= maxnest) { - dblquotep = ckrealloc(dblquotep, maxnest / 8); - dblquotep[(maxnest / 32) - 1] = 0; - maxnest += 32; - } - } - } - goto parsesub_return; -} - - -/* - * Called to parse command substitutions. Newstyle is set if the command - * is enclosed inside $(...); nlpp is a pointer to the head of the linked - * list of commands (passed by reference), and savelen is the number of - * characters on the top of the stack which must be preserved. - */ - -parsebackq: { - struct nodelist **nlpp; - int savepbq; - union node *n; - char *volatile str = NULL; - struct jmploc jmploc; - struct jmploc *volatile savehandler = NULL; - int savelen; - int saveprompt; - - savepbq = parsebackquote; - if (setjmp(jmploc.loc)) { - if (str) - ckfree(str); - parsebackquote = 0; - handler = savehandler; - longjmp(handler->loc, 1); - } - INTOFF; - str = NULL; - savelen = out - stackblock(); - if (savelen > 0) { - str = ckmalloc(savelen); - memcpy(str, stackblock(), savelen); - } - savehandler = handler; - handler = &jmploc; - INTON; - if (oldstyle) { - /* We must read until the closing backquote, giving special - treatment to some slashes, and then push the string and - reread it as input, interpreting it normally. */ - char *pout; - int pc; - int psavelen; - char *pstr; - - - STARTSTACKSTR(pout); - for (;;) { - if (needprompt) { - setprompt(2); - needprompt = 0; - } - switch (pc = pgetc()) { - case '`': - goto done; - - case '\\': - if ((pc = pgetc()) == '\n') { - plinno++; - if (doprompt) - setprompt(2); - else - setprompt(0); - /* - * If eating a newline, avoid putting - * the newline into the new character - * stream (via the STPUTC after the - * switch). - */ - continue; - } - if (pc != '\\' && pc != '`' && pc != '$' - && (!ISDBLQUOTE() || pc != '"')) - STPUTC('\\', pout); - break; - - case '\n': - plinno++; - needprompt = doprompt; - break; - - case PEOF: - startlinno = plinno; - synerror("EOF in backquote substitution"); - break; - - default: - break; - } - STPUTC(pc, pout); - } -done: - STPUTC('\0', pout); - psavelen = pout - stackblock(); - if (psavelen > 0) { - pstr = grabstackstr(pout); - setinputstring(pstr, 1); - } - } - nlpp = &bqlist; - while (*nlpp) - nlpp = &(*nlpp)->next; - *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist)); - (*nlpp)->next = NULL; - parsebackquote = oldstyle; - - if (oldstyle) { - saveprompt = doprompt; - doprompt = 0; - } else - saveprompt = 0; - - n = list(0, oldstyle); - - if (oldstyle) - doprompt = saveprompt; - else { - if (readtoken() != TRP) - synexpect(TRP); - } - - (*nlpp)->n = n; - if (oldstyle) { - /* - * Start reading from old file again, ignoring any pushed back - * tokens left from the backquote parsing - */ - popfile(); - tokpushback = 0; - } - while (stackblocksize() <= savelen) - growstackblock(); - STARTSTACKSTR(out); - if (str) { - memcpy(out, str, savelen); - STADJUST(savelen, out); - INTOFF; - ckfree(str); - str = NULL; - INTON; - } - parsebackquote = savepbq; - handler = savehandler; - if (arinest || ISDBLQUOTE()) - USTPUTC(CTLBACKQ | CTLQUOTE, out); - else - USTPUTC(CTLBACKQ, out); - if (oldstyle) - goto parsebackq_oldreturn; - else - goto parsebackq_newreturn; -} - -/* - * Parse an arithmetic expansion (indicate start of one and set state) - */ -parsearith: { - - if (++arinest == 1) { - prevsyntax = syntax; - syntax = ARISYNTAX; - USTPUTC(CTLARI, out); - if (ISDBLQUOTE()) - USTPUTC('"',out); - else - USTPUTC(' ',out); - } else { - /* - * we collapse embedded arithmetic expansion to - * parenthesis, which should be equivalent - */ - USTPUTC('(', out); - } - goto parsearith_return; -} - -} /* end of readtoken */ - - - -#ifdef mkinit -RESET { - tokpushback = 0; - checkkwd = 0; -} -#endif - -/* - * Returns true if the text contains nothing to expand (no dollar signs - * or backquotes). - */ - -STATIC int -noexpand(char *text) -{ - char *p; - char c; - - p = text; - while ((c = *p++) != '\0') { - if (c == CTLQUOTEMARK) - continue; - if (c == CTLESC) - p++; - else if (BASESYNTAX[(int)c] == CCTL) - return 0; - } - return 1; -} - - -/* - * Return true if the argument is a legal variable name (a letter or - * underscore followed by zero or more letters, underscores, and digits). - */ - -int -goodname(char *name) - { - char *p; - - p = name; - if (! is_name(*p)) - return 0; - while (*++p) { - if (! is_in_name(*p)) - return 0; - } - return 1; -} - - -/* - * Called when an unexpected token is read during the parse. The argument - * is the token that is expected, or -1 if more than one type of token can - * occur at this point. - */ - -STATIC void -synexpect(int token) -{ - char msg[64]; - - if (token >= 0) { - fmtstr(msg, 64, "%s unexpected (expecting %s)", - tokname[lasttoken], tokname[token]); - } else { - fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]); - } - synerror(msg); - /* NOTREACHED */ -} - - -STATIC void -synerror(const char *msg) -{ - if (commandname) - outfmt(&errout, "%s: %d: ", commandname, startlinno); - else - outfmt(&errout, "%s: ", getprogname()); - outfmt(&errout, "Syntax error: %s\n", msg); - error(NULL); - /* NOTREACHED */ -} - -STATIC void -setprompt(int which) -{ - whichprompt = which; - -#ifndef SMALL - if (!el) -#endif - out2str(getprompt(NULL)); -} - -/* - * called by editline -- any expansions to the prompt - * should be added here. - */ -const char * -getprompt(void *unused) - { - switch (whichprompt) { - case 0: - return ""; - case 1: - return ps1val(); - case 2: - return ps2val(); - default: - return ""; - } -} diff --git a/bin/sh/parser.h b/bin/sh/parser.h deleted file mode 100644 index cc4910f84..000000000 --- a/bin/sh/parser.h +++ /dev/null @@ -1,84 +0,0 @@ -/* $NetBSD: parser.h,v 1.18 2013/10/02 19:52:58 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)parser.h 8.3 (Berkeley) 5/4/95 - */ - -/* control characters in argument strings */ -#define CTL_FIRST '\201' /* first 'special' character */ -#define CTLESC '\201' /* escape next character */ -#define CTLVAR '\202' /* variable defn */ -#define CTLENDVAR '\203' -#define CTLBACKQ '\204' -#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */ -/* CTLBACKQ | CTLQUOTE == '\205' */ -#define CTLARI '\206' /* arithmetic expression */ -#define CTLENDARI '\207' -#define CTLQUOTEMARK '\210' -#define CTLQUOTEEND '\211' /* only inside ${...} */ -#define CTL_LAST '\211' /* last 'special' character */ - -/* variable substitution byte (follows CTLVAR) */ -#define VSTYPE 0x0f /* type of variable substitution */ -#define VSNUL 0x10 /* colon--treat the empty string as unset */ -#define VSLINENO 0x20 /* expansion of $LINENO, the line number - follows immediately */ -#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */ - -/* values of VSTYPE field */ -#define VSNORMAL 0x1 /* normal variable: $var or ${var} */ -#define VSMINUS 0x2 /* ${var-text} */ -#define VSPLUS 0x3 /* ${var+text} */ -#define VSQUESTION 0x4 /* ${var?message} */ -#define VSASSIGN 0x5 /* ${var=text} */ -#define VSTRIMLEFT 0x6 /* ${var#pattern} */ -#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */ -#define VSTRIMRIGHT 0x8 /* ${var%pattern} */ -#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */ -#define VSLENGTH 0xa /* ${#var} */ - - -/* - * NEOF is returned by parsecmd when it encounters an end of file. It - * must be distinct from NULL, so we use the address of a variable that - * happens to be handy. - */ -extern int tokpushback; -#define NEOF ((union node *)&tokpushback) -extern int whichprompt; /* 1 == PS1, 2 == PS2 */ - - -union node *parsecmd(int); -void fixredir(union node *, const char *, int); -int goodname(char *); -const char *getprompt(void *); diff --git a/bin/sh/redir.c b/bin/sh/redir.c deleted file mode 100644 index 62fe6d609..000000000 --- a/bin/sh/redir.c +++ /dev/null @@ -1,400 +0,0 @@ -/* $NetBSD: redir.c,v 1.37 2014/10/23 21:03:25 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: redir.c,v 1.37 2014/10/23 21:03:25 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include /* PIPE_BUF */ -#include -#include -#include -#include -#include -#include - -/* - * Code for dealing with input/output redirection. - */ - -#include "main.h" -#include "shell.h" -#include "nodes.h" -#include "jobs.h" -#include "options.h" -#include "expand.h" -#include "redir.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" - - -#define EMPTY -2 /* marks an unused slot in redirtab */ -#define CLOSED -1 /* fd was not open before redir */ -#ifndef PIPE_BUF -# define PIPESIZE 4096 /* amount of buffering in a pipe */ -#else -# define PIPESIZE PIPE_BUF -#endif - - -MKINIT -struct redirtab { - struct redirtab *next; - short renamed[10]; -}; - - -MKINIT struct redirtab *redirlist; - -/* - * We keep track of whether or not fd0 has been redirected. This is for - * background commands, where we want to redirect fd0 to /dev/null only - * if it hasn't already been redirected. -*/ -int fd0_redirected = 0; - -STATIC void openredirect(union node *, char[10], int); -STATIC int openhere(const union node *); - - -/* - * Process a list of redirection commands. If the REDIR_PUSH flag is set, - * old file descriptors are stashed away so that the redirection can be - * undone by calling popredir. If the REDIR_BACKQ flag is set, then the - * standard output, and the standard error if it becomes a duplicate of - * stdout, is saved in memory. - */ - -void -redirect(union node *redir, int flags) -{ - union node *n; - struct redirtab *sv = NULL; - int i; - int fd; - char memory[10]; /* file descriptors to write to memory */ - - for (i = 10 ; --i >= 0 ; ) - memory[i] = 0; - memory[1] = flags & REDIR_BACKQ; - if (flags & REDIR_PUSH) { - /* We don't have to worry about REDIR_VFORK here, as - * flags & REDIR_PUSH is never true if REDIR_VFORK is set. - */ - sv = ckmalloc(sizeof (struct redirtab)); - for (i = 0 ; i < 10 ; i++) - sv->renamed[i] = EMPTY; - sv->next = redirlist; - redirlist = sv; - } - for (n = redir ; n ; n = n->nfile.next) { - fd = n->nfile.fd; - if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) && - n->ndup.dupfd == fd) - continue; /* redirect from/to same file descriptor */ - - if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) { - INTOFF; - if ((i = fcntl(fd, F_DUPFD, 10)) == -1) { - switch (errno) { - case EBADF: - i = CLOSED; - break; - default: - INTON; - error("%d: %s", fd, strerror(errno)); - /* NOTREACHED */ - } - } else - (void)fcntl(i, F_SETFD, FD_CLOEXEC); - sv->renamed[fd] = i; - INTON; - } else { - close(fd); - } - if (fd == 0) - fd0_redirected++; - openredirect(n, memory, flags); - } - if (memory[1]) - out1 = &memout; - if (memory[2]) - out2 = &memout; -} - - -STATIC void -openredirect(union node *redir, char memory[10], int flags) -{ - struct stat sb; - int fd = redir->nfile.fd; - char *fname; - int f; - int eflags; - - /* - * We suppress interrupts so that we won't leave open file - * descriptors around. This may not be such a good idea because - * an open of a device or a fifo can block indefinitely. - */ - INTOFF; - memory[fd] = 0; - switch (redir->nfile.type) { - case NFROM: - fname = redir->nfile.expfname; - if (flags & REDIR_VFORK) - eflags = O_NONBLOCK; - else - eflags = 0; - if ((f = open(fname, O_RDONLY|eflags)) < 0) - goto eopen; - if (eflags) - (void)fcntl(f, F_SETFL, fcntl(f, F_GETFL, 0) & ~eflags); - break; - case NFROMTO: - fname = redir->nfile.expfname; - if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0) - goto ecreate; - break; - case NTO: - if (Cflag) { - fname = redir->nfile.expfname; - if ((f = open(fname, O_WRONLY)) == -1) { - if ((f = open(fname, O_WRONLY|O_CREAT|O_EXCL, - 0666)) < 0) - goto ecreate; - } else if (fstat(f, &sb) == -1) { - int serrno = errno; - close(f); - errno = serrno; - goto ecreate; - } else if (S_ISREG(sb.st_mode)) { - close(f); - errno = EEXIST; - goto ecreate; - } - break; - } - /* FALLTHROUGH */ - case NCLOBBER: - fname = redir->nfile.expfname; - if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) - goto ecreate; - break; - case NAPPEND: - fname = redir->nfile.expfname; - if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0) - goto ecreate; - break; - case NTOFD: - case NFROMFD: - if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ - if (memory[redir->ndup.dupfd]) - memory[fd] = 1; - else - copyfd(redir->ndup.dupfd, fd, 1); - } - INTON; - return; - case NHERE: - case NXHERE: - f = openhere(redir); - break; - default: - abort(); - } - - if (f != fd) { - copyfd(f, fd, 1); - close(f); - } - INTON; - return; -ecreate: - exerrno = 1; - error("cannot create %s: %s", fname, errmsg(errno, E_CREAT)); -eopen: - exerrno = 1; - error("cannot open %s: %s", fname, errmsg(errno, E_OPEN)); -} - - -/* - * Handle here documents. Normally we fork off a process to write the - * data to a pipe. If the document is short, we can stuff the data in - * the pipe without forking. - */ - -STATIC int -openhere(const union node *redir) -{ - int pip[2]; - int len = 0; - - if (pipe(pip) < 0) - error("Pipe call failed"); - if (redir->type == NHERE) { - len = strlen(redir->nhere.doc->narg.text); - if (len <= PIPESIZE) { - xwrite(pip[1], redir->nhere.doc->narg.text, len); - goto out; - } - } - if (forkshell(NULL, NULL, FORK_NOJOB) == 0) { - close(pip[0]); - signal(SIGINT, SIG_IGN); - signal(SIGQUIT, SIG_IGN); - signal(SIGHUP, SIG_IGN); -#ifdef SIGTSTP - signal(SIGTSTP, SIG_IGN); -#endif - signal(SIGPIPE, SIG_DFL); - if (redir->type == NHERE) - xwrite(pip[1], redir->nhere.doc->narg.text, len); - else - expandhere(redir->nhere.doc, pip[1]); - _exit(0); - } -out: - close(pip[1]); - return pip[0]; -} - - - -/* - * Undo the effects of the last redirection. - */ - -void -popredir(void) -{ - struct redirtab *rp = redirlist; - int i; - - for (i = 0 ; i < 10 ; i++) { - if (rp->renamed[i] != EMPTY) { - if (i == 0) - fd0_redirected--; - close(i); - if (rp->renamed[i] >= 0) { - copyfd(rp->renamed[i], i, 1); - close(rp->renamed[i]); - } - } - } - INTOFF; - redirlist = rp->next; - ckfree(rp); - INTON; -} - -/* - * Undo all redirections. Called on error or interrupt. - */ - -#ifdef mkinit - -INCLUDE "redir.h" - -RESET { - while (redirlist) - popredir(); -} - -SHELLPROC { - clearredir(0); -} - -#endif - -/* Return true if fd 0 has already been redirected at least once. */ -int -fd0_redirected_p (void) { - return fd0_redirected != 0; -} - -/* - * Discard all saved file descriptors. - */ - -void -clearredir(int vforked) -{ - struct redirtab *rp; - int i; - - for (rp = redirlist ; rp ; rp = rp->next) { - for (i = 0 ; i < 10 ; i++) { - if (rp->renamed[i] >= 0) { - close(rp->renamed[i]); - } - if (!vforked) - rp->renamed[i] = EMPTY; - } - } -} - - - -/* - * Copy a file descriptor to be >= to. Returns -1 - * if the source file descriptor is closed, EMPTY if there are no unused - * file descriptors left. - */ - -int -copyfd(int from, int to, int equal) -{ - int newfd; - - if (equal) - newfd = dup2(from, to); - else - newfd = fcntl(from, F_DUPFD, to); - if (newfd < 0) { - if (errno == EMFILE) - return EMPTY; - else - error("%d: %s", from, strerror(errno)); - } - return newfd; -} diff --git a/bin/sh/redir.h b/bin/sh/redir.h deleted file mode 100644 index 923619fbd..000000000 --- a/bin/sh/redir.h +++ /dev/null @@ -1,48 +0,0 @@ -/* $NetBSD: redir.h,v 1.16 2011/02/17 15:13:49 pooka Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)redir.h 8.2 (Berkeley) 5/4/95 - */ - -/* flags passed to redirect */ -#define REDIR_PUSH 01 /* save previous values of file descriptors */ -#define REDIR_BACKQ 02 /* save the command output in memory */ -#define REDIR_VFORK 04 /* running under vfork(2), be careful */ - -union node; -void redirect(union node *, int); -void popredir(void); -int fd0_redirected_p(void); -void clearredir(int); -int copyfd(int, int, int); - diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 deleted file mode 100644 index 8980be65f..000000000 --- a/bin/sh/sh.1 +++ /dev/null @@ -1,2047 +0,0 @@ -.\" $NetBSD: sh.1,v 1.115 2015/05/26 21:35:15 christos Exp $ -.\" Copyright (c) 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" Kenneth Almquist. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)sh.1 8.6 (Berkeley) 5/4/95 -.\" -.Dd May 26, 2015 -.Dt SH 1 -.Os -.Sh NAME -.Nm sh -.Nd command interpreter (shell) -.Sh SYNOPSIS -.Nm -.Bk -words -.Op Fl aCefnuvxIimqVEb -.Op Cm +aCefnuvxIimqVEb -.Ek -.Bk -words -.Op Fl o Ar option_name -.Op Cm +o Ar option_name -.Ek -.Bk -words -.Op Ar command_file Oo Ar argument ... Oc -.Ek -.Nm -.Fl c -.Bk -words -.Op Fl abCEefnuvxIimpqV -.Op Cm +abCEefnuvxIimpqV -.Ek -.Bk -words -.Op Fl o Ar option_name -.Op Cm +o Ar option_name -.Ek -.Bk -words -.Ar command_string -.Op Ar command_name Oo Ar argument ... Oc -.Ek -.Nm -.Fl s -.Bk -words -.Op Fl abCEefnuvxIimpqV -.Op Cm +abCEefnuvxIimpqV -.Ek -.Bk -words -.Op Fl o Ar option_name -.Op Cm +o Ar option_name -.Ek -.Bk -words -.Op Ar argument ... -.Ek -.Sh DESCRIPTION -.Nm -is the standard command interpreter for the system. -The current version of -.Nm -is in the process of being changed to conform with the -.Tn POSIX -1003.2 and 1003.2a specifications for the shell. -This version has many -features which make it appear similar in some respects to the Korn shell, -but it is not a Korn shell clone (see -.Xr ksh 1 ) . -Only features designated by -.Tn POSIX , -plus a few Berkeley extensions, are being incorporated into this shell. -.\" We expect -.\" .Tn POSIX -.\" conformance by the time 4.4 BSD is released. -This man page is not intended -to be a tutorial or a complete specification of the shell. -.Ss Overview -The shell is a command that reads lines from either a file or the -terminal, interprets them, and generally executes other commands. -It is the program that is running when a user logs into the system -(although a user can select a different shell with the -.Xr chsh 1 -command). -The shell implements a language that has flow control -constructs, a macro facility that provides a variety of features in -addition to data storage, along with built in history and line editing -capabilities. -It incorporates many features to aid interactive use and -has the advantage that the interpretative language is common to both -interactive and non-interactive use (shell scripts). -That is, commands -can be typed directly to the running shell or can be put into a file and -the file can be executed directly by the shell. -.Ss Invocation -If no arguments are present and if the standard input of the shell -is connected to a terminal (or if the -.Fl i -flag is set), -and the -.Fl c -option is not present, the shell is considered an interactive shell. -An interactive shell generally prompts before each command and handles -programming and command errors differently (as described below). -When first starting, -the shell inspects argument 0, and if it begins with a dash -.Sq - , -the shell is also considered -a login shell. -This is normally done automatically by the system -when the user first logs in. -A login shell first reads commands -from the files -.Pa /etc/profile -and -.Pa .profile -if they exist. -If the environment variable -.Ev ENV -is set on entry to a shell, or is set in the -.Pa .profile -of a login shell, the shell next reads -commands from the file named in -.Ev ENV . -Therefore, a user should place commands that are to be executed only at -login time in the -.Pa .profile -file, and commands that are executed for every shell inside the -.Ev ENV -file. -To set the -.Ev ENV -variable to some file, place the following line in your -.Pa .profile -of your home directory -.Pp -.Dl ENV=$HOME/.shinit; export ENV -.Pp -substituting for -.Dq .shinit -any filename you wish. -Since the -.Ev ENV -file is read for every invocation of the shell, including shell scripts -and non-interactive shells, the following paradigm is useful for -restricting commands in the -.Ev ENV -file to interactive invocations. -Place commands within the -.Dq case -and -.Dq esac -below (these commands are described later): -.Pp -.Bl -item -compact -offset indent -.It -.Li case $- in *i*) -.Bl -item -compact -offset indent -.It -.Li # commands for interactive use only -.It -.Li ... -.El -.It -.Li esac -.El -.Pp -If command line arguments besides the options have been specified, then -the shell treats the first argument as the name of a file from which to -read commands (a shell script), and the remaining arguments are set as the -positional parameters of the shell ($1, $2, etc). -Otherwise, the shell -reads commands from its standard input. -.Ss Argument List Processing -All of the single letter options have a corresponding name that can be -used as an argument to the -.Fl o -option. -The set -.Fl o -name is provided next to the single letter option in -the description below. -Specifying a dash -.Dq - -turns the option on, while using a plus -.Dq + -disables the option. -The following options can be set from the command line or -with the -.Ic set -built-in (described later). -.Bl -tag -width aaaallexportfoo -offset indent -.It Fl a Em allexport -Export all variables assigned to. -.It Fl c -Read commands from the -.Ar command_string -operand instead of from the standard input. -Special parameter 0 will be set from the -.Ar command_name -operand and the positional parameters ($1, $2, etc.) -set from the remaining argument operands. -.It Fl C Em noclobber -Don't overwrite existing files with -.Dq \*[Gt] . -.It Fl e Em errexit -If not interactive, exit immediately if any untested command fails. -The exit status of a command is considered to be -explicitly tested if the command is used to control an -.Ic if , -.Ic elif , -.Ic while , -or -.Ic until , -or if the command is the left hand operand of an -.Dq \*[Am]\*[Am] -or -.Dq || -operator. -.It Fl f Em noglob -Disable pathname expansion. -.It Fl n Em noexec -If not interactive, read commands but do not execute them. -This is useful for checking the syntax of shell scripts. -.It Fl u Em nounset -Write a message to standard error when attempting to expand a variable -that is not set, and if the shell is not interactive, exit immediately. -.It Fl v Em verbose -The shell writes its input to standard error as it is read. -Useful for debugging. -.It Fl x Em xtrace -Write each command to standard error (preceded by a -.Sq +\ ) -before it is executed. -Useful for debugging. -.It Fl q Em quietprofile -If the -.Fl v -or -.Fl x -options have been set, do not apply them when reading -initialization files, these being -.Pa /etc/profile , -.Pa .profile , -and the file specified by the -.Ev ENV -environment variable. -.It Fl I Em ignoreeof -Ignore EOFs from input when interactive. -.It Fl i Em interactive -Force the shell to behave interactively. -.It Fl m Em monitor -Turn on job control (set automatically when interactive). -.It Fl s Em stdin -Read commands from standard input (set automatically if no file arguments -are present). -This option has no effect when set after the shell has -already started running (i.e. with -.Ic set ) . -.It Fl V Em vi -Enable the built-in -.Xr vi 1 -command line editor (disables -.Fl E -if it has been set). -(See the -.Sx Command Line Editing -section below.) -.It Fl E Em emacs -Enable the built-in emacs style -command line editor (disables -.Fl V -if it has been set). -(See the -.Sx Command Line Editing -section below.) -.It Fl b Em notify -Enable asynchronous notification of background job completion. -(Not implemented.) -.It Fl p Em nopriv -Do not attempt to reset effective uid if it does not match uid. -This is not set by default to help avoid incorrect usage by setuid -root programs via -.Xr system 3 -or -.Xr popen 3 . -.It "\ \ " Em cdprint -Make an interactive shell always print the new directory name when -changed by the -.Ic cd -command. -.It "\ \ " Em tabcomplete -Enables filename completion in the command line editor. -Typing a tab character will extend the current input word to match a -filename. -If more than one filename matches it is only extended to be the common prefix. -Typing a second tab character will list all the matching names. -One of the editing modes, either -.Fl E -or -.Fl V , -must be enabled for this to work. -.El -.Ss Lexical Structure -The shell reads input in terms of lines from a file and breaks it up into -words at whitespace (blanks and tabs), and at certain sequences of -characters that are special to the shell called -.Dq operators . -There are two types of operators: control operators and redirection -operators (their meaning is discussed later). -Following is a list of operators: -.Bl -ohang -offset indent -.It "Control operators:" -.Dl \*[Am] \*[Am]\*[Am] \&( \&) \&; ;; | || \*[Lt]newline\*[Gt] -.It "Redirection operators:" -.Dl \*[Lt] \*[Gt] \*[Gt]| \*[Lt]\*[Lt] \*[Gt]\*[Gt] \*[Lt]\*[Am] \*[Gt]\*[Am] \*[Lt]\*[Lt]- \*[Lt]\*[Gt] -.El -.Ss Quoting -Quoting is used to remove the special meaning of certain characters or -words to the shell, such as operators, whitespace, or keywords. -There are three types of quoting: matched single quotes, -matched double quotes, and backslash. -.Ss Backslash -A backslash preserves the literal meaning of the following -character, with the exception of -.Aq newline . -A backslash preceding a -.Aq newline -is treated as a line continuation. -.Ss Single Quotes -Enclosing characters in single quotes preserves the literal meaning of all -the characters (except single quotes, making it impossible to put -single quotes in a single-quoted string). -.Ss Double Quotes -Enclosing characters within double quotes preserves the literal -meaning of all characters except dollar sign -.Pq $ , -backquote -.Pq ` , -and backslash -.Pq \e . -The backslash inside double quotes is historically weird, and serves to -quote only the following characters: -.Dl $ ` \*q \e \*[Lt]newline\*[Gt] . -Otherwise it remains literal. -.Ss Reserved Words -Reserved words are words that have special meaning to the -shell and are recognized at the beginning of a line and -after a control operator. -The following are reserved words: -.Bl -column while while while while while -offset indent -.It ! Ta elif Ta fi Ta while Ta case -.It else Ta for Ta then Ta { Ta } -.It do Ta done Ta until Ta if Ta esac -.El -.Pp -Their meaning is discussed later. -.Ss Aliases -An alias is a name and corresponding value set using the -.Ic alias -built-in command. -Whenever a reserved word may occur (see above), -and after checking for reserved words, the shell -checks the word to see if it matches an alias. -If it does, it replaces it in the input stream with its value. -For example, if there is an alias called -.Dq lf -with the value -.Dq "ls -F" , -then the input: -.Pp -.Dl lf foobar Aq return -.Pp -would become -.Pp -.Dl ls -F foobar Aq return -.Pp -Aliases provide a convenient way for naive users to create shorthands for -commands without having to learn how to create functions with arguments. -They can also be used to create lexically obscure code. -This use is discouraged. -.Ss Commands -The shell interprets the words it reads according to a language, the -specification of which is outside the scope of this man page (refer to the -BNF in the -.Tn POSIX -1003.2 document). -Essentially though, a line is read and if the first -word of the line (or after a control operator) is not a reserved word, -then the shell has recognized a simple command. -Otherwise, a complex -command or some other special construct may have been recognized. -.Ss Simple Commands -If a simple command has been recognized, the shell performs -the following actions: -.Bl -enum -offset indent -.It -Leading words of the form -.Dq name=value -are stripped off and assigned to the environment of the simple command. -Redirection operators and their arguments (as described below) are -stripped off and saved for processing. -.It -The remaining words are expanded as described in the -.Sx Word Expansions -section below, -and the first remaining word is considered the command name and the -command is located. -The remaining words are considered the arguments of the command. -If no command name resulted, then the -.Dq name=value -variable assignments recognized in item 1 affect the current shell. -.It -Redirections are performed as described in the next section. -.El -.Ss Redirections -Redirections are used to change where a command reads its input or sends -its output. -In general, redirections open, close, or duplicate an -existing reference to a file. -The overall format used for redirection is: -.Pp -.Dl [n] Va redir-op Ar file -.Pp -where -.Va redir-op -is one of the redirection operators mentioned previously. -Following is a list of the possible redirections. -The -.Bq n -is an optional number, as in -.Sq 3 -(not -.Sq Bq 3 ) , -that refers to a file descriptor. -.Bl -tag -width aaabsfiles -offset indent -.It [n] Ns \*[Gt] file -Redirect standard output (or n) to file. -.It [n] Ns \*[Gt]| file -Same, but override the -.Fl C -option. -.It [n] Ns \*[Gt]\*[Gt] file -Append standard output (or n) to file. -.It [n] Ns \*[Lt] file -Redirect standard input (or n) from file. -.It [n1] Ns \*[Lt]\*[Am] Ns n2 -Duplicate standard input (or n1) from file descriptor n2. -.It [n] Ns \*[Lt]\*[Am]- -Close standard input (or n). -.It [n1] Ns \*[Gt]\*[Am] Ns n2 -Duplicate standard output (or n1) to n2. -.It [n] Ns \*[Gt]\*[Am]- -Close standard output (or n). -.It [n] Ns \*[Lt]\*[Gt] file -Open file for reading and writing on standard input (or n). -.El -.Pp -The following redirection is often called a -.Dq here-document . -.Bl -item -offset indent -.It -.Li [n]\*[Lt]\*[Lt] delimiter -.Dl here-doc-text ... -.Li delimiter -.El -.Pp -All the text on successive lines up to the delimiter, or to an EOF, is -saved away and made available to the command on standard input, or file -descriptor n if it is specified. -If the delimiter as specified on the initial line is -quoted, then the here-doc-text is treated literally; otherwise, the text is -subjected to parameter expansion, command substitution, and arithmetic -expansion as described in the -.Sx Word Expansions -section below. -If the operator is -.Dq \*[Lt]\*[Lt]- -instead of -.Dq \*[Lt]\*[Lt] , -then leading tabs in the here-doc-text are stripped. -.Ss Search and Execution -There are three types of commands: shell functions, built-in commands, and -normal programs -- and the command is searched for (by name) in that order. -They each are executed in a different way. -.Pp -When a shell function is executed, all of the shell positional parameters -(except $0, which remains unchanged) are set to the arguments of the shell -function. -The variables which are explicitly placed in the environment of -the command (by placing assignments to them before the function name) are -made local to the function and are set to the values given. -Then the command given in the function definition is executed. -The positional parameters are restored to their original values -when the command completes. -This all occurs within the current shell. -.Pp -Shell built-ins are executed internally to the shell, without spawning a -new process. -.Pp -Otherwise, if the command name doesn't match a function or built-in, the -command is searched for as a normal program in the file system (as -described in the next section). -When a normal program is executed, the shell runs the program, -passing the arguments and the environment to the program. -If the program is not a normal executable file (i.e., if it does -not begin with the "magic number" whose -.Tn ASCII -representation is "#!", so -.Xr execve 2 -returns -.Er ENOEXEC -then) the shell will interpret the program in a subshell. -The child shell will reinitialize itself in this case, -so that the effect will be as if a -new shell had been invoked to handle the ad-hoc shell script, except that -the location of hashed commands located in the parent shell will be -remembered by the child. -.Pp -Note that previous versions of this document and the source code itself -misleadingly and sporadically refer to a shell script without a magic -number as a "shell procedure". -.Ss Path Search -When locating a command, the shell first looks to see if it has a shell -function by that name. -Then it looks for a built-in command by that name. -If a built-in command is not found, one of two things happen: -.Bl -enum -.It -Command names containing a slash are simply executed without performing -any searches. -.It -The shell searches each entry in -.Ev PATH -in turn for the command. -The value of the -.Ev PATH -variable should be a series of entries separated by colons. -Each entry consists of a directory name. -The current directory may be indicated -implicitly by an empty directory name, or explicitly by a single period. -.El -.Ss Command Exit Status -Each command has an exit status that can influence the behavior -of other shell commands. -The paradigm is that a command exits -with zero for normal or success, and non-zero for failure, -error, or a false indication. -The man page for each command -should indicate the various exit codes and what they mean. -Additionally, the built-in commands return exit codes, as does -an executed shell function. -.Pp -If a command consists entirely of variable assignments then the -exit status of the command is that of the last command substitution -if any, otherwise 0. -.Ss Complex Commands -Complex commands are combinations of simple commands with control -operators or reserved words, together creating a larger complex command. -More generally, a command is one of the following: -.Bl -bullet -.It -simple command -.It -pipeline -.It -list or compound-list -.It -compound command -.It -function definition -.El -.Pp -Unless otherwise stated, the exit status of a command is that of the last -simple command executed by the command. -.Ss Pipelines -A pipeline is a sequence of one or more commands separated -by the control operator |. -The standard output of all but -the last command is connected to the standard input -of the next command. -The standard output of the last -command is inherited from the shell, as usual. -.Pp -The format for a pipeline is: -.Pp -.Dl [!] command1 [ | command2 ...] -.Pp -The standard output of command1 is connected to the standard input of -command2. -The standard input, standard output, or both of a command is -considered to be assigned by the pipeline before any redirection specified -by redirection operators that are part of the command. -.Pp -If the pipeline is not in the background (discussed later), the shell -waits for all commands to complete. -.Pp -If the reserved word ! does not precede the pipeline, the exit status is -the exit status of the last command specified in the pipeline. -Otherwise, the exit status is the logical NOT of the exit status of the -last command. -That is, if the last command returns zero, the exit status -is 1; if the last command returns greater than zero, the exit status is -zero. -.Pp -Because pipeline assignment of standard input or standard output or both -takes place before redirection, it can be modified by redirection. -For example: -.Pp -.Dl $ command1 2\*[Gt]\*[Am]1 | command2 -.Pp -sends both the standard output and standard error of command1 -to the standard input of command2. -.Pp -A ; or -.Aq newline -terminator causes the preceding AND-OR-list (described -next) to be executed sequentially; a \*[Am] causes asynchronous execution of -the preceding AND-OR-list. -.Pp -Note that unlike some other shells, each process in the pipeline is a -child of the invoking shell (unless it is a shell built-in, in which case -it executes in the current shell -- but any effect it has on the -environment is wiped). -.Ss Background Commands -- \*[Am] -If a command is terminated by the control operator ampersand (\*[Am]), the -shell executes the command asynchronously -- that is, the shell does not -wait for the command to finish before executing the next command. -.Pp -The format for running a command in background is: -.Pp -.Dl command1 \*[Am] [command2 \*[Am] ...] -.Pp -If the shell is not interactive, the standard input of an asynchronous -command is set to -.Pa /dev/null . -.Ss Lists -- Generally Speaking -A list is a sequence of zero or more commands separated by newlines, -semicolons, or ampersands, and optionally terminated by one of these three -characters. -The commands in a list are executed in the order they are written. -If command is followed by an ampersand, the shell starts the -command and immediately proceed onto the next command; otherwise it waits -for the command to terminate before proceeding to the next one. -.Ss Short-Circuit List Operators -.Dq \*[Am]\*[Am] -and -.Dq || -are AND-OR list operators. -.Dq \*[Am]\*[Am] -executes the first command, and then executes the second command if and only -if the exit status of the first command is zero. -.Dq || -is similar, but executes the second command if and only if the exit status -of the first command is nonzero. -.Dq \*[Am]\*[Am] -and -.Dq || -both have the same priority. -Note that these operators are left-associative, so -.Dq true || echo bar \*[Am]\*[Am] echo baz -writes -.Dq baz -and nothing else. -This is not the way it works in C. -Also, if you forget the left-hand side (for example when continuing lines but -forgetting to use a backslash) it defaults to a true statement. -This behavior is not useful and should not be relied upon. -.Ss Flow-Control Constructs -- if, while, for, case -The syntax of the if command is -.Bd -literal -offset indent -if list -then list -[ elif list -then list ] ... -[ else list ] -fi -.Ed -.Pp -The syntax of the while command is -.Bd -literal -offset indent -while list -do list -done -.Ed -.Pp -The two lists are executed repeatedly while the exit status of the -first list is zero. -The until command is similar, but has the word -until in place of while, which causes it to -repeat until the exit status of the first list is zero. -.Pp -The syntax of the for command is -.Bd -literal -offset indent -for variable in word ... -do list -done -.Ed -.Pp -The words are expanded, and then the list is executed repeatedly with the -variable set to each word in turn. -do and done may be replaced with -.Dq { -and -.Dq } . -.Pp -The syntax of the break and continue command is -.Bd -literal -offset indent -break [ num ] -continue [ num ] -.Ed -.Pp -Break terminates the num innermost for or while loops. -Continue continues with the next iteration of the innermost loop. -These are implemented as built-in commands. -.Pp -The syntax of the case command is -.Bd -literal -offset indent -case word in -pattern) list ;; -\&... -esac -.Ed -.Pp -The pattern can actually be one or more patterns (see -.Sx Shell Patterns -described later), separated by -.Dq \*(Ba -characters. -.Ss Grouping Commands Together -Commands may be grouped by writing either -.Pp -.Dl (list) -.Pp -or -.Pp -.Dl { list; } -.Pp -The first of these executes the commands in a subshell. -Built-in commands grouped into a (list) will not affect the current shell. -The second form does not fork another shell so is slightly more efficient. -Grouping commands together this way allows you to redirect -their output as though they were one program: -.Bd -literal -offset indent -{ echo -n \*q hello \*q ; echo \*q world" ; } \*[Gt] greeting -.Ed -.Pp -Note that -.Dq } -must follow a control operator (here, -.Dq \&; ) -so that it is recognized as a reserved word and not as another command argument. -.Ss Functions -The syntax of a function definition is -.Pp -.Dl name ( ) command -.Pp -A function definition is an executable statement; when executed it -installs a function named name and returns an exit status of zero. -The command is normally a list enclosed between -.Dq { -and -.Dq } . -.Pp -Variables may be declared to be local to a function by using a local -command. -This should appear as the first statement of a function, and the syntax is -.Pp -.Dl local [ variable | - ] ... -.Pp -.Dq Local -is implemented as a built-in command. -.Pp -When a variable is made local, it inherits the initial value and exported -and read-only flags from the variable with the same name in the surrounding -scope, if there is one. -Otherwise, the variable is initially unset. -The shell uses dynamic scoping, so that if you make the variable x local to -function f, which then calls function g, references to the variable x made -inside g will refer to the variable x declared inside f, not to the global -variable named x. -.Pp -The only special parameter that can be made local is -.Dq - . -Making -.Dq - -local causes any shell options that are changed via the set command inside the -function to be restored to their original values when the function -returns. -.Pp -The syntax of the return command is -.Pp -.Dl return [ exitstatus ] -.Pp -It terminates the currently executing function. -Return is implemented as a built-in command. -.Ss Variables and Parameters -The shell maintains a set of parameters. -A parameter denoted by a name is called a variable. -When starting up, the shell turns all the environment -variables into shell variables. -New variables can be set using the form -.Pp -.Dl name=value -.Pp -Variables set by the user must have a name consisting solely of -alphabetics, numerics, and underscores - the first of which must not be -numeric. -A parameter can also be denoted by a number or a special -character as explained below. -.Ss Positional Parameters -A positional parameter is a parameter denoted by a number (n \*[Gt] 0). -The shell sets these initially to the values of its command line arguments -that follow the name of the shell script. -The -.Ic set -built-in can also be used to set or reset them. -.Ss Special Parameters -A special parameter is a parameter denoted by one of the following special -characters. -The value of the parameter is listed next to its character. -.Bl -tag -width thinhyphena -.It * -Expands to the positional parameters, starting from one. -When the -expansion occurs within a double-quoted string it expands to a single -field with the value of each parameter separated by the first character of -the -.Ev IFS -variable, or by a -.Aq space -if -.Ev IFS -is unset. -.It @ -Expands to the positional parameters, starting from one. -When the expansion occurs within double quotes, each positional -parameter expands as a separate argument. -If there are no positional parameters, the -expansion of @ generates zero arguments, even when @ is -double-quoted. -What this basically means, for example, is -if $1 is -.Dq abc -and $2 is -.Dq def ghi , -then -.Qq $@ -expands to -the two arguments: -.Pp -.Sm off -.Dl \*q abc \*q \ \*q def\ ghi \*q -.Sm on -.It # -Expands to the number of positional parameters. -.It \&? -Expands to the exit status of the most recent pipeline. -.It - (Hyphen.) -Expands to the current option flags (the single-letter -option names concatenated into a string) as specified on -invocation, by the set built-in command, or implicitly -by the shell. -.It $ -Expands to the process ID of the invoked shell. -A subshell retains the same value of $ as its parent. -.It \&! -Expands to the process ID of the most recent background -command executed from the current shell. -For a pipeline, the process ID is that of the last command in the pipeline. -.It 0 (Zero.) -Expands to the name of the shell or shell script. -.El -.Ss Word Expansions -This section describes the various expansions that are performed on words. -Not all expansions are performed on every word, as explained later. -.Pp -Tilde expansions, parameter expansions, command substitutions, arithmetic -expansions, and quote removals that occur within a single word expand to a -single field. -It is only field splitting or pathname expansion that can -create multiple fields from a single word. -The single exception to this -rule is the expansion of the special parameter @ within double quotes, as -was described above. -.Pp -The order of word expansion is: -.Bl -enum -.It -Tilde Expansion, Parameter Expansion, Command Substitution, -Arithmetic Expansion (these all occur at the same time). -.It -Field Splitting is performed on fields -generated by step (1) unless the -.Ev IFS -variable is null. -.It -Pathname Expansion (unless set -.Fl f -is in effect). -.It -Quote Removal. -.El -.Pp -The $ character is used to introduce parameter expansion, command -substitution, or arithmetic evaluation. -.Ss Tilde Expansion (substituting a user's home directory) -A word beginning with an unquoted tilde character (~) is -subjected to tilde expansion. -All the characters up to -a slash (/) or the end of the word are treated as a username -and are replaced with the user's home directory. -If the username is missing (as in -.Pa ~/foobar ) , -the tilde is replaced with the value of the -.Va HOME -variable (the current user's home directory). -.Ss Parameter Expansion -The format for parameter expansion is as follows: -.Pp -.Dl ${expression} -.Pp -where expression consists of all characters until the matching -.Dq } . -Any -.Dq } -escaped by a backslash or within a quoted string, and characters in -embedded arithmetic expansions, command substitutions, and variable -expansions, are not examined in determining the matching -.Dq } . -.Pp -The simplest form for parameter expansion is: -.Pp -.Dl ${parameter} -.Pp -The value, if any, of parameter is substituted. -.Pp -The parameter name or symbol can be enclosed in braces, which are -optional except for positional parameters with more than one digit or -when parameter is followed by a character that could be interpreted as -part of the name. -If a parameter expansion occurs inside double quotes: -.Bl -enum -.It -Pathname expansion is not performed on the results of the expansion. -.It -Field splitting is not performed on the results of the -expansion, with the exception of the special rules for @. -.El -.Pp -In addition, a parameter expansion can be modified by using one of the -following formats. -If the -.Dq Dv \&: -is omitted in the following modifiers, then the expansion is applied only -to unset parameters, not null ones. -.Bl -tag -width aaparameterwordaaaaa -.It ${parameter:-word} -Use Default Values. -If parameter is unset or null, the expansion of word -is substituted; otherwise, the value of parameter is substituted. -.It ${parameter:=word} -Assign Default Values. -If parameter is unset or null, the expansion of -word is assigned to parameter. -In all cases, the final value of parameter is substituted. -Only variables, not positional parameters or special -parameters, can be assigned in this way. -.It ${parameter:?[word]} -Indicate Error if Null or Unset. -If parameter is unset or null, the -expansion of word (or a message indicating it is unset if word is omitted) -is written to standard error and the shell exits with a nonzero exit status. -Otherwise, the value of parameter is substituted. -An interactive shell need not exit. -.It ${parameter:+word} -Use Alternative Value. -If parameter is unset or null, null is -substituted; otherwise, the expansion of word is substituted. -.It ${#parameter} -String Length. -The length in characters of the value of parameter. -.El -.Pp -The following four varieties of parameter expansion provide for substring -processing. -In each case, pattern matching notation (see -.Sx Shell Patterns ) , -rather than regular expression notation, is used to evaluate the patterns. -If parameter is * or @, the result of the expansion is unspecified. -Enclosing the full parameter expansion string in double quotes does not -cause the following four varieties of pattern characters to be quoted, -whereas quoting characters within the braces has this effect. -.Bl -tag -width aaparameterwordaaaaa -.It ${parameter%word} -Remove Smallest Suffix Pattern. -The word is expanded to produce a pattern. -The parameter expansion then results in parameter, with the -smallest portion of the suffix matched by the pattern deleted. -.It ${parameter%%word} -Remove Largest Suffix Pattern. -The word is expanded to produce a pattern. -The parameter expansion then results in parameter, with the largest -portion of the suffix matched by the pattern deleted. -.It ${parameter#word} -Remove Smallest Prefix Pattern. -The word is expanded to produce a pattern. -The parameter expansion then results in parameter, with the -smallest portion of the prefix matched by the pattern deleted. -.It ${parameter##word} -Remove Largest Prefix Pattern. -The word is expanded to produce a pattern. -The parameter expansion then results in parameter, with the largest -portion of the prefix matched by the pattern deleted. -.El -.Ss Command Substitution -Command substitution allows the output of a command to be substituted in -place of the command name itself. -Command substitution occurs when the command is enclosed as follows: -.Pp -.Dl $(command) -.Pp -or -.Po -.Dq backquoted -version -.Pc : -.Pp -.Dl `command` -.Pp -The shell expands the command substitution by executing command in a -subshell environment and replacing the command substitution with the -standard output of the command, removing sequences of one or more -.Ao newline Ac Ns s -at the end of the substitution. -(Embedded -.Ao newline Ac Ns s -before -the end of the output are not removed; however, during field splitting, -they may be translated into -.Ao space Ac Ns s , -depending on the value of -.Ev IFS -and quoting that is in effect.) -.Ss Arithmetic Expansion -Arithmetic expansion provides a mechanism for evaluating an arithmetic -expression and substituting its value. -The format for arithmetic expansion is as follows: -.Pp -.Dl $((expression)) -.Pp -The expression is treated as if it were in double quotes, except -that a double quote inside the expression is not treated specially. -The shell expands all tokens in the expression for parameter expansion, -command substitution, and quote removal. -.Pp -Next, the shell treats this as an arithmetic expression and -substitutes the value of the expression. -.Pp -Arithmetic expressions use a syntax similar to that -of the C language, and are evaluated using the -.Ql intmax_t -data type (this is an extension to -.Tn POSIX , -which requires only -.Ql long -arithmetic). -Shell variables may be referenced by name inside an arithmetic -expression, without needing a -.Dq \&$ -sign. -.Ss White Space Splitting (Field Splitting) -After parameter expansion, command substitution, and -arithmetic expansion the shell scans the results of -expansions and substitutions that did not occur in double quotes for -field splitting and multiple fields can result. -.Pp -The shell treats each character of the -.Ev IFS -as a delimiter and use the delimiters to split the results of parameter -expansion and command substitution into fields. -.Pp -Non-whitespace characters in -.Ev IFS -are treated strictly as parameter terminators. -So adjacent non-whitespace -.Ev IFS -characters will produce empty parameters. -.Pp -If -.Ev IFS -is unset it is assumed to contain space, tab, and newline. -.Ss Pathname Expansion (File Name Generation) -Unless the -.Fl f -flag is set, file name generation is performed after word splitting is -complete. -Each word is viewed as a series of patterns, separated by slashes. -The process of expansion replaces the word with the names of all -existing files whose names can be formed by replacing each pattern with a -string that matches the specified pattern. -There are two restrictions on -this: first, a pattern cannot match a string containing a slash, and -second, a pattern cannot match a string starting with a period unless the -first character of the pattern is a period. -The next section describes the -patterns used for both Pathname Expansion and the -.Ic case -command. -.Ss Shell Patterns -A pattern consists of normal characters, which match themselves, -and meta-characters. -The meta-characters are -.Dq \&! , -.Dq * , -.Dq \&? , -and -.Dq \&[ . -These characters lose their special meanings if they are quoted. -When command or variable substitution is performed -and the dollar sign or backquotes are not double-quoted, -the value of the variable or the output of -the command is scanned for these characters and they are turned into -meta-characters. -.Pp -An asterisk -.Pq Dq * -matches any string of characters. -A question mark -.Pq Dq \&? -matches any single character. -A left bracket -.Pq Dq \&[ -introduces a character class. -The end of the character class is indicated by a right bracket -.Pq Dq \&] ; -if this -.Dq \&] -is missing then the -.Dq \&[ -matches a -.Dq \&[ -rather than introducing a character class. -A character class matches any of the characters between the square brackets. -A named class of characters (see -.Xr wctype 3 ) -may be specified by surrounding the name with -.Pq Dq [: -and -.Pq Dq :] . -For example, -.Pq Dq [[:alpha:]] -is a shell pattern that matches a single letter. -A range of characters may be specified using a minus sign -.Pq Dq - . -The character class may be complemented -by making an exclamation mark -.Pq Dq \&! -the first character of the character class. -.Pp -To include a -.Dq \&] -in a character class, make it the first character listed (after the -.Dq \&! , -if any). -To include a -.Dq - , -make it the first or last character listed. -.Ss Built-ins -This section lists the built-in commands which are built-in because they -need to perform some operation that can't be performed by a separate -process. -In addition to these, there are several other commands that may -be built in for efficiency (e.g. -.Xr printf 1 , -.Xr echo 1 , -.Xr test 1 , -etc). -.Bl -tag -width 5n -.It : [ Ar arg ... ] -A null command that returns a 0 (true) exit value. -Any arguments are ignored. -.It \&. file -The dot command reads and executes the commands from the specified -.Ar file -in the current shell environment. -The file does not need to be executable and is looked up from the directories -listed in the -.Ev PATH -variable if it does not contain a directory separator -.Pq Sq / . -The return command can be used for a premature return from the sourced file. -.Pp -The POSIX standard is unclear on how loop control keywords (break -and continue) behave across a dot command boundary. -This implementation allows them to control loops surrounding the dot command, -but obviously such behavior should not be relied on. -.It alias Op Ar name Ns Op Ar "=string ..." -If -.Ar name=string -is specified, the shell defines the alias -.Ar name -with value -.Ar string . -If just -.Ar name -is specified, the value of the alias -.Ar name -is printed. -With no arguments, the -.Ic alias -built-in prints the -names and values of all defined aliases (see -.Ic unalias ) . -.It bg [ Ar job ] ... -Continue the specified jobs (or the current job if no -jobs are given) in the background. -.It command Oo Fl p Oc Oo Fl v Oc Oo Fl V Oc Ar command Oo Ar arg ... Oc -Execute the specified command but ignore shell functions when searching -for it. -(This is useful when you -have a shell function with the same name as a built-in command.) -.Bl -tag -width 5n -.It Fl p -search for command using a -.Ev PATH -that guarantees to find all the standard utilities. -.It Fl V -Do not execute the command but -search for the command and print the resolution of the -command search. -This is the same as the -.Ic type -built-in. -.It Fl v -Do not execute the command but -search for the command and print the absolute pathname -of utilities, the name for built-ins or the expansion of aliases. -.El -.It cd Oo Fl P Oc Op Ar directory Op Ar replace -Switch to the specified directory (default -.Ev $HOME ) . -If -.Ar replace -is specified, then the new directory name is generated by replacing -the first occurrence of -.Ar directory -in the current directory name with -.Ar replace . -If -.Ar directory -is -.Sq - , -then the current working directory is changed to the previous current -working directory as set in -.Ev OLDPWD . -Otherwise if an entry for -.Ev CDPATH -appears in the environment of the -.Ic cd -command or the shell variable -.Ev CDPATH -is set and the directory name does not begin with a slash, -or its first (or only) component isn't dot or dot dot, -then the directories listed in -.Ev CDPATH -will be searched for the specified directory. -The format of -.Ev CDPATH -is the same as that of -.Ev PATH . -.Pp -The -.Fl P -option instructs the shell to update -.Ev PWD -with the specified physical directory path and change to that directory. -This is the default. -.Pp -When the directory changes, the variable -.Ev OLDPWD -is set to the working directory before the change. -.Pp -Some shells also support a -.Fl L -option, which instructs the shell to update -.Ev PWD -with the logical path and to change the current directory -accordingly. -This is not supported. -.Pp -In an interactive shell, the -.Ic cd -command will print out the name of the -directory that it actually switched to if this is different from the name -that the user gave. -These may be different either because the -.Ev CDPATH -mechanism was used or because a symbolic link was crossed. -.It eval Ar string ... -Concatenate all the arguments with spaces. -Then re-parse and execute the command. -.It exec Op Ar command arg ... -Unless command is omitted, the shell process is replaced with the -specified program (which must be a real program, not a shell built-in or -function). -Any redirections on the -.Ic exec -command are marked as permanent, so that they are not undone when the -.Ic exec -command finishes. -.It exit Op Ar exitstatus -Terminate the shell process. -If -.Ar exitstatus -is given it is used as the exit status of the shell; otherwise the -exit status of the preceding command is used. -.It export Ar name ... -.It export Fl p -The specified names are exported so that they will appear in the -environment of subsequent commands. -The only way to un-export a variable is to unset it. -The shell allows the value of a variable to be set at the -same time it is exported by writing -.Pp -.Dl export name=value -.Pp -With no arguments the export command lists the names of all exported variables. -With the -.Fl p -option specified the output will be formatted suitably for non-interactive use. -.It fc Oo Fl e Ar editor Oc Oo Ar first Oo Ar last Oc Oc -.It fc Fl l Oo Fl nr Oc Oo Ar first Oo Ar last Oc Oc -.It fc Fl s Oo Ar old=new Oc Oo Ar first Oc -The -.Ic fc -built-in lists, or edits and re-executes, commands previously entered -to an interactive shell. -.Bl -tag -width 5n -.It Fl e No editor -Use the editor named by editor to edit the commands. -The editor string is a command name, subject to search via the -.Ev PATH -variable. -The value in the -.Ev FCEDIT -variable is used as a default when -.Fl e -is not specified. -If -.Ev FCEDIT -is null or unset, the value of the -.Ev EDITOR -variable is used. -If -.Ev EDITOR -is null or unset, -.Xr ed 1 -is used as the editor. -.It Fl l No (ell) -List the commands rather than invoking an editor on them. -The commands are written in the sequence indicated by -the first and last operands, as affected by -.Fl r , -with each command preceded by the command number. -.It Fl n -Suppress command numbers when listing with -l. -.It Fl r -Reverse the order of the commands listed (with -.Fl l ) -or edited (with neither -.Fl l -nor -.Fl s ) . -.It Fl s -Re-execute the command without invoking an editor. -.It first -.It last -Select the commands to list or edit. -The number of previous commands that -can be accessed are determined by the value of the -.Ev HISTSIZE -variable. -The value of first or last or both are one of the following: -.Bl -tag -width 5n -.It [+]number -A positive number representing a command number; command numbers can be -displayed with the -.Fl l -option. -.It Fl number -A negative decimal number representing the command that was executed -number of commands previously. -For example, \-1 is the immediately previous command. -.El -.It string -A string indicating the most recently entered command that begins with -that string. -If the old=new operand is not also specified with -.Fl s , -the string form of the first operand cannot contain an embedded equal sign. -.El -.Pp -The following environment variables affect the execution of fc: -.Bl -tag -width HISTSIZE -.It Ev FCEDIT -Name of the editor to use. -.It Ev HISTSIZE -The number of previous commands that are accessible. -.El -.It fg Op Ar job -Move the specified job or the current job to the foreground. -.It getopts Ar optstring var -The -.Tn POSIX -.Ic getopts -command, not to be confused with the -.Em Bell Labs --derived -.Xr getopt 1 . -.Pp -The first argument should be a series of letters, each of which may be -optionally followed by a colon to indicate that the option requires an -argument. -The variable specified is set to the parsed option. -.Pp -The -.Ic getopts -command deprecates the older -.Xr getopt 1 -utility due to its handling of arguments containing whitespace. -.Pp -The -.Ic getopts -built-in may be used to obtain options and their arguments -from a list of parameters. -When invoked, -.Ic getopts -places the value of the next option from the option string in the list in -the shell variable specified by -.Va var -and its index in the shell variable -.Ev OPTIND . -When the shell is invoked, -.Ev OPTIND -is initialized to 1. -For each option that requires an argument, the -.Ic getopts -built-in will place it in the shell variable -.Ev OPTARG . -If an option is not allowed for in the -.Va optstring , -then -.Ev OPTARG -will be unset. -.Pp -.Va optstring -is a string of recognized option letters (see -.Xr getopt 3 ) . -If a letter is followed by a colon, the option is expected to have an -argument which may or may not be separated from it by whitespace. -If an option character is not found where expected, -.Ic getopts -will set the variable -.Va var -to a -.Dq \&? ; -.Ic getopts -will then unset -.Ev OPTARG -and write output to standard error. -By specifying a colon as the first character of -.Va optstring -all errors will be ignored. -.Pp -A nonzero value is returned when the last option is reached. -If there are no remaining arguments, -.Ic getopts -will set -.Va var -to the special option, -.Dq -- , -otherwise, it will set -.Va var -to -.Dq \&? . -.Pp -The following code fragment shows how one might process the arguments -for a command that can take the options -.Op a -and -.Op b , -and the option -.Op c , -which requires an argument. -.Bd -literal -offset indent -while getopts abc: f -do - case $f in - a | b) flag=$f;; - c) carg=$OPTARG;; - \e?) echo $USAGE; exit 1;; - esac -done -shift $(expr $OPTIND - 1) -.Ed -.Pp -This code will accept any of the following as equivalent: -.Bd -literal -offset indent -cmd \-acarg file file -cmd \-a \-c arg file file -cmd \-carg -a file file -cmd \-a \-carg \-\- file file -.Ed -.It hash Fl rv Ar command ... -The shell maintains a hash table which remembers the -locations of commands. -With no arguments whatsoever, -the -.Ic hash -command prints out the contents of this table. -Entries which have not been looked at since the last -.Ic cd -command are marked with an asterisk; it is possible for these entries -to be invalid. -.Pp -With arguments, the -.Ic hash -command removes the specified commands from the hash table (unless -they are functions) and then locates them. -With the -.Fl v -option, hash prints the locations of the commands as it finds them. -The -.Fl r -option causes the hash command to delete all the entries in the hash table -except for functions. -.It inputrc Ar file -Read the -.Va file -to set keybindings as defined by -.Xr editrc 5 . -.It jobid Op Ar job -Print the process id's of the processes in the job. -If the -.Ar job -argument is omitted, the current job is used. -.It jobs -This command lists out all the background processes -which are children of the current shell process. -.It pwd Op Fl \&LP -Print the current directory. -If -.Fl L -is specified the cached value (initially set from -.Ev PWD ) -is checked to see if it refers to the current directory; if it does -the value is printed. -Otherwise the current directory name is found using -.Xr getcwd 3 . -The environment variable -.Ev PWD -is set to the printed value. -.Pp -The default is -.Ic pwd -.Fl L , -but note that the built-in -.Ic cd -command doesn't currently support the -.Fl L -option and will cache (almost) the absolute path. -If -.Ic cd -is changed, -.Ic pwd -may be changed to default to -.Ic pwd -.Fl P . -.Pp -If the current directory is renamed and replaced by a symlink to the -same directory, or the initial -.Ev PWD -value followed a symbolic link, then the cached value may not -be the absolute path. -.Pp -The built-in command may differ from the program of the same name because -the program will use -.Ev PWD -and the built-in uses a separately cached value. -.It read Oo Fl p Ar prompt Oc Oo Fl r Oc Ar variable Oo Ar ... Oc -The prompt is printed if the -.Fl p -option is specified and the standard input is a terminal. -Then a line is read from the standard input. -The trailing newline is deleted from the -line and the line is split as described in the -.Sx Word Expansions -section above, and the pieces are assigned to the variables in order. -If there are more pieces than variables, the remaining pieces -(along with the characters in -.Ev IFS -that separated them) are assigned to the last variable. -If there are more variables than pieces, -the remaining variables are assigned the null string. -The -.Ic read -built-in will indicate success unless EOF is encountered on input, in -which case failure is returned. -.Pp -By default, unless the -.Fl r -option is specified, the backslash -.Dq \e -acts as an escape character, causing the following character to be treated -literally. -If a backslash is followed by a newline, the backslash and the -newline will be deleted. -.It readonly Ar name ... -.It readonly Fl p -The specified names are marked as read only, so that they cannot be -subsequently modified or unset. -The shell allows the value of a variable -to be set at the same time it is marked read only by writing -.Pp -.Dl readonly name=value -.Pp -With no arguments the readonly command lists the names of all read only -variables. -With the -.Fl p -option specified the output will be formatted suitably for non-interactive use. -.Pp -.It return [ Ar n ] -Stop executing the current function or a dot command with return value of -.Ar n -or the value of the last executed command, if not specified. -For portability, -.Ar n -should be in the range from 0 to 255. -.Pp -The POSIX standard says that the results of -.Sq return -outside a function or a dot command are unspecified. -This implementation treats such a return as a no-op with a return value of 0 -(success, true). -Use the exit command instead, if you want to return from a script or exit -your shell. -.It set Oo { Fl options | Cm +options | Cm \-- } Oc Ar arg ... -The -.Ic set -command performs three different functions. -.Pp -With no arguments, it lists the values of all shell variables. -.Pp -If options are given, it sets the specified option -flags, or clears them as described in the -.Sx Argument List Processing -section. -.Pp -The third use of the set command is to set the values of the shell's -positional parameters to the specified arguments. -To change the positional -parameters without changing any options, use -.Dq -- -as the first argument to set. -If no arguments are present, the set command -will clear all the positional parameters (equivalent to executing -.Dq shift $# . ) -.It setvar Ar variable Ar value -Assigns value to variable. -(In general it is better to write -variable=value rather than using -.Ic setvar . -.Ic setvar -is intended to be used in -functions that assign values to variables whose names are passed as -parameters.) -.It shift Op Ar n -Shift the positional parameters n times. -A -.Ic shift -sets the value of -.Va $1 -to the value of -.Va $2 , -the value of -.Va $2 -to the value of -.Va $3 , -and so on, decreasing -the value of -.Va $# -by one. -If there are zero positional parameters, -.Ic shift -does nothing. -.It trap Oo Fl l Oc -.It trap Oo Ar action Oc Ar signal ... -Cause the shell to parse and execute action when any of the specified -signals are received. -The signals are specified by signal number or as the name of the signal. -If -.Ar signal -is -.Li 0 -or its equivalent, EXIT, -the action is executed when the shell exits. -.Ar action -may be null, which cause the specified signals to be ignored. -With -.Ar action -omitted or set to -.Sq - -the specified signals are set to their default action. -When the shell forks off a subshell, it resets trapped (but not ignored) -signals to the default action. -On non-interactive shells, the -.Ic trap -command has no effect on signals that were -ignored on entry to the shell. -On interactive shells, the -.Ic trap -command will catch or reset signals ignored on entry. -Issuing -.Ic trap -with option -.Ar -l -will print a list of valid signal names. -.Ic trap -without any arguments cause it to write a list of signals and their -associated action to the standard output in a format that is suitable -as an input to the shell that achieves the same trapping results. -.Pp -Examples: -.Pp -.Dl trap -.Pp -List trapped signals and their corresponding action -.Pp -.Dl trap -l -.Pp -Print a list of valid signals -.Pp -.Dl trap '' INT QUIT tstp 30 -.Pp -Ignore signals INT QUIT TSTP USR1 -.Pp -.Dl trap date INT -.Pp -Print date upon receiving signal INT -.It type Op Ar name ... -Interpret each name as a command and print the resolution of the command -search. -Possible resolutions are: -shell keyword, alias, shell built-in, -command, tracked alias and not found. -For aliases the alias expansion is -printed; for commands and tracked aliases the complete pathname of the -command is printed. -.It ulimit Oo Fl H \*(Ba Fl S Oc Oo Fl a \*(Ba Fl btfdscmlrpnv Oo Ar value Oc Oc -Inquire about or set the hard or soft limits on processes or set new -limits. -The choice between hard limit (which no process is allowed to -violate, and which may not be raised once it has been lowered) and soft -limit (which causes processes to be signaled but not necessarily killed, -and which may be raised) is made with these flags: -.Bl -tag -width Fl -.It Fl H -set or inquire about hard limits -.It Fl S -set or inquire about soft limits. -If neither -.Fl H -nor -.Fl S -is specified, the soft limit is displayed or both limits are set. -If both are specified, the last one wins. -.El -.Pp -The limit to be interrogated or set, then, is chosen by specifying -any one of these flags: -.Bl -tag -width Fl -.It Fl a -show all the current limits -.It Fl b -show or set the limit on the socket buffer size of a process (in bytes) -.It Fl t -show or set the limit on CPU time (in seconds) -.It Fl f -show or set the limit on the largest file that can be created -(in 512-byte blocks) -.It Fl d -show or set the limit on the data segment size of a process (in kilobytes) -.It Fl s -show or set the limit on the stack size of a process (in kilobytes) -.It Fl c -show or set the limit on the largest core dump size that can be produced -(in 512-byte blocks) -.It Fl m -show or set the limit on the total physical memory that can be -in use by a process (in kilobytes) -.It Fl l -show or set the limit on how much memory a process can lock with -.Xr mlock 2 -(in kilobytes) -.It Fl r -show or set the limit on the number of threads this user can -have at one time -.It Fl p -show or set the limit on the number of processes this user can -have at one time -.It Fl n -show or set the limit on the number of files a process can have open at once -.It Fl v -show or set the limit on how large a process address space can be -.El -.Pp -If none of these is specified, it is the limit on file size that is shown -or set. -If value is specified, the limit is set to that number; otherwise -the current limit is displayed. -.Pp -Limits of an arbitrary process can be displayed or set using the -.Xr sysctl 8 -utility. -.Pp -.It umask Op Ar mask -Set the value of umask (see -.Xr umask 2 ) -to the specified octal value. -If the argument is omitted, the umask value is printed. -.It unalias Oo Fl a Oc Oo Ar name Oc -If -.Ar name -is specified, the shell removes that alias. -If -.Fl a -is specified, all aliases are removed. -.It unset Ar name ... -The specified variables and functions are unset and unexported. -If a given name corresponds to both a variable and a function, both -the variable and the function are unset. -.It wait Op Ar job -Wait for the specified job to complete and return the exit status of the -last process in the job. -If the argument is omitted, wait for all jobs to -complete and then return an exit status of zero. -.El -.Ss Command Line Editing -When -.Nm -is being used interactively from a terminal, the current command -and the command history (see -.Ic fc -in the -.Sx Built-ins -section) -can be edited using emacs-mode or vi-mode command-line editing. -The command -.Ql set -o emacs -enables emacs-mode editing. -The command -.Ql set -o vi -enables vi-mode editing and places the current shell process into -.Ar vi -insert mode. -(See the -.Sx Argument List Processing -section above.) -.Pp -The -.Ar vi -mode uses commands similar to a subset of those described in the -.Xr vi 1 -man page. -With vi-mode -enabled, -.Nm sh -can be switched between insert mode and command mode. -It's similar to -.Xr vi 1 : -pressing the -.Aq ESC -key will throw you into command VI command mode. -Pressing the -.Aq return -key while in command mode will pass the line to the shell. -.Pp -The -.Ar emacs -mode uses commands similar to a subset available in -the -.Xr emacs 1 -editor. -With emacs-mode enabled, special keys can be used to modify the text -in the buffer using the control key. -.Pp -.Nm -uses the -.Xr editline 3 -library. -.Sh ENVIRONMENT -.Bl -tag -width MAILCHECK -.It Ev HOME -Set automatically by -.Xr login 1 -from the user's login directory in the password file -.Pq Xr passwd 5 . -This environment variable also functions as the default argument for the -.Ic cd -built-in. -.It Ev PATH -The default search path for executables. -See the -.Sx Path Search -section above. -.It Ev CDPATH -The search path used with the -.Ic cd -built-in. -.It Ev LINENO -The current line number in the script or function. -.It Ev LANG -The string used to specify localization information that allows users -to work with different culture-specific and language conventions. -See -.Xr nls 7 . -.It Ev MAIL -The name of a mail file, that will be checked for the arrival of new mail. -Overridden by -.Ev MAILPATH . -.It Ev MAILCHECK -The frequency in seconds that the shell checks for the arrival of mail -in the files specified by the -.Ev MAILPATH -or the -.Ev MAIL -file. -If set to 0, the check will occur at each prompt. -.It Ev MAILPATH -A colon -.Dq \&: -separated list of file names, for the shell to check for incoming mail. -This environment setting overrides the -.Ev MAIL -setting. -There is a maximum of 10 mailboxes that can be monitored at once. -.It Ev PS1 -The primary prompt string, which defaults to -.Dq $ \ , -unless you are the superuser, in which case it defaults to -.Dq # \ . -.It Ev PS2 -The secondary prompt string, which defaults to -.Dq \*[Gt] \ . -.It Ev PS4 -Output before each line when execution trace (set -x) is enabled, -defaults to -.Dq + \ . -.It Ev IFS -Input Field Separators. -This is normally set to -.Aq space , -.Aq tab , -and -.Aq newline . -See the -.Sx White Space Splitting -section for more details. -.It Ev TERM -The default terminal setting for the shell. -This is inherited by -children of the shell, and is used in the history editing modes. -.It Ev HISTSIZE -The number of lines in the history buffer for the shell. -.El -.Sh FILES -.Bl -item -.It -.Pa $HOME/.profile -.It -.Pa /etc/profile -.El -.Sh EXIT STATUS -Errors that are detected by the shell, such as a syntax error, will cause the -shell to exit with a non-zero exit status. -If the shell is not an -interactive shell, the execution of the shell file will be aborted. -Otherwise -the shell will return the exit status of the last command executed, or -if the exit built-in is used with a numeric argument, it will return the -argument. -.Sh SEE ALSO -.Xr csh 1 , -.Xr echo 1 , -.Xr getopt 1 , -.Xr ksh 1 , -.Xr login 1 , -.Xr printf 1 , -.Xr test 1 , -.Xr editline 3 , -.Xr getopt 3 , -.\" .Xr profile 4 , -.Xr editrc 5 , -.Xr passwd 5 , -.Xr environ 7 , -.Xr nls 7 , -.Xr sysctl 8 -.Sh HISTORY -A -.Nm -command appeared in -.At v1 . -It was, however, unmaintainable so we wrote this one. -.Sh BUGS -Setuid shell scripts should be avoided at all costs, as they are a -significant security risk. -.Pp -PS1, PS2, and PS4 should be subject to parameter expansion before -being displayed. -.Pp -The characters generated by filename completion should probably be quoted -to ensure that the filename is still valid after the input line has been -processed. diff --git a/bin/sh/shell.h b/bin/sh/shell.h deleted file mode 100644 index 4df721a80..000000000 --- a/bin/sh/shell.h +++ /dev/null @@ -1,89 +0,0 @@ -/* $NetBSD: shell.h,v 1.18 2013/04/28 17:01:28 dholland Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)shell.h 8.2 (Berkeley) 5/4/95 - */ - -/* - * The follow should be set to reflect the type of system you have: - * JOBS -> 1 if you have Berkeley job control, 0 otherwise. - * SHORTNAMES -> 1 if your linker cannot handle long names. - * define BSD if you are running 4.2 BSD or later. - * define SYSV if you are running under System V. - * define DEBUG=1 to compile in debugging ('set -o debug' to turn on) - * define DEBUG=2 to compile in and turn on debugging. - * define DO_SHAREDVFORK to indicate that vfork(2) shares its address - * with its parent. - * - * When debugging is on, debugging info will be written to ./trace and - * a quit signal will generate a core dump. - */ - -#include - -#if defined(__minix) -#define JOBS 0 -#else -#define JOBS 1 -#endif /* defined(__minix) */ -#ifndef BSD -#define BSD 1 -#endif - -#ifndef DO_SHAREDVFORK -#if !defined(__minix) -#if __NetBSD_Version__ >= 104000000 -#define DO_SHAREDVFORK -#endif -#endif /* !defined(__minix) */ -#endif - -typedef void *pointer; -#ifndef NULL -#define NULL (void *)0 -#endif -#define STATIC /* empty */ -#define MKINIT /* empty */ - -#include - -extern const char nullstr[1]; /* null string */ - - -#ifdef DEBUG -#define TRACE(param) trace param -#define TRACEV(param) tracev param -#else -#define TRACE(param) -#define TRACEV(param) -#endif diff --git a/bin/sh/show.c b/bin/sh/show.c deleted file mode 100644 index 9c008715d..000000000 --- a/bin/sh/show.c +++ /dev/null @@ -1,430 +0,0 @@ -/* $NetBSD: show.c,v 1.28 2011/08/23 10:01:32 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: show.c,v 1.28 2011/08/23 10:01:32 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include - -#include "shell.h" -#include "parser.h" -#include "nodes.h" -#include "mystring.h" -#include "show.h" -#include "options.h" - - -#ifdef DEBUG -static void shtree(union node *, int, char *, FILE*); -static void shcmd(union node *, FILE *); -static void sharg(union node *, FILE *); -static void indent(int, char *, FILE *); -static void trstring(char *); - - -void -showtree(union node *n) -{ - trputs("showtree called\n"); - shtree(n, 1, NULL, stdout); -} - - -static void -shtree(union node *n, int ind, char *pfx, FILE *fp) -{ - struct nodelist *lp; - const char *s; - - if (n == NULL) - return; - - indent(ind, pfx, fp); - switch(n->type) { - case NSEMI: - s = "; "; - goto binop; - case NAND: - s = " && "; - goto binop; - case NOR: - s = " || "; -binop: - shtree(n->nbinary.ch1, ind, NULL, fp); - /* if (ind < 0) */ - fputs(s, fp); - shtree(n->nbinary.ch2, ind, NULL, fp); - break; - case NCMD: - shcmd(n, fp); - if (ind >= 0) - putc('\n', fp); - break; - case NPIPE: - for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) { - shcmd(lp->n, fp); - if (lp->next) - fputs(" | ", fp); - } - if (n->npipe.backgnd) - fputs(" &", fp); - if (ind >= 0) - putc('\n', fp); - break; - default: - fprintf(fp, "", n->type); - if (ind >= 0) - putc('\n', fp); - break; - } -} - - - -static void -shcmd(union node *cmd, FILE *fp) -{ - union node *np; - int first; - const char *s; - int dftfd; - - first = 1; - for (np = cmd->ncmd.args ; np ; np = np->narg.next) { - if (! first) - putchar(' '); - sharg(np, fp); - first = 0; - } - for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) { - if (! first) - putchar(' '); - switch (np->nfile.type) { - case NTO: s = ">"; dftfd = 1; break; - case NCLOBBER: s = ">|"; dftfd = 1; break; - case NAPPEND: s = ">>"; dftfd = 1; break; - case NTOFD: s = ">&"; dftfd = 1; break; - case NFROM: s = "<"; dftfd = 0; break; - case NFROMFD: s = "<&"; dftfd = 0; break; - case NFROMTO: s = "<>"; dftfd = 0; break; - default: s = "*error*"; dftfd = 0; break; - } - if (np->nfile.fd != dftfd) - fprintf(fp, "%d", np->nfile.fd); - fputs(s, fp); - if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) { - fprintf(fp, "%d", np->ndup.dupfd); - } else { - sharg(np->nfile.fname, fp); - } - first = 0; - } -} - - - -static void -sharg(union node *arg, FILE *fp) -{ - char *p; - struct nodelist *bqlist; - int subtype; - - if (arg->type != NARG) { - printf("\n", arg->type); - abort(); - } - bqlist = arg->narg.backquote; - for (p = arg->narg.text ; *p ; p++) { - switch (*p) { - case CTLESC: - putc(*++p, fp); - break; - case CTLVAR: - putc('$', fp); - putc('{', fp); - subtype = *++p; - if (subtype == VSLENGTH) - putc('#', fp); - - while (*p != '=') - putc(*p++, fp); - - if (subtype & VSNUL) - putc(':', fp); - - switch (subtype & VSTYPE) { - case VSNORMAL: - putc('}', fp); - break; - case VSMINUS: - putc('-', fp); - break; - case VSPLUS: - putc('+', fp); - break; - case VSQUESTION: - putc('?', fp); - break; - case VSASSIGN: - putc('=', fp); - break; - case VSTRIMLEFT: - putc('#', fp); - break; - case VSTRIMLEFTMAX: - putc('#', fp); - putc('#', fp); - break; - case VSTRIMRIGHT: - putc('%', fp); - break; - case VSTRIMRIGHTMAX: - putc('%', fp); - putc('%', fp); - break; - case VSLENGTH: - break; - default: - printf("", subtype); - } - break; - case CTLENDVAR: - putc('}', fp); - break; - case CTLBACKQ: - case CTLBACKQ|CTLQUOTE: - putc('$', fp); - putc('(', fp); - shtree(bqlist->n, -1, NULL, fp); - putc(')', fp); - break; - default: - putc(*p, fp); - break; - } - } -} - - -static void -indent(int amount, char *pfx, FILE *fp) -{ - int i; - - for (i = 0 ; i < amount ; i++) { - if (pfx && i == amount - 1) - fputs(pfx, fp); - putc('\t', fp); - } -} -#endif - - - -/* - * Debugging stuff. - */ - - -FILE *tracefile; - - -#ifdef DEBUG -void -trputc(int c) -{ - if (debug != 1 || !tracefile) - return; - putc(c, tracefile); -} -#endif - -void -trace(const char *fmt, ...) -{ -#ifdef DEBUG - va_list va; - - if (debug != 1 || !tracefile) - return; - va_start(va, fmt); - (void) vfprintf(tracefile, fmt, va); - va_end(va); -#endif -} - -void -tracev(const char *fmt, va_list va) -{ -#ifdef DEBUG - va_list ap; - if (debug != 1 || !tracefile) - return; - va_copy(ap, va); - (void) vfprintf(tracefile, fmt, ap); - va_end(ap); -#endif -} - - -#ifdef DEBUG -void -trputs(const char *s) -{ - if (debug != 1 || !tracefile) - return; - fputs(s, tracefile); -} - - -static void -trstring(char *s) -{ - char *p; - char c; - - if (debug != 1 || !tracefile) - return; - putc('"', tracefile); - for (p = s ; *p ; p++) { - switch (*p) { - case '\n': c = 'n'; goto backslash; - case '\t': c = 't'; goto backslash; - case '\r': c = 'r'; goto backslash; - case '"': c = '"'; goto backslash; - case '\\': c = '\\'; goto backslash; - case CTLESC: c = 'e'; goto backslash; - case CTLVAR: c = 'v'; goto backslash; - case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; - case CTLBACKQ: c = 'q'; goto backslash; - case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; -backslash: putc('\\', tracefile); - putc(c, tracefile); - break; - default: - if (*p >= ' ' && *p <= '~') - putc(*p, tracefile); - else { - putc('\\', tracefile); - putc(*p >> 6 & 03, tracefile); - putc(*p >> 3 & 07, tracefile); - putc(*p & 07, tracefile); - } - break; - } - } - putc('"', tracefile); -} -#endif - - -void -trargs(char **ap) -{ -#ifdef DEBUG - if (debug != 1 || !tracefile) - return; - while (*ap) { - trstring(*ap++); - if (*ap) - putc(' ', tracefile); - else - putc('\n', tracefile); - } -#endif -} - - -#ifdef DEBUG -void -opentrace(void) -{ - char s[100]; -#ifdef O_APPEND - int flags; -#endif - - if (debug != 1) { - if (tracefile) - fflush(tracefile); - /* leave open because libedit might be using it */ - return; - } -#ifdef not_this_way - { - char *p; - if ((p = getenv("HOME")) == NULL) { - if (geteuid() == 0) - p = "/"; - else - p = "/tmp"; - } - scopy(p, s); - strcat(s, "/trace"); - } -#else - snprintf(s, sizeof(s), "./trace.%d", (int)getpid()); -#endif /* not_this_way */ - if (tracefile) { - if (!freopen(s, "a", tracefile)) { - fprintf(stderr, "Can't re-open %s\n", s); - tracefile = NULL; - debug = 0; - return; - } - } else { - if ((tracefile = fopen(s, "a")) == NULL) { - fprintf(stderr, "Can't open %s\n", s); - debug = 0; - return; - } - } -#ifdef O_APPEND - if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0) - fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); -#endif - setlinebuf(tracefile); - fputs("\nTracing started.\n", tracefile); -} -#endif /* DEBUG */ diff --git a/bin/sh/show.h b/bin/sh/show.h deleted file mode 100644 index 3152ff277..000000000 --- a/bin/sh/show.h +++ /dev/null @@ -1,45 +0,0 @@ -/* $NetBSD: show.h,v 1.7 2003/08/07 09:05:38 agc Exp $ */ - -/*- - * Copyright (c) 1995 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)show.h 1.1 (Berkeley) 5/4/95 - */ - -#include - -union node; -void showtree(union node *); -void trace(const char *, ...); -void tracev(const char *, va_list); -void trargs(char **); -#ifdef DEBUG -void trputc(int); -void trputs(const char *); -void opentrace(void); -#endif diff --git a/bin/sh/syntax.c b/bin/sh/syntax.c deleted file mode 100644 index e0647294f..000000000 --- a/bin/sh/syntax.c +++ /dev/null @@ -1,105 +0,0 @@ -/* $NetBSD: syntax.c,v 1.3 2012/03/28 20:11:25 christos Exp $ */ - -#include -__RCSID("$NetBSD: syntax.c,v 1.3 2012/03/28 20:11:25 christos Exp $"); - -#include -#include "shell.h" -#include "syntax.h" -#include "parser.h" - -#if CWORD != 0 -#error initialisation assumes 'CWORD' is zero -#endif - -#define ndx(ch) (ch + 1 - CHAR_MIN) -#define set(ch, val) [ndx(ch)] = val, -#define set_range(s, e, val) [ndx(s) ... ndx(e)] = val, - -/* syntax table used when not in quotes */ -const char basesyntax[257] = { CEOF, - set_range(CTL_FIRST, CTL_LAST, CCTL) - set('\n', CNL) - set('\\', CBACK) - set('\'', CSQUOTE) - set('"', CDQUOTE) - set('`', CBQUOTE) - set('$', CVAR) - set('}', CENDVAR) - set('<', CSPCL) - set('>', CSPCL) - set('(', CSPCL) - set(')', CSPCL) - set(';', CSPCL) - set('&', CSPCL) - set('|', CSPCL) - set(' ', CSPCL) - set('\t', CSPCL) -}; - -/* syntax table used when in double quotes */ -const char dqsyntax[257] = { CEOF, - set_range(CTL_FIRST, CTL_LAST, CCTL) - set('\n', CNL) - set('\\', CBACK) - set('"', CDQUOTE) - set('`', CBQUOTE) - set('$', CVAR) - set('}', CENDVAR) - /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ - set('!', CCTL) - set('*', CCTL) - set('?', CCTL) - set('[', CCTL) - set('=', CCTL) - set('~', CCTL) - set(':', CCTL) - set('/', CCTL) - set('-', CCTL) -}; - -/* syntax table used when in single quotes */ -const char sqsyntax[257] = { CEOF, - set_range(CTL_FIRST, CTL_LAST, CCTL) - set('\n', CNL) - set('\'', CSQUOTE) - /* ':/' for tilde expansion, '-' for [a\-x] pattern ranges */ - set('!', CCTL) - set('*', CCTL) - set('?', CCTL) - set('[', CCTL) - set('=', CCTL) - set('~', CCTL) - set(':', CCTL) - set('/', CCTL) - set('-', CCTL) -}; - -/* syntax table used when in arithmetic */ -const char arisyntax[257] = { CEOF, - set_range(CTL_FIRST, CTL_LAST, CCTL) - set('\n', CNL) - set('\\', CBACK) - set('`', CBQUOTE) - set('\'', CSQUOTE) - set('"', CDQUOTE) - set('$', CVAR) - set('}', CENDVAR) - set('(', CLP) - set(')', CRP) -}; - -/* character classification table */ -const char is_type[257] = { 0, - set_range('0', '9', ISDIGIT) - set_range('a', 'z', ISLOWER) - set_range('A', 'Z', ISUPPER) - set('_', ISUNDER) - set('#', ISSPECL) - set('?', ISSPECL) - set('$', ISSPECL) - set('!', ISSPECL) - set('-', ISSPECL) - set('*', ISSPECL) - set('@', ISSPECL) -}; diff --git a/bin/sh/syntax.h b/bin/sh/syntax.h deleted file mode 100644 index 89a32dcdc..000000000 --- a/bin/sh/syntax.h +++ /dev/null @@ -1,83 +0,0 @@ -/* $NetBSD: syntax.h,v 1.2 2004/01/17 17:38:12 dsl Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include - -/* Syntax classes */ -#define CWORD 0 /* character is nothing special */ -#define CNL 1 /* newline character */ -#define CBACK 2 /* a backslash character */ -#define CSQUOTE 3 /* single quote */ -#define CDQUOTE 4 /* double quote */ -#define CBQUOTE 5 /* backwards single quote */ -#define CVAR 6 /* a dollar sign */ -#define CENDVAR 7 /* a '}' character */ -#define CLP 8 /* a left paren in arithmetic */ -#define CRP 9 /* a right paren in arithmetic */ -#define CEOF 10 /* end of file */ -#define CCTL 11 /* like CWORD, except it must be escaped */ -#define CSPCL 12 /* these terminate a word */ - -/* Syntax classes for is_ functions */ -#define ISDIGIT 01 /* a digit */ -#define ISUPPER 02 /* an upper case letter */ -#define ISLOWER 04 /* a lower case letter */ -#define ISUNDER 010 /* an underscore */ -#define ISSPECL 020 /* the name of a special parameter */ - -#define PEOF (CHAR_MIN - 1) -#define SYNBASE (-PEOF) -/* XXX UPEOF is CHAR_MAX, so is a valid 'char' value... */ -#define UPEOF ((char)PEOF) - - -#define BASESYNTAX (basesyntax + SYNBASE) -#define DQSYNTAX (dqsyntax + SYNBASE) -#define SQSYNTAX (sqsyntax + SYNBASE) -#define ARISYNTAX (arisyntax + SYNBASE) - -/* These defines assume that the digits are contiguous */ -#define is_digit(c) ((unsigned)((c) - '0') <= 9) -#define is_alpha(c) (((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && isalpha((unsigned char)(c))) -#define is_name(c) (((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalpha((unsigned char)(c)))) -#define is_in_name(c) (((char)(c)) != UPEOF && ((c) < CTL_FIRST || (c) > CTL_LAST) && ((c) == '_' || isalnum((unsigned char)(c)))) -#define is_special(c) ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT)) -#define digit_val(c) ((c) - '0') - -extern const char basesyntax[]; -extern const char dqsyntax[]; -extern const char sqsyntax[]; -extern const char arisyntax[]; -extern const char is_type[]; diff --git a/bin/sh/trap.c b/bin/sh/trap.c deleted file mode 100644 index 644c9ea4d..000000000 --- a/bin/sh/trap.c +++ /dev/null @@ -1,484 +0,0 @@ -/* $NetBSD: trap.c,v 1.37 2015/08/22 12:12:47 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95"; -#else -__RCSID("$NetBSD: trap.c,v 1.37 2015/08/22 12:12:47 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include - -#include "shell.h" -#include "main.h" -#include "nodes.h" /* for other headers */ -#include "eval.h" -#include "jobs.h" -#include "show.h" -#include "options.h" -#include "builtins.h" -#include "syntax.h" -#include "output.h" -#include "memalloc.h" -#include "error.h" -#include "trap.h" -#include "mystring.h" -#include "var.h" - - -/* - * Sigmode records the current value of the signal handlers for the various - * modes. A value of zero means that the current handler is not known. - * S_HARD_IGN indicates that the signal was ignored on entry to the shell, - */ - -#define S_DFL 1 /* default signal handling (SIG_DFL) */ -#define S_CATCH 2 /* signal is caught */ -#define S_IGN 3 /* signal is ignored (SIG_IGN) */ -#define S_HARD_IGN 4 /* signal is ignored permenantly */ -#define S_RESET 5 /* temporary - to reset a hard ignored sig */ - - -char *trap[NSIG+1]; /* trap handler commands */ -MKINIT char sigmode[NSIG]; /* current value of signal */ -static volatile char gotsig[NSIG];/* indicates specified signal received */ -volatile int pendingsigs; /* indicates some signal received */ - -static int getsigaction(int, sig_t *); - -/* - * return the signal number described by `p' (as a number or a name) - * or -1 if it isn't one - */ - -static int -signame_to_signum(const char *p) -{ - int i; - - if (is_number(p)) - return number(p); - - if (strcasecmp(p, "exit") == 0 ) - return 0; - - if (strncasecmp(p, "sig", 3) == 0) - p += 3; - - for (i = 0; i < NSIG; ++i) - if (strcasecmp (p, sys_signame[i]) == 0) - return i; - return -1; -} - -/* - * Print a list of valid signal names - */ -static void -printsignals(void) -{ - int n; - - out1str("EXIT "); - - for (n = 1; n < NSIG; n++) { - out1fmt("%s", sys_signame[n]); - if ((n == NSIG/2) || n == (NSIG - 1)) - out1str("\n"); - else - out1c(' '); - } -} - -/* - * The trap builtin. - */ - -int -trapcmd(int argc, char **argv) -{ - char *action; - char **ap; - int signo; - - if (argc <= 1) { - for (signo = 0 ; signo <= NSIG ; signo++) - if (trap[signo] != NULL) { - out1fmt("trap -- "); - print_quoted(trap[signo]); - out1fmt(" %s\n", - (signo) ? sys_signame[signo] : "EXIT"); - } - return 0; - } - ap = argv + 1; - - action = NULL; - - if (strcmp(*ap, "--") == 0) - if (*++ap == NULL) - return 0; - - if (signame_to_signum(*ap) == -1) { - if ((*ap)[0] == '-') { - if ((*ap)[1] == '\0') - ap++; - else if ((*ap)[1] == 'l' && (*ap)[2] == '\0') { - printsignals(); - return 0; - } - else - error("bad option %s\n", *ap); - } - else - action = *ap++; - } - - while (*ap) { - if (is_number(*ap)) - signo = number(*ap); - else - signo = signame_to_signum(*ap); - - if (signo < 0 || signo > NSIG) - error("%s: bad trap", *ap); - - INTOFF; - if (action) - action = savestr(action); - - if (trap[signo]) - ckfree(trap[signo]); - - trap[signo] = action; - - if (signo != 0) - setsignal(signo, 0); - INTON; - ap++; - } - return 0; -} - - - -/* - * Clear traps on a fork or vfork. - * Takes one arg vfork, to tell it to not be destructive of - * the parents variables. - */ - -void -clear_traps(int vforked) -{ - char **tp; - - for (tp = trap ; tp <= &trap[NSIG] ; tp++) { - if (*tp && **tp) { /* trap not NULL or SIG_IGN */ - INTOFF; - if (!vforked) { - ckfree(*tp); - *tp = NULL; - } - if (tp != &trap[0]) - setsignal(tp - trap, vforked); - INTON; - } - } -} - - - -/* - * Set the signal handler for the specified signal. The routine figures - * out what it should be set to. - */ - -sig_t -setsignal(int signo, int vforked) -{ - int action; - sig_t sigact = SIG_DFL, sig; - char *t, tsig; - - if ((t = trap[signo]) == NULL) - action = S_DFL; - else if (*t != '\0') - action = S_CATCH; - else - action = S_IGN; - if (rootshell && !vforked && action == S_DFL) { - switch (signo) { - case SIGINT: - if (iflag || minusc || sflag == 0) - action = S_CATCH; - break; - case SIGQUIT: -#ifdef DEBUG - if (debug) - break; -#endif - /* FALLTHROUGH */ - case SIGTERM: - if (iflag) - action = S_IGN; - break; -#if JOBS - case SIGTSTP: - case SIGTTOU: - if (mflag) - action = S_IGN; - break; -#endif - } - } - - t = &sigmode[signo - 1]; - tsig = *t; - if (tsig == 0) { - /* - * current setting unknown - */ - if (!getsigaction(signo, &sigact)) { - /* - * Pretend it worked; maybe we should give a warning - * here, but other shells don't. We don't alter - * sigmode, so that we retry every time. - */ - return 0; - } - if (sigact == SIG_IGN) { - /* - * POSIX 3.14.13 states that non-interactive shells - * should ignore trap commands for signals that were - * ignored upon entry, and leaves the behavior - * unspecified for interactive shells. On interactive - * shells, or if job control is on, and we have a job - * control related signal, we allow the trap to work. - * - * This change allows us to be POSIX compliant, and - * at the same time override the default behavior if - * we need to by setting the interactive flag. - */ - if ((mflag && (signo == SIGTSTP || - signo == SIGTTIN || signo == SIGTTOU)) || iflag) { - tsig = S_IGN; - } else - tsig = S_HARD_IGN; - } else { - tsig = S_RESET; /* force to be set */ - } - } - if (tsig == S_HARD_IGN || tsig == action) - return 0; - switch (action) { - case S_DFL: sigact = SIG_DFL; break; - case S_CATCH: sigact = onsig; break; - case S_IGN: sigact = SIG_IGN; break; - } - sig = signal(signo, sigact); - if (sig != SIG_ERR) { - sigset_t ss; - if (!vforked) - *t = action; - if (action == S_CATCH) - (void)siginterrupt(signo, 1); - /* - * If our parent accidentally blocked signals for - * us make sure we unblock them - */ - (void)sigemptyset(&ss); - (void)sigaddset(&ss, signo); - (void)sigprocmask(SIG_UNBLOCK, &ss, NULL); - } - return sig; -} - -/* - * Return the current setting for sig w/o changing it. - */ -static int -getsigaction(int signo, sig_t *sigact) -{ - struct sigaction sa; - - if (sigaction(signo, (struct sigaction *)0, &sa) == -1) - return 0; - *sigact = (sig_t) sa.sa_handler; - return 1; -} - -/* - * Ignore a signal. - */ - -void -ignoresig(int signo, int vforked) -{ - if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) { - signal(signo, SIG_IGN); - } - if (!vforked) - sigmode[signo - 1] = S_HARD_IGN; -} - - -#ifdef mkinit -INCLUDE -INCLUDE "trap.h" - -SHELLPROC { - char *sm; - - clear_traps(0); - for (sm = sigmode ; sm < sigmode + NSIG ; sm++) { - if (*sm == S_IGN) - *sm = S_HARD_IGN; - } -} -#endif - - - -/* - * Signal handler. - */ - -void -onsig(int signo) -{ - signal(signo, onsig); - if (signo == SIGINT && trap[SIGINT] == NULL) { - onint(); - return; - } - gotsig[signo - 1] = 1; - pendingsigs++; -} - - - -/* - * Called to execute a trap. Perhaps we should avoid entering new trap - * handlers while we are executing a trap handler. - */ - -void -dotrap(void) -{ - int i; - int savestatus; - - for (;;) { - for (i = 1 ; ; i++) { - if (gotsig[i - 1]) - break; - if (i >= NSIG) - goto done; - } - gotsig[i - 1] = 0; - savestatus=exitstatus; - evalstring(trap[i], 0); - exitstatus=savestatus; - } -done: - pendingsigs = 0; -} - -int -lastsig(void) -{ - int i; - - for (i = NSIG; i > 0; i--) - if (gotsig[i - 1]) - return i; - return SIGINT; /* XXX */ -} - -/* - * Controls whether the shell is interactive or not. - */ - - -void -setinteractive(int on) -{ - static int is_interactive; - - if (on == is_interactive) - return; - setsignal(SIGINT, 0); - setsignal(SIGQUIT, 0); - setsignal(SIGTERM, 0); - is_interactive = on; -} - - - -/* - * Called to exit the shell. - */ - -void -exitshell(int status) -{ - struct jmploc loc1, loc2; - char *p; - - TRACE(("pid %d, exitshell(%d)\n", getpid(), status)); - if (setjmp(loc1.loc)) { - goto l1; - } - if (setjmp(loc2.loc)) { - goto l2; - } - handler = &loc1; - if ((p = trap[0]) != NULL && *p != '\0') { - trap[0] = NULL; - evalstring(p, 0); - } -l1: handler = &loc2; /* probably unnecessary */ - flushall(); -#if JOBS - setjobctl(0); -#endif -l2: _exit(status); - /* NOTREACHED */ -} diff --git a/bin/sh/trap.h b/bin/sh/trap.h deleted file mode 100644 index 316ef35ff..000000000 --- a/bin/sh/trap.h +++ /dev/null @@ -1,46 +0,0 @@ -/* $NetBSD: trap.h,v 1.22 2015/08/22 12:12:47 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)trap.h 8.3 (Berkeley) 6/5/95 - */ - -extern volatile int pendingsigs; - -void clear_traps(int); -sig_t setsignal(int, int); -void ignoresig(int, int); -void onsig(int); -void dotrap(void); -void setinteractive(int); -void exitshell(int) __dead; -int lastsig(void); diff --git a/bin/sh/var.c b/bin/sh/var.c deleted file mode 100644 index c61b15bab..000000000 --- a/bin/sh/var.c +++ /dev/null @@ -1,844 +0,0 @@ -/* $NetBSD: var.c,v 1.44 2015/05/26 21:35:15 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95"; -#else -__RCSID("$NetBSD: var.c,v 1.44 2015/05/26 21:35:15 christos Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include - -/* - * Shell variables. - */ - -#include "shell.h" -#include "output.h" -#include "expand.h" -#include "nodes.h" /* for other headers */ -#include "eval.h" /* defines cmdenviron */ -#include "exec.h" -#include "syntax.h" -#include "options.h" -#include "builtins.h" -#include "mail.h" -#include "var.h" -#include "memalloc.h" -#include "error.h" -#include "mystring.h" -#include "parser.h" -#include "show.h" -#ifndef SMALL -#include "myhistedit.h" -#endif - -#ifdef SMALL -#define VTABSIZE 39 -#else -#define VTABSIZE 517 -#endif - - -struct varinit { - struct var *var; - int flags; - const char *text; - void (*func)(const char *); -}; - -struct localvar *localvars; - -#if ATTY -struct var vatty; -#endif -#ifndef SMALL -struct var vhistsize; -struct var vterm; -#endif -struct var vifs; -struct var vmail; -struct var vmpath; -struct var vpath; -struct var vps1; -struct var vps2; -struct var vps4; -struct var vvers; -struct var voptind; - -const struct varinit varinit[] = { -#if ATTY - { &vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY=", - NULL }, -#endif -#ifndef SMALL - { &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=", - sethistsize }, -#endif - { &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n", - NULL }, - { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=", - NULL }, - { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=", - NULL }, - { &vpath, VSTRFIXED|VTEXTFIXED, "PATH=" _PATH_DEFPATH, - changepath }, - /* - * vps1 depends on uid - */ - { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ", - NULL }, - { &vps4, VSTRFIXED|VTEXTFIXED, "PS4=+ ", - NULL }, -#ifndef SMALL - { &vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM=", - setterm }, -#endif - { &voptind, VSTRFIXED|VTEXTFIXED|VNOFUNC, "OPTIND=1", - getoptsreset }, - { NULL, 0, NULL, - NULL } -}; - -struct var *vartab[VTABSIZE]; - -STATIC int strequal(const char *, const char *); -STATIC struct var *find_var(const char *, struct var ***, int *); - -/* - * Initialize the varable symbol tables and import the environment - */ - -#ifdef mkinit -INCLUDE "var.h" -MKINIT char **environ; -INIT { - char **envp; - - initvar(); - for (envp = environ ; *envp ; envp++) { - if (strchr(*envp, '=')) { - setvareq(*envp, VEXPORT|VTEXTFIXED); - } - } -} -#endif - - -/* - * This routine initializes the builtin variables. It is called when the - * shell is initialized and again when a shell procedure is spawned. - */ - -void -initvar(void) -{ - const struct varinit *ip; - struct var *vp; - struct var **vpp; - - for (ip = varinit ; (vp = ip->var) != NULL ; ip++) { - if (find_var(ip->text, &vpp, &vp->name_len) != NULL) - continue; - vp->next = *vpp; - *vpp = vp; - vp->text = strdup(ip->text); - vp->flags = ip->flags; - vp->func = ip->func; - } - /* - * PS1 depends on uid - */ - if (find_var("PS1", &vpp, &vps1.name_len) == NULL) { - vps1.next = *vpp; - *vpp = &vps1; - vps1.flags = VSTRFIXED|VTEXTFIXED; - vps1.text = NULL; - choose_ps1(); - } -} - -void -choose_ps1(void) -{ - free(vps1.text); - vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# "); -} - -/* - * Safe version of setvar, returns 1 on success 0 on failure. - */ - -int -setvarsafe(const char *name, const char *val, int flags) -{ - struct jmploc jmploc; - struct jmploc *volatile savehandler = handler; - int volatile err = 0; - - if (setjmp(jmploc.loc)) - err = 1; - else { - handler = &jmploc; - setvar(name, val, flags); - } - handler = savehandler; - return err; -} - -/* - * Set the value of a variable. The flags argument is ored with the - * flags of the variable. If val is NULL, the variable is unset. - */ - -void -setvar(const char *name, const char *val, int flags) -{ - const char *p; - const char *q; - char *d; - int len; - int namelen; - char *nameeq; - int isbad; - - isbad = 0; - p = name; - if (! is_name(*p)) - isbad = 1; - p++; - for (;;) { - if (! is_in_name(*p)) { - if (*p == '\0' || *p == '=') - break; - isbad = 1; - } - p++; - } - namelen = p - name; - if (isbad) - error("%.*s: bad variable name", namelen, name); - len = namelen + 2; /* 2 is space for '=' and '\0' */ - if (val == NULL) { - flags |= VUNSET; - } else { - len += strlen(val); - } - d = nameeq = ckmalloc(len); - q = name; - while (--namelen >= 0) - *d++ = *q++; - *d++ = '='; - *d = '\0'; - if (val) - scopy(val, d); - setvareq(nameeq, flags); -} - - - -/* - * Same as setvar except that the variable and value are passed in - * the first argument as name=value. Since the first argument will - * be actually stored in the table, it should not be a string that - * will go away. - */ - -void -setvareq(char *s, int flags) -{ - struct var *vp, **vpp; - int nlen; - - if (aflag) - flags |= VEXPORT; - vp = find_var(s, &vpp, &nlen); - if (vp != NULL) { - if (vp->flags & VREADONLY) - error("%.*s: is read only", vp->name_len, s); - if (flags & VNOSET) - return; - INTOFF; - - if (vp->func && (flags & VNOFUNC) == 0) - (*vp->func)(s + vp->name_len + 1); - - if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0) - ckfree(vp->text); - - vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET); - vp->flags |= flags & ~VNOFUNC; - vp->text = s; - - /* - * We could roll this to a function, to handle it as - * a regular variable function callback, but why bother? - */ - if (vp == &vmpath || (vp == &vmail && ! mpathset())) - chkmail(1); - INTON; - return; - } - /* not found */ - if (flags & VNOSET) - return; - vp = ckmalloc(sizeof (*vp)); - vp->flags = flags & ~VNOFUNC; - vp->text = s; - vp->name_len = nlen; - vp->next = *vpp; - vp->func = NULL; - *vpp = vp; -} - - - -/* - * Process a linked list of variable assignments. - */ - -void -listsetvar(struct strlist *list, int flags) -{ - struct strlist *lp; - - INTOFF; - for (lp = list ; lp ; lp = lp->next) { - setvareq(savestr(lp->text), flags); - } - INTON; -} - -void -listmklocal(struct strlist *list, int flags) -{ - struct strlist *lp; - - for (lp = list ; lp ; lp = lp->next) - mklocal(lp->text, flags); -} - - -/* - * Find the value of a variable. Returns NULL if not set. - */ - -char * -lookupvar(const char *name) -{ - struct var *v; - - v = find_var(name, NULL, NULL); - if (v == NULL || v->flags & VUNSET) - return NULL; - return v->text + v->name_len + 1; -} - - - -/* - * Search the environment of a builtin command. If the second argument - * is nonzero, return the value of a variable even if it hasn't been - * exported. - */ - -char * -bltinlookup(const char *name, int doall) -{ - struct strlist *sp; - struct var *v; - - for (sp = cmdenviron ; sp ; sp = sp->next) { - if (strequal(sp->text, name)) - return strchr(sp->text, '=') + 1; - } - - v = find_var(name, NULL, NULL); - - if (v == NULL || v->flags & VUNSET || (!doall && !(v->flags & VEXPORT))) - return NULL; - return v->text + v->name_len + 1; -} - - - -/* - * Generate a list of exported variables. This routine is used to construct - * the third argument to execve when executing a program. - */ - -char ** -environment(void) -{ - int nenv; - struct var **vpp; - struct var *vp; - char **env; - char **ep; - - nenv = 0; - for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { - for (vp = *vpp ; vp ; vp = vp->next) - if (vp->flags & VEXPORT) - nenv++; - } - ep = env = stalloc((nenv + 1) * sizeof *env); - for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { - for (vp = *vpp ; vp ; vp = vp->next) - if (vp->flags & VEXPORT) - *ep++ = vp->text; - } - *ep = NULL; - return env; -} - - -/* - * Called when a shell procedure is invoked to clear out nonexported - * variables. It is also necessary to reallocate variables of with - * VSTACK set since these are currently allocated on the stack. - */ - -#ifdef mkinit -void shprocvar(void); - -SHELLPROC { - shprocvar(); -} -#endif - -void -shprocvar(void) -{ - struct var **vpp; - struct var *vp, **prev; - - for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { - for (prev = vpp ; (vp = *prev) != NULL ; ) { - if ((vp->flags & VEXPORT) == 0) { - *prev = vp->next; - if ((vp->flags & VTEXTFIXED) == 0) - ckfree(vp->text); - if ((vp->flags & VSTRFIXED) == 0) - ckfree(vp); - } else { - if (vp->flags & VSTACK) { - vp->text = savestr(vp->text); - vp->flags &=~ VSTACK; - } - prev = &vp->next; - } - } - } - initvar(); -} - - - -/* - * Command to list all variables which are set. Currently this command - * is invoked from the set command when the set command is called without - * any variables. - */ - -void -print_quoted(const char *p) -{ - const char *q; - - if (strcspn(p, "|&;<>()$`\\\"' \t\n*?[]#~=%") == strlen(p)) { - out1fmt("%s", p); - return; - } - while (*p) { - if (*p == '\'') { - out1fmt("\\'"); - p++; - continue; - } - q = strchr(p, '\''); - if (!q) { - out1fmt("'%s'", p ); - return; - } - out1fmt("'%.*s'", (int)(q - p), p ); - p = q; - } -} - -static int -sort_var(const void *v_v1, const void *v_v2) -{ - const struct var * const *v1 = v_v1; - const struct var * const *v2 = v_v2; - - /* XXX Will anyone notice we include the '=' of the shorter name? */ - return strcoll((*v1)->text, (*v2)->text); -} - -/* - * POSIX requires that 'set' (but not export or readonly) output the - * variables in lexicographic order - by the locale's collating order (sigh). - * Maybe we could keep them in an ordered balanced binary tree - * instead of hashed lists. - * For now just roll 'em through qsort for printing... - */ - -int -showvars(const char *name, int flag, int show_value) -{ - struct var **vpp; - struct var *vp; - const char *p; - - static struct var **list; /* static in case we are interrupted */ - static int list_len; - int count = 0; - - if (!list) { - list_len = 32; - list = ckmalloc(list_len * sizeof *list); - } - - for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { - for (vp = *vpp ; vp ; vp = vp->next) { - if (flag && !(vp->flags & flag)) - continue; - if (vp->flags & VUNSET && !(show_value & 2)) - continue; - if (count >= list_len) { - list = ckrealloc(list, - (list_len << 1) * sizeof *list); - list_len <<= 1; - } - list[count++] = vp; - } - } - - qsort(list, count, sizeof *list, sort_var); - - for (vpp = list; count--; vpp++) { - vp = *vpp; - if (name) - out1fmt("%s ", name); - for (p = vp->text ; *p != '=' ; p++) - out1c(*p); - if (!(vp->flags & VUNSET) && show_value) { - out1fmt("="); - print_quoted(++p); - } - out1c('\n'); - } - return 0; -} - - - -/* - * The export and readonly commands. - */ - -int -exportcmd(int argc, char **argv) -{ - struct var *vp; - char *name; - const char *p; - int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT; - int pflg; - - pflg = nextopt("p") == 'p' ? 3 : 0; - if (argc <= 1 || pflg) { - showvars( pflg ? argv[0] : 0, flag, pflg ); - return 0; - } - - while ((name = *argptr++) != NULL) { - if ((p = strchr(name, '=')) != NULL) { - p++; - } else { - vp = find_var(name, NULL, NULL); - if (vp != NULL) { - vp->flags |= flag; - continue; - } - } - setvar(name, p, flag); - } - return 0; -} - - -/* - * The "local" command. - */ - -int -localcmd(int argc, char **argv) -{ - char *name; - - if (! in_function()) - error("Not in a function"); - while ((name = *argptr++) != NULL) { - mklocal(name, 0); - } - return 0; -} - - -/* - * Make a variable a local variable. When a variable is made local, its - * value and flags are saved in a localvar structure. The saved values - * will be restored when the shell function returns. We handle the name - * "-" as a special case. - */ - -void -mklocal(const char *name, int flags) -{ - struct localvar *lvp; - struct var **vpp; - struct var *vp; - - INTOFF; - lvp = ckmalloc(sizeof (struct localvar)); - if (name[0] == '-' && name[1] == '\0') { - char *p; - p = ckmalloc(sizeof_optlist); - lvp->text = memcpy(p, optlist, sizeof_optlist); - vp = NULL; - } else { - vp = find_var(name, &vpp, NULL); - if (vp == NULL) { - if (strchr(name, '=')) - setvareq(savestr(name), VSTRFIXED|flags); - else - setvar(name, NULL, VSTRFIXED|flags); - vp = *vpp; /* the new variable */ - lvp->text = NULL; - lvp->flags = VUNSET; - } else { - lvp->text = vp->text; - lvp->flags = vp->flags; - vp->flags |= VSTRFIXED|VTEXTFIXED; - if (name[vp->name_len] == '=') - setvareq(savestr(name), flags); - } - } - lvp->vp = vp; - lvp->next = localvars; - localvars = lvp; - INTON; -} - - -/* - * Called after a function returns. - */ - -void -poplocalvars(void) -{ - struct localvar *lvp; - struct var *vp; - - while ((lvp = localvars) != NULL) { - localvars = lvp->next; - vp = lvp->vp; - TRACE(("poplocalvar %s", vp ? vp->text : "-")); - if (vp == NULL) { /* $- saved */ - memcpy(optlist, lvp->text, sizeof_optlist); - ckfree(lvp->text); - } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { - (void)unsetvar(vp->text, 0); - } else { - if (vp->func && (vp->flags & VNOFUNC) == 0) - (*vp->func)(lvp->text + vp->name_len + 1); - if ((vp->flags & VTEXTFIXED) == 0) - ckfree(vp->text); - vp->flags = lvp->flags; - vp->text = lvp->text; - } - ckfree(lvp); - } -} - - -int -setvarcmd(int argc, char **argv) -{ - if (argc <= 2) - return unsetcmd(argc, argv); - else if (argc == 3) - setvar(argv[1], argv[2], 0); - else - error("List assignment not implemented"); - return 0; -} - - -/* - * The unset builtin command. We unset the function before we unset the - * variable to allow a function to be unset when there is a readonly variable - * with the same name. - */ - -int -unsetcmd(int argc, char **argv) -{ - char **ap; - int i; - int flg_func = 0; - int flg_var = 0; - int ret = 0; - - while ((i = nextopt("evf")) != '\0') { - if (i == 'f') - flg_func = 1; - else - flg_var = i; - } - if (flg_func == 0 && flg_var == 0) - flg_var = 1; - - for (ap = argptr; *ap ; ap++) { - if (flg_func) - ret |= unsetfunc(*ap); - if (flg_var) - ret |= unsetvar(*ap, flg_var == 'e'); - } - return ret; -} - - -/* - * Unset the specified variable. - */ - -int -unsetvar(const char *s, int unexport) -{ - struct var **vpp; - struct var *vp; - - vp = find_var(s, &vpp, NULL); - if (vp == NULL) - return 0; - - if (vp->flags & VREADONLY) - return 1; - - INTOFF; - if (unexport) { - vp->flags &= ~VEXPORT; - } else { - if (vp->text[vp->name_len + 1] != '\0') - setvar(s, nullstr, 0); - vp->flags &= ~VEXPORT; - vp->flags |= VUNSET; - if ((vp->flags & VSTRFIXED) == 0) { - if ((vp->flags & VTEXTFIXED) == 0) - ckfree(vp->text); - *vpp = vp->next; - ckfree(vp); - } - } - INTON; - return 0; -} - - -/* - * Returns true if the two strings specify the same varable. The first - * variable name is terminated by '='; the second may be terminated by - * either '=' or '\0'. - */ - -STATIC int -strequal(const char *p, const char *q) -{ - while (*p == *q++) { - if (*p++ == '=') - return 1; - } - if (*p == '=' && *(q - 1) == '\0') - return 1; - return 0; -} - -/* - * Search for a variable. - * 'name' may be terminated by '=' or a NUL. - * vppp is set to the pointer to vp, or the list head if vp isn't found - * lenp is set to the number of charactets in 'name' - */ - -STATIC struct var * -find_var(const char *name, struct var ***vppp, int *lenp) -{ - unsigned int hashval; - int len; - struct var *vp, **vpp; - const char *p = name; - - hashval = 0; - while (*p && *p != '=') - hashval = 2 * hashval + (unsigned char)*p++; - len = p - name; - - if (lenp) - *lenp = len; - vpp = &vartab[hashval % VTABSIZE]; - if (vppp) - *vppp = vpp; - - for (vp = *vpp ; vp ; vpp = &vp->next, vp = *vpp) { - if (vp->name_len != len) - continue; - if (memcmp(vp->text, name, len) != 0) - continue; - if (vppp) - *vppp = vpp; - return vp; - } - return NULL; -} diff --git a/bin/sh/var.h b/bin/sh/var.h deleted file mode 100644 index 53708d558..000000000 --- a/bin/sh/var.h +++ /dev/null @@ -1,130 +0,0 @@ -/* $NetBSD: var.h,v 1.26 2015/05/26 21:35:15 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Kenneth Almquist. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)var.h 8.2 (Berkeley) 5/4/95 - */ - -/* - * Shell variables. - */ - -/* flags */ -#define VEXPORT 0x01 /* variable is exported */ -#define VREADONLY 0x02 /* variable cannot be modified */ -#define VSTRFIXED 0x04 /* variable struct is statically allocated */ -#define VTEXTFIXED 0x08 /* text is statically allocated */ -#define VSTACK 0x10 /* text is allocated on the stack */ -#define VUNSET 0x20 /* the variable is not set */ -#define VNOFUNC 0x40 /* don't call the callback function */ -#define VNOSET 0x80 /* do not set variable - just readonly test */ - - -struct var { - struct var *next; /* next entry in hash list */ - int flags; /* flags are defined above */ - char *text; /* name=value */ - int name_len; /* length of name */ - void (*func)(const char *); - /* function to be called when */ - /* the variable gets set/unset */ -}; - - -struct localvar { - struct localvar *next; /* next local variable in list */ - struct var *vp; /* the variable that was made local */ - int flags; /* saved flags */ - char *text; /* saved text */ -}; - - -extern struct localvar *localvars; - -#if ATTY -extern struct var vatty; -#endif -extern struct var vifs; -extern struct var vmail; -extern struct var vmpath; -extern struct var vpath; -extern struct var vps1; -extern struct var vps2; -extern struct var vps4; -#ifndef SMALL -extern struct var vterm; -extern struct var vtermcap; -extern struct var vhistsize; -#endif - -/* - * The following macros access the values of the above variables. - * They have to skip over the name. They return the null string - * for unset variables. - */ - -#define ifsval() (vifs.text + 4) -#define ifsset() ((vifs.flags & VUNSET) == 0) -#define mailval() (vmail.text + 5) -#define mpathval() (vmpath.text + 9) -#define pathval() (vpath.text + 5) -#define ps1val() (vps1.text + 4) -#define ps2val() (vps2.text + 4) -#define ps4val() (vps4.text + 4) -#define optindval() (voptind.text + 7) -#ifndef SMALL -#define histsizeval() (vhistsize.text + 9) -#define termval() (vterm.text + 5) -#endif - -#if ATTY -#define attyset() ((vatty.flags & VUNSET) == 0) -#endif -#define mpathset() ((vmpath.flags & VUNSET) == 0) - -void initvar(void); -void setvar(const char *, const char *, int); -void setvareq(char *, int); -struct strlist; -void listsetvar(struct strlist *, int); -char *lookupvar(const char *); -char *bltinlookup(const char *, int); -char **environment(void); -void shprocvar(void); -int showvars(const char *, int, int); -void mklocal(const char *, int); -void listmklocal(struct strlist *, int); -void poplocalvars(void); -int unsetvar(const char *, int); -void choose_ps1(void); -int setvarsafe(const char *, const char *, int); -void print_quoted(const char *); diff --git a/bin/sleep/Makefile b/bin/sleep/Makefile deleted file mode 100644 index 917f95f3d..000000000 --- a/bin/sleep/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $NetBSD: Makefile,v 1.9 1997/08/04 01:13:07 perry Exp $ -# @(#)Makefile 8.1 (Berkeley) 5/31/93 - -PROG= sleep -LDADD+= -lm -DPADD+= ${LIBM} - -.include diff --git a/bin/sleep/sleep.1 b/bin/sleep/sleep.1 deleted file mode 100644 index c7345c5e5..000000000 --- a/bin/sleep/sleep.1 +++ /dev/null @@ -1,128 +0,0 @@ -.\" $NetBSD: sleep.1,v 1.23 2016/08/12 02:36:38 sevan Exp $ -.\" -.\" Copyright (c) 1990, 1993, 1994 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Institute of Electrical and Electronics Engineers, Inc. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)sleep.1 8.3 (Berkeley) 4/18/94 -.\" -.Dd August 12, 2016 -.Dt SLEEP 1 -.Os -.Sh NAME -.Nm sleep -.Nd suspend execution for an interval of time -.Sh SYNOPSIS -.Nm -.Ar seconds -.Sh DESCRIPTION -The -.Nm -utility -suspends execution for a minimum of -.Ar seconds . -It is usually used to schedule the execution of other commands (see -.Sx EXAMPLES -below). -.Pp -Note: The -.Nx -.Nm -command will accept and honor a non-integer number of specified seconds. -This is a non-portable extension, and its use will nearly guarantee that -a shell script will not execute properly on another system. -.Pp -When the -.Dv SIGINFO -signal is received, the estimate of the amount of seconds left to -sleep is printed on the standard output. -.Sh EXIT STATUS -The -.Nm -utility exits with one of the following values: -.Bl -tag -width flag -.It Li \&0 -On successful completion, or if the signal -.Dv SIGALRM -was received. -.It Li \&\*[Gt]\&0 -An error occurred. -.El -.Sh EXAMPLES -To schedule the execution of a command for 1800 seconds later: -.Pp -.Dl (sleep 1800; sh command_file \*[Gt]\*[Am] errors)\*[Am] -.Pp -This incantation would wait half an hour before -running the script command_file. -(See the -.Xr at 1 -utility.) -.Pp -To reiteratively run a command (with -.Xr csh 1 ) : -.Pp -.Bd -literal -offset indent -compact -while (1) - if (! -r zzz.rawdata) then - sleep 300 - else - foreach i (*.rawdata) - sleep 70 - awk -f collapse_data $i \*[Gt]\*[Gt] results - end - break - endif -end -.Ed -.Pp -The scenario for a script such as this might be: a program currently -running is taking longer than expected to process a series of -files, and it would be nice to have -another program start processing the files created by the first -program as soon as it is finished (when zzz.rawdata is created). -The script checks every five minutes for the file zzz.rawdata, -when the file is found, then another portion processing -is done courteously by sleeping for 70 seconds in between each -awk job. -.Sh SEE ALSO -.Xr at 1 , -.Xr nanosleep 2 , -.Xr sleep 3 -.Sh STANDARDS -The -.Nm -command is expected to be -.St -p1003.2 -compatible. -.Sh HISTORY -A -.Nm -utility appeared in -.At v4 . diff --git a/bin/sleep/sleep.c b/bin/sleep/sleep.c deleted file mode 100644 index 4349af439..000000000 --- a/bin/sleep/sleep.c +++ /dev/null @@ -1,159 +0,0 @@ -/* $NetBSD: sleep.c,v 1.24 2011/08/29 14:51:19 joerg Exp $ */ - -/* - * Copyright (c) 1988, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)sleep.c 8.3 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: sleep.c,v 1.24 2011/08/29 14:51:19 joerg Exp $"); -#endif -#endif /* not lint */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -__dead static void alarmhandle(int); -__dead static void usage(void); - -static volatile sig_atomic_t report_requested; -static void -report_request(int signo __unused) -{ - - report_requested = 1; -} - -int -main(int argc, char *argv[]) -{ - char *arg, *temp; - double fval, ival, val; - struct timespec ntime; - time_t original; - int ch, fracflag, rv; - - setprogname(argv[0]); - (void)setlocale(LC_ALL, ""); - - (void)signal(SIGALRM, alarmhandle); - - while ((ch = getopt(argc, argv, "")) != -1) - switch(ch) { - default: - usage(); - } - argc -= optind; - argv += optind; - - if (argc != 1) - usage(); - - /* - * Okay, why not just use atof for everything? Why bother - * checking if there is a fraction in use? Because the old - * sleep handled the full range of integers, that's why, and a - * double can't handle a large long. This is fairly useless - * given how large a number a double can hold on most - * machines, but now we won't ever have trouble. If you want - * 1000000000.9 seconds of sleep, well, that's your - * problem. Why use an isdigit() check instead of checking for - * a period? Because doing it this way means locales will be - * handled transparently by the atof code. - */ - fracflag = 0; - arg = *argv; - for (temp = arg; *temp != '\0'; temp++) - if (!isdigit((unsigned char)*temp)) - fracflag++; - - if (fracflag) { - val = atof(arg); - if (val <= 0) - usage(); - ival = floor(val); - fval = (1000000000 * (val-ival)); - ntime.tv_sec = ival; - ntime.tv_nsec = fval; - } - else { - ntime.tv_sec = atol(arg); - if (ntime.tv_sec <= 0) - return EXIT_SUCCESS; - ntime.tv_nsec = 0; - } - - original = ntime.tv_sec; - signal(SIGINFO, report_request); - while ((rv = nanosleep(&ntime, &ntime)) != 0) { - if (report_requested) { - /* Reporting does not bother with nanoseconds. */ - warnx("about %d second(s) left out of the original %d", - (int)ntime.tv_sec, (int)original); - report_requested = 0; - } else - break; - } - - if (rv == -1) - err(EXIT_FAILURE, "nanosleep failed"); - - return EXIT_SUCCESS; - /* NOTREACHED */ -} - -static void -usage(void) -{ - (void)fprintf(stderr, "usage: %s seconds\n", getprogname()); - exit(EXIT_FAILURE); - /* NOTREACHED */ -} - -/* ARGSUSED */ -static void -alarmhandle(int i) -{ - _exit(EXIT_SUCCESS); - /* NOTREACHED */ -} diff --git a/bin/stty/Makefile b/bin/stty/Makefile deleted file mode 100644 index 546ee3f26..000000000 --- a/bin/stty/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $NetBSD: Makefile,v 1.11 2012/04/04 10:59:44 joerg Exp $ -# @(#)Makefile 8.1 (Berkeley) 5/31/93 - -PROG= stty -SRCS= cchar.c gfmt.c key.c modes.c print.c stty.c - -CWARNFLAGS.clang+= -Wno-string-plus-int - -.include diff --git a/bin/stty/cchar.c b/bin/stty/cchar.c deleted file mode 100644 index ad88c760d..000000000 --- a/bin/stty/cchar.c +++ /dev/null @@ -1,148 +0,0 @@ -/* $NetBSD: cchar.c,v 1.16 2006/10/16 00:37:55 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)cchar.c 8.5 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: cchar.c,v 1.16 2006/10/16 00:37:55 christos Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include -#include -#include -#include - -#include "stty.h" -#include "extern.h" - -/* - * Special control characters. - * - * Cchars1 are the standard names, cchars2 are the old aliases. - * The first are displayed, but both are recognized on the - * command line. - */ -const struct cchar cchars1[] = { - { "discard", VDISCARD, CDISCARD }, - { "dsusp", VDSUSP, CDSUSP }, - { "eof", VEOF, CEOF }, - { "eol", VEOL, CEOL }, - { "eol2", VEOL2, CEOL }, - { "erase", VERASE, CERASE }, - { "intr", VINTR, CINTR }, - { "kill", VKILL, CKILL }, - { "lnext", VLNEXT, CLNEXT }, - { "min", VMIN, CMIN }, - { "quit", VQUIT, CQUIT }, - { "reprint", VREPRINT, CREPRINT }, - { "start", VSTART, CSTART }, - { "status", VSTATUS, CSTATUS }, - { "stop", VSTOP, CSTOP }, - { "susp", VSUSP, CSUSP }, - { "time", VTIME, CTIME }, - { "werase", VWERASE, CWERASE }, - { .name = NULL }, -}; - -const struct cchar cchars2[] = { - { "brk", VEOL, CEOL }, - { "flush", VDISCARD, CDISCARD }, - { "rprnt", VREPRINT, CREPRINT }, - { .name = NULL }, -}; - -static int c_cchar(const void *, const void *); - -static int -c_cchar(const void *a, const void *b) -{ - return (strcmp(((const struct cchar *)a)->name, - ((const struct cchar *)b)->name)); -} - -int -csearch(char ***argvp, struct info *ip) -{ - struct cchar *cp, tmp; - long val; - char *arg, *ep, *name; - - name = **argvp; - - tmp.name = name; - if (!(cp = (struct cchar *)bsearch(&tmp, cchars1, - sizeof(cchars1)/sizeof(cchars1[0]) - 1, sizeof(cchars1[0]), - c_cchar)) && - !(cp = (struct cchar *)bsearch(&tmp, cchars2, - sizeof(cchars2)/sizeof(cchars2[0]) - 1, sizeof(cchars2[0]), - c_cchar))) - return (0); - - arg = *++*argvp; - if (!arg) { - warnx("option requires an argument -- %s", name); - usage(); - } - -#define CHK(s) (*arg == s[0] && !strcmp(arg, s)) - if (CHK("undef") || CHK("")) - ip->t.c_cc[cp->sub] = _POSIX_VDISABLE; - else if (cp->sub == VMIN || cp->sub == VTIME) { - val = strtol(arg, &ep, 10); - if (val == _POSIX_VDISABLE) { - warnx("value of %ld would disable the option -- %s", - val, name); - usage(); - } - if (val > UCHAR_MAX) { - warnx("maximum option value is %d -- %s", - UCHAR_MAX, name); - usage(); - } - if (*ep != '\0') { - warnx("option requires a numeric argument -- %s", name); - usage(); - } - ip->t.c_cc[cp->sub] = (cc_t)val; - } else if (arg[0] == '^') - ip->t.c_cc[cp->sub] = (arg[1] == '?') ? 0177 : - (arg[1] == '-') ? _POSIX_VDISABLE : arg[1] & 037; - else - ip->t.c_cc[cp->sub] = arg[0]; - ip->set = 1; - return (1); -} diff --git a/bin/stty/extern.h b/bin/stty/extern.h deleted file mode 100644 index 92598eb43..000000000 --- a/bin/stty/extern.h +++ /dev/null @@ -1,51 +0,0 @@ -/* $NetBSD: extern.h,v 1.13 2013/09/12 19:47:23 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)extern.h 8.1 (Berkeley) 5/31/93 - */ - -#ifndef _EXTERN_H_ -#define _EXTERN_H_ - -int c_cchars(const void *, const void *); -int c_modes(const void *, const void *); -int csearch(char ***, struct info *); -void checkredirect(void); -void gprint(struct termios *); -void gread(struct termios *, char *); -int ksearch(char ***, struct info *); -int msearch(char ***, struct info *); -void optlist(void); -void print(struct termios *, struct winsize *, int, const char *, enum FMT); -__dead void usage(void); - -extern const struct cchar cchars1[], cchars2[]; - -#endif /* !_EXTERN_H_ */ diff --git a/bin/stty/gfmt.c b/bin/stty/gfmt.c deleted file mode 100644 index 55ec0c285..000000000 --- a/bin/stty/gfmt.c +++ /dev/null @@ -1,132 +0,0 @@ -/* $NetBSD: gfmt.c,v 1.17 2011/08/29 14:51:19 joerg Exp $ */ - -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)gfmt.c 8.6 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: gfmt.c,v 1.17 2011/08/29 14:51:19 joerg Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include -#include - -#include "stty.h" -#include "extern.h" - -__dead static void gerr(char *); - -static void -gerr(char *s) -{ - if (s) - errx(1, "illegal gfmt1 option -- %s", s); - else - errx(1, "illegal gfmt1 option"); -} - -void -gprint(struct termios *tp) -{ - const struct cchar *cp; - - (void)printf("gfmt1:cflag=%x:iflag=%x:lflag=%x:oflag=%x:", - tp->c_cflag, tp->c_iflag, tp->c_lflag, tp->c_oflag); - for (cp = cchars1; cp->name; ++cp) - (void)printf("%s=%x:", cp->name, tp->c_cc[cp->sub]); - (void)printf("ispeed=%d:ospeed=%d\n", cfgetispeed(tp), cfgetospeed(tp)); -} - -void -gread(struct termios *tp, char *s) -{ - const struct cchar *cp; - char *ep, *p; - long tmp; - - if ((s = strchr(s, ':')) == NULL) - gerr(NULL); - for (++s; s != NULL;) { - p = strsep(&s, ":\0"); - if (!p || !*p) - break; - if (!(ep = strchr(p, '='))) - gerr(p); - *ep++ = '\0'; - (void)sscanf(ep, "%lx", &tmp); - -#define CHK(s) (*p == s[0] && !strcmp(p, s)) - if (CHK("cflag")) { - tp->c_cflag = tmp; - continue; - } - if (CHK("iflag")) { - tp->c_iflag = tmp; - continue; - } -#ifdef BSD4_4 - if (CHK("ispeed")) { - (void)sscanf(ep, "%ld", &tmp); - tp->c_ispeed = tmp; - continue; - } -#endif - if (CHK("lflag")) { - tp->c_lflag = tmp; - continue; - } - if (CHK("oflag")) { - tp->c_oflag = tmp; - continue; - } -#ifdef BSD4_4 - if (CHK("ospeed")) { - (void)sscanf(ep, "%ld", &tmp); - tp->c_ospeed = tmp; - continue; - } -#endif - for (cp = cchars1; cp->name != NULL; ++cp) - if (CHK(cp->name)) { - if (cp->sub == VMIN || cp->sub == VTIME) - (void)sscanf(ep, "%ld", &tmp); - tp->c_cc[cp->sub] = tmp; - break; - } - if (cp->name == NULL) - gerr(p); - } -} diff --git a/bin/stty/key.c b/bin/stty/key.c deleted file mode 100644 index 0094d3b35..000000000 --- a/bin/stty/key.c +++ /dev/null @@ -1,332 +0,0 @@ -/* $NetBSD: key.c,v 1.22 2017/01/10 20:44:05 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)key.c 8.4 (Berkeley) 2/20/95"; -#else -__RCSID("$NetBSD: key.c,v 1.22 2017/01/10 20:44:05 christos Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "stty.h" -#include "extern.h" - -__BEGIN_DECLS -void f_all(struct info *); -void f_cbreak(struct info *); -void f_columns(struct info *); -void f_dec(struct info *); -void f_everything(struct info *); -void f_extproc(struct info *); -void f_insane(struct info *); -void f_ispeed(struct info *); -void f_nl(struct info *); -void f_ospeed(struct info *); -void f_raw(struct info *); -void f_rows(struct info *); -void f_sane(struct info *); -void f_size(struct info *); -void f_speed(struct info *); -void f_ostart(struct info *); -void f_ostop(struct info *); -void f_tty(struct info *); -__END_DECLS - -static const struct key { - const char *name; /* name */ - void (*f)(struct info *); /* function */ -#define F_NEEDARG 0x01 /* needs an argument */ -#define F_OFFOK 0x02 /* can turn off */ - int flags; -} keys[] = { - { "all", f_all, 0 }, - { "cbreak", f_cbreak, F_OFFOK }, - { "cols", f_columns, F_NEEDARG }, - { "columns", f_columns, F_NEEDARG }, - { "cooked", f_sane, 0 }, - { "dec", f_dec, 0 }, - { "everything", f_everything, 0 }, - { "extproc", f_extproc, F_OFFOK }, - { "insane", f_insane, 0 }, - { "ispeed", f_ispeed, F_NEEDARG }, - { "new", f_tty, 0 }, - { "nl", f_nl, F_OFFOK }, - { "old", f_tty, 0 }, - { "ospeed", f_ospeed, F_NEEDARG }, - { "ostart", f_ostart, 0 }, - { "ostop", f_ostop, 0 }, - { "raw", f_raw, F_OFFOK }, - { "rows", f_rows, F_NEEDARG }, - { "sane", f_sane, 0 }, - { "size", f_size, 0 }, - { "speed", f_speed, 0 }, - { "tty", f_tty, 0 }, -}; - -static int c_key(const void *, const void *); - -static int -c_key(const void *a, const void *b) -{ - - return (strcmp(((const struct key *)a)->name, - ((const struct key *)b)->name)); -} - -int -ksearch(char ***argvp, struct info *ip) -{ - char *name; - struct key *kp, tmp; - - name = **argvp; - if (*name == '-') { - ip->off = 1; - ++name; - } else - ip->off = 0; - - tmp.name = name; - if (!(kp = (struct key *)bsearch(&tmp, keys, - sizeof(keys)/sizeof(struct key), sizeof(struct key), c_key))) - return (0); - if (!(kp->flags & F_OFFOK) && ip->off) { - warnx("illegal option -- %s", name); - usage(); - } - if (kp->flags & F_NEEDARG && !(ip->arg = *++*argvp)) { - warnx("option requires an argument -- %s", name); - usage(); - } - kp->f(ip); - return (1); -} - -void -f_all(struct info *ip) -{ - print(&ip->t, &ip->win, ip->queue, ip->ldisc, STTY_BSD); -} - -void -f_cbreak(struct info *ip) -{ - if (ip->off) - f_sane(ip); - else { - ip->t.c_iflag |= BRKINT|IXON|IMAXBEL; - ip->t.c_oflag |= OPOST; - ip->t.c_lflag |= ISIG|IEXTEN; - ip->t.c_lflag &= ~ICANON; - ip->set = 1; - } -} - -void -f_columns(struct info *ip) -{ - ip->win.ws_col = atoi(ip->arg); - ip->wset = 1; -} - -void -f_dec(struct info *ip) -{ - ip->t.c_cc[VERASE] = (u_char)0177; - ip->t.c_cc[VKILL] = CTRL('u'); - ip->t.c_cc[VINTR] = CTRL('c'); - ip->t.c_lflag &= ~ECHOPRT; - ip->t.c_lflag |= ECHOE|ECHOKE|ECHOCTL; - ip->t.c_iflag &= ~IXANY; - ip->set = 1; -} - -void -f_everything(struct info *ip) -{ - print(&ip->t, &ip->win, ip->queue, ip->ldisc, STTY_BSD); -} - -void -f_extproc(struct info *ip) -{ -#ifdef TIOCEXT - if (ip->off) { - int tmp = 0; - (void)ioctl(ip->fd, TIOCEXT, &tmp); - } else { - int tmp = 1; - (void)ioctl(ip->fd, TIOCEXT, &tmp); - } - ip->set = 1; -#endif -} - -void -f_insane(struct info *ip) -{ - int f, r; - - r = f = open(_PATH_URANDOM, O_RDONLY, 0); - if (f >= 0) { - r = read(f, &(ip->t), sizeof(struct termios)); - close(f); - } - if (r < 0) { - /* XXX not cryptographically secure! */ - - srandom(time(NULL)); - ip->t.c_iflag = random(); - ip->t.c_oflag = random(); - ip->t.c_cflag = random(); - ip->t.c_lflag = random(); - for (f = 0; f < NCCS; f++) { - ip->t.c_cc[f] = random() & 0xFF; - } - ip->t.c_ispeed = random(); - ip->t.c_ospeed = random(); - } - - ip->set = 1; -} - -void -f_ispeed(struct info *ip) -{ - cfsetispeed(&ip->t, atoi(ip->arg)); - ip->set = 1; -} - -void -f_nl(struct info *ip) -{ - if (ip->off) { - ip->t.c_iflag |= ICRNL; - ip->t.c_oflag |= ONLCR; - } else { - ip->t.c_iflag &= ~ICRNL; - ip->t.c_oflag &= ~ONLCR; - } - ip->set = 1; -} - -void -f_ospeed(struct info *ip) -{ - cfsetospeed(&ip->t, atoi(ip->arg)); - ip->set = 1; -} - -void -f_raw(struct info *ip) -{ - if (ip->off) - f_sane(ip); - else { - cfmakeraw(&ip->t); - ip->t.c_cflag &= ~(CSIZE|PARENB); - ip->t.c_cflag |= CS8; - ip->set = 1; - } -} - -void -f_rows(struct info *ip) -{ - ip->win.ws_row = atoi(ip->arg); - ip->wset = 1; -} - -void -f_sane(struct info *ip) -{ - ip->t.c_cflag = TTYDEF_CFLAG | (ip->t.c_cflag & (CLOCAL|CRTSCTS|CDTRCTS)); - ip->t.c_iflag = TTYDEF_IFLAG; - ip->t.c_iflag |= ICRNL; - /* preserve user-preference flags in lflag */ -#define LKEEP (ECHOKE|ECHOE|ECHOK|ECHOPRT|ECHOCTL|ALTWERASE|TOSTOP|NOFLSH) - ip->t.c_lflag = TTYDEF_LFLAG | (ip->t.c_lflag & LKEEP); - ip->t.c_oflag = TTYDEF_OFLAG; - ip->set = 1; -} - -void -f_size(struct info *ip) -{ - (void)printf("%d %d\n", ip->win.ws_row, ip->win.ws_col); -} - -void -f_speed(struct info *ip) -{ - (void)printf("%d\n", cfgetospeed(&ip->t)); -} - -/* ARGSUSED */ -void -f_tty(struct info *ip) -{ -#ifdef TTYDISC - int tmp; - - tmp = TTYDISC; - if (ioctl(0, TIOCSETD, &tmp) < 0) - err(1, "TIOCSETD"); -#endif -} - -void -f_ostart(struct info *ip) -{ - if (ioctl (0, TIOCSTART) < 0) - err(1, "TIOCSTART"); -} - -void -f_ostop(struct info *ip) -{ - if (ioctl (0, TIOCSTOP) < 0) - err(1, "TIOCSTOP"); -} diff --git a/bin/stty/modes.c b/bin/stty/modes.c deleted file mode 100644 index a7877af80..000000000 --- a/bin/stty/modes.c +++ /dev/null @@ -1,224 +0,0 @@ -/* $NetBSD: modes.c,v 1.18 2015/05/01 17:01:08 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)modes.c 8.3 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: modes.c,v 1.18 2015/05/01 17:01:08 christos Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include -#include - -#include "stty.h" -#include "extern.h" - -struct modes { - const char *name; - tcflag_t flag; -}; - -struct specialmodes { - const char *name; - tcflag_t set; - tcflag_t unset; -}; - -/* - * The code in optlist() depends on minus options following regular - * options, i.e. "foo" must immediately precede "-foo". - */ -const struct modes cmodes[] = { - { "cstopb", CSTOPB }, - { "cread", CREAD }, - { "parenb", PARENB }, - { "parodd", PARODD }, - { "hupcl", HUPCL }, - { "hup", HUPCL }, - { "clocal", CLOCAL }, - { "crtscts", CRTSCTS }, - { "mdmbuf", MDMBUF }, - { "cdtrcts", CDTRCTS }, - { .name = NULL }, -}; - -const struct specialmodes cspecialmodes[] = { - { "cs5", CS5, CSIZE }, - { "cs6", CS6, CSIZE }, - { "cs7", CS7, CSIZE }, - { "cs8", CS8, CSIZE }, - { "parity", PARENB | CS7, PARODD | CSIZE }, - { "-parity", CS8, PARODD | PARENB | CSIZE }, - { "evenp", PARENB | CS7, PARODD | CSIZE }, - { "-evenp", CS8, PARODD | PARENB | CSIZE }, - { "oddp", PARENB | CS7 | PARODD, CSIZE }, - { "-oddp", CS8, PARODD | PARENB | CSIZE }, - { "pass8", CS8, PARODD | PARENB | CSIZE }, - { "-pass8", PARENB | CS7, PARODD | CSIZE }, - { .name = NULL }, -}; - -const struct modes imodes[] = { - { "ignbrk", IGNBRK }, - { "brkint", BRKINT }, - { "ignpar", IGNPAR }, - { "parmrk", PARMRK }, - { "inpck", INPCK }, - { "istrip", ISTRIP }, - { "inlcr", INLCR }, - { "igncr", IGNCR }, - { "icrnl", ICRNL }, - { "ixon", IXON }, - { "flow", IXON }, - { "ixoff", IXOFF }, - { "tandem", IXOFF }, - { "ixany", IXANY }, - { "imaxbel", IMAXBEL }, - { .name = NULL }, -}; - -const struct specialmodes ispecialmodes[] = { - { "decctlq", 0, IXANY }, - { "-decctlq", IXANY, 0 }, - { .name = NULL }, -}; - -const struct modes lmodes[] = { - { "echo", ECHO }, - { "echoe", ECHOE }, - { "crterase", ECHOE }, - { "crtbs", ECHOE }, /* crtbs not supported, close enough */ - { "echok", ECHOK }, - { "echoke", ECHOKE }, - { "crtkill", ECHOKE }, - { "altwerase", ALTWERASE }, - { "iexten", IEXTEN }, - { "echonl", ECHONL }, - { "echoctl", ECHOCTL }, - { "ctlecho", ECHOCTL }, - { "echoprt", ECHOPRT }, - { "prterase", ECHOPRT }, - { "isig", ISIG }, - { "icanon", ICANON }, - { "noflsh", NOFLSH }, - { "tostop", TOSTOP }, - { "flusho", FLUSHO }, - { "pendin", PENDIN }, - { "nokerninfo", NOKERNINFO }, - { .name = NULL }, -}; - -const struct specialmodes lspecialmodes[] = { - { "crt", ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT }, - { "-crt", ECHOK, ECHOE|ECHOKE|ECHOCTL }, - { "newcrt", ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT }, - { "-newcrt", ECHOK, ECHOE|ECHOKE|ECHOCTL }, - { "kerninfo", 0, NOKERNINFO }, - { "-kerninfo", NOKERNINFO, 0 }, - { .name = NULL }, -}; - -const struct modes omodes[] = { - { "opost", OPOST }, - { "onlcr", ONLCR }, - { "ocrnl", OCRNL }, - { "oxtabs", OXTABS }, - { "onocr", ONOCR }, - { "onlret", ONLRET }, - { .name = NULL }, -}; - -const struct specialmodes ospecialmodes[] = { - { "litout", 0, OPOST }, - { "-litout", OPOST, 0 }, - { "tabs", 0, OXTABS }, /* "preserve" tabs */ - { "-tabs", OXTABS, 0 }, - { .name = NULL }, -}; - -#define CHK(s) (!strcmp(name, s)) - -static int -modeset(const char *name, const struct modes *mp, - const struct specialmodes *smp, tcflag_t *f) -{ - bool neg; - - for (; smp->name; ++smp) - if (CHK(smp->name)) { - *f &= ~smp->unset; - *f |= smp->set; - return 1; - } - - if ((neg = (*name == '-'))) - name++; - - for (; mp->name; ++mp) - if (CHK(mp->name)) { - if (neg) - *f &= ~mp->flag; - else - *f |= mp->flag; - return 1; - } - - return 0; -} - -int -msearch(char ***argvp, struct info *ip) -{ - const char *name = **argvp; - - if (modeset(name, cmodes, cspecialmodes, &ip->t.c_cflag)) - goto out; - - if (modeset(name, imodes, ispecialmodes, &ip->t.c_iflag)) - goto out; - - if (modeset(name, lmodes, lspecialmodes, &ip->t.c_lflag)) - goto out; - - if (modeset(name, omodes, ospecialmodes, &ip->t.c_oflag)) - goto out; - - return 0; -out: - ip->set = 1; - return 1; -} diff --git a/bin/stty/print.c b/bin/stty/print.c deleted file mode 100644 index 6f2de1a58..000000000 --- a/bin/stty/print.c +++ /dev/null @@ -1,257 +0,0 @@ -/* $NetBSD: print.c,v 1.23 2013/09/12 19:47:23 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -#if 0 -static char sccsid[] = "@(#)print.c 8.6 (Berkeley) 4/16/94"; -#else -__RCSID("$NetBSD: print.c,v 1.23 2013/09/12 19:47:23 christos Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include -#include - -#include "stty.h" -#include "extern.h" - -static void binit(const char *); -static void bput(const char *); -static const char *ccval(const struct cchar *, int); - -void -print(struct termios *tp, struct winsize *wp, int queue, const char *ldisc, - enum FMT fmt) -{ - const struct cchar *p; - long tmp; - u_char *cc; - int cnt, ispeed, ospeed; - char buf1[100], buf2[100]; - - cnt = 0; - - /* Line speed. */ - ispeed = cfgetispeed(tp); - ospeed = cfgetospeed(tp); - if (ispeed != ospeed) - cnt += - printf("ispeed %d baud; ospeed %d baud;", ispeed, ospeed); - else - cnt += printf("speed %d baud;", ispeed); - if (fmt >= STTY_BSD) { - cnt += printf(" %d rows; %d columns;", wp->ws_row, wp->ws_col); - if (queue) - cnt += printf(" queue = %d;", queue); - if (ldisc) - cnt += printf(" line = %s;", ldisc); - } - - if (cnt) - (void)printf("\n"); - -#define on(f) ((tmp&f) != 0) -#define put(n, f, d) \ - if (fmt >= STTY_BSD || on(f) != d) \ - bput(n + on(f)); - - /* "local" flags */ - tmp = tp->c_lflag; - binit("lflags"); - put("-icanon", ICANON, 1); - put("-isig", ISIG, 1); - put("-iexten", IEXTEN, 1); - put("-echo", ECHO, 1); - put("-echoe", ECHOE, 0); - put("-echok", ECHOK, 0); - put("-echoke", ECHOKE, 0); - put("-echonl", ECHONL, 0); - put("-echoctl", ECHOCTL, 0); - put("-echoprt", ECHOPRT, 0); - put("-altwerase", ALTWERASE, 0); - put("-noflsh", NOFLSH, 0); - put("-tostop", TOSTOP, 0); - put("-flusho", FLUSHO, 0); - put("-pendin", PENDIN, 0); - put("-nokerninfo", NOKERNINFO, 0); - put("-extproc", EXTPROC, 0); - - /* input flags */ - tmp = tp->c_iflag; - binit("iflags"); - put("-istrip", ISTRIP, 0); - put("-icrnl", ICRNL, 1); - put("-inlcr", INLCR, 0); - put("-igncr", IGNCR, 0); - put("-ixon", IXON, 1); - put("-ixoff", IXOFF, 0); - put("-ixany", IXANY, 1); - put("-imaxbel", IMAXBEL, 1); - put("-ignbrk", IGNBRK, 0); - put("-brkint", BRKINT, 1); - put("-inpck", INPCK, 0); - put("-ignpar", IGNPAR, 0); - put("-parmrk", PARMRK, 0); - - /* output flags */ - tmp = tp->c_oflag; - binit("oflags"); - put("-opost", OPOST, 1); - put("-onlcr", ONLCR, 1); - put("-ocrnl", OCRNL, 0); - put("-oxtabs", OXTABS, 1); - put("-onocr", OXTABS, 0); - put("-onlret", OXTABS, 0); - - /* control flags (hardware state) */ - tmp = tp->c_cflag; - binit("cflags"); - put("-cread", CREAD, 1); - switch(tmp&CSIZE) { - case CS5: - bput("cs5"); - break; - case CS6: - bput("cs6"); - break; - case CS7: - bput("cs7"); - break; - case CS8: - bput("cs8"); - break; - } - bput("-parenb" + on(PARENB)); - put("-parodd", PARODD, 0); - put("-hupcl", HUPCL, 1); - put("-clocal", CLOCAL, 0); - put("-cstopb", CSTOPB, 0); - put("-crtscts", CRTSCTS, 0); - put("-mdmbuf", MDMBUF, 0); - put("-cdtrcts", CDTRCTS, 0); - - /* special control characters */ - cc = tp->c_cc; - if (fmt == STTY_POSIX) { - binit("cchars"); - for (p = cchars1; p->name; ++p) { - (void)snprintf(buf1, sizeof(buf1), "%s = %s;", - p->name, ccval(p, cc[p->sub])); - bput(buf1); - } - binit(NULL); - } else { - binit(NULL); - for (p = cchars1, cnt = 0; p->name; ++p) { - if (fmt != STTY_BSD && cc[p->sub] == p->def) - continue; -#define WD "%-8s" - (void)snprintf(buf1 + cnt * 8, 9, WD, p->name); - (void)snprintf(buf2 + cnt * 8, 9, WD, ccval(p, cc[p->sub])); - if (++cnt == LINELENGTH / 8) { - cnt = 0; - (void)printf("%s\n", buf1); - (void)printf("%s\n", buf2); - } - } - if (cnt) { - (void)printf("%s\n", buf1); - (void)printf("%s\n", buf2); - } - } -} - -static int col; -static const char *label; - -static void -binit(const char *lb) -{ - - if (col) { - (void)printf("\n"); - col = 0; - } - label = lb; -} - -static void -bput(const char *s) -{ - - if (col == 0) { - col = printf("%s: %s", label, s); - return; - } - if ((col + strlen(s)) > LINELENGTH) { - (void)printf("\n\t"); - col = printf("%s", s) + 8; - return; - } - col += printf(" %s", s); -} - -static const char * -ccval(const struct cchar *p, int c) -{ - static char buf[5]; - char *bp; - - if (c == _POSIX_VDISABLE) - return (""); - - if (p->sub == VMIN || p->sub == VTIME) { - (void)snprintf(buf, sizeof(buf), "%d", c); - return (buf); - } - bp = buf; - if (c & 0200) { - *bp++ = 'M'; - *bp++ = '-'; - c &= 0177; - } - if (c == 0177) { - *bp++ = '^'; - *bp++ = '?'; - } - else if (c < 040) { - *bp++ = '^'; - *bp++ = c + '@'; - } - else - *bp++ = c; - *bp = '\0'; - return (buf); -} diff --git a/bin/stty/stty.1 b/bin/stty/stty.1 deleted file mode 100644 index 637f31abc..000000000 --- a/bin/stty/stty.1 +++ /dev/null @@ -1,640 +0,0 @@ -.\" $NetBSD: stty.1,v 1.43 2016/08/14 23:29:43 sevan Exp $ -.\" -.\" Copyright (c) 1990, 1993, 1994 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Institute of Electrical and Electronics Engineers, Inc. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)stty.1 8.5 (Berkeley) 6/1/94 -.\" -.Dd August 15, 2016 -.Dt STTY 1 -.Os -.Sh NAME -.Nm stty -.Nd set options for a terminal device interface -.Sh SYNOPSIS -.Nm -.Op Fl a | Fl e | Fl g -.Op Fl f Ar file -.Op operand ... -.Sh DESCRIPTION -The -.Nm -utility sets or reports on terminal -characteristics for the device that is its standard input. -If no options or operands are specified, it reports the settings of a subset -of characteristics as well as additional ones if they differ from their -default values. -Otherwise it modifies -the terminal state according to the specified arguments. -Some combinations of arguments are mutually -exclusive on some terminal types. -.Pp -The following options are available: -.Bl -tag -width XfXfileXX -.It Fl a -Display all the current settings for the terminal to standard output -as per -.St -p1003.2 . -.It Fl e -Display all the current settings for the terminal to standard output -in the traditional -.Bx -.Dq all -and -.Dq everything -formats. -.It Fl f Ar file -Open and use the terminal named by -.Ar file -rather than using standard input. -The file is opened using the -.Dv O_NONBLOCK -flag of -.Fn open , -making it possible to -set or display settings on a terminal that might otherwise -block on the open. -.It Fl g -Display all the current settings for the terminal to standard output -in a form that may be used as an argument to a subsequent invocation of -.Nm -to restore the current terminal state as per -.St -p1003.2 . -.El -.Pp -The following arguments are available to set the terminal -characteristics: -.Ss Control Modes -Control mode flags affect hardware characteristics associated with the -terminal. -This corresponds to the -.Fa c_cflag -of the -.Xr termios 4 -structure. -.Bl -tag -width Fl -.It Cm parenb Pq Fl parenb -Enable (disable) parity generation -and detection. -.It Cm parodd Pq Fl parodd -Select odd (even) parity. -.It Cm cs5 cs6 cs7 cs8 -Select character size, if possible. -.It Ar number -Set terminal baud rate to -.Ar number , -if possible. -If the -baud rate is set to zero, modem -control is no longer -asserted. -.It Cm ispeed Ar number -Set terminal input baud rate to -.Ar number , -if possible. -If the -input baud rate is set to zero, the -input baud rate is set to the -value of the output baud -rate. -.It Cm ospeed Ar number -Set terminal output baud rate to -.Ar number , -if possible. -If -the output baud rate is set to -zero, modem control is -no longer asserted. -.It Cm speed Ar number -This sets both -.Cm ispeed -and -.Cm ospeed -to -.Ar number . -.It Cm hupcl Pq Fl hupcl -Stop asserting modem control -(do not stop asserting modem control) on last close. -.It Cm hup Pq Fl hup -Same as hupcl -.Pq Fl hupcl . -.It Cm cstopb Pq Fl cstopb -Use two (one) stop bits per character. -.It Cm cread Pq Fl cread -Enable (disable) the receiver. -.It Cm clocal Pq Fl clocal -Assume a line without (with) modem -control. -.It Cm crtscts Pq Fl crtscts -Enable RTS/CTS flow control. -.It Cm cdtrcts Pq Fl cdtrcts -Enable DTR/CTS flow control (if supported). -.El -.Ss Input Modes -This corresponds to the -.Fa c_iflag -of the -.Xr termios 4 -structure. -.Bl -tag -width Fl -.It Cm ignbrk Pq Fl ignbrk -Ignore (do not ignore) break on -input. -.It Cm brkint Pq Fl brkint -Signal (do not signal) -.Dv INTR -on -break. -.It Cm ignpar Pq Fl ignpar -Ignore (do not ignore) parity -errors. -.It Cm parmrk Pq Fl parmrk -Mark (do not mark) parity errors. -.It Cm inpck Pq Fl inpck -Enable (disable) input parity -checking. -.It Cm istrip Pq Fl istrip -Strip (do not strip) input characters -to seven bits. -.It Cm inlcr Pq Fl inlcr -Map (do not map) -.Dv NL -to -.Dv CR -on input. -.It Cm igncr Pq Fl igncr -Ignore (do not ignore) -.Dv CR -on input. -.It Cm icrnl Pq Fl icrnl -Map (do not map) -.Dv CR -to -.Dv NL -on input. -.It Cm ixon Pq Fl ixon -Enable (disable) -.Dv START/STOP -output -control. -Output from the system is -stopped when the system receives -.Dv STOP -and started when the system -receives -.Dv START , -or if -.Cm ixany -is set, any character restarts output. -.It Cm ixoff Pq Fl ixoff -Request that the system send (not -send) -.Dv START/STOP -characters when -the input queue is nearly -empty/full. -.It Cm ixany Pq Fl ixany -Allow any character (allow only -.Dv START ) -to restart output. -.It Cm imaxbel Pq Fl imaxbel -The system imposes a limit of -.Dv MAX_INPUT -(currently 255) characters in the input queue. -If -.Cm imaxbel -is set and the input queue limit has been reached, -subsequent input causes the system to send an ASCII BEL -character to the output queue (the terminal beeps at you). -Otherwise, -if -.Cm imaxbel -is unset and the input queue is full, the next input character causes -the entire input and output queues to be discarded. -.El -.Ss Output Modes -This corresponds to the -.Fa c_oflag -of the -.Xr termios 4 -structure. -.Bl -tag -width Fl -.It Cm opost Pq Fl opost -Post-process output (do not -post-process output; ignore all other -output modes). -.It Cm onlcr Pq Fl onlcr -Map (do not map) -.Dv NL -to -.Dv CR-NL -on output. -.It Cm ocrnl Pq Fl ocrnl -Map (do not map) -.Dv CR -to -.Dv NL -on output. -.It Cm oxtabs Pq Fl oxtabs -Expand (do not expand) tabs to spaces on output. -.It Cm onocr Pq Fl onocr -Do not (do) output CRs at column zero. -.It Cm onlret Pq Fl onlret -On the terminal NL performs (does not perform) the CR function. -.El -.Ss Local Modes -Local mode flags (lflags) affect various and sundry characteristics of terminal -processing. -Historically the term "local" pertained to new job control features -implemented by Jim Kulp on a -.Tn PDP Ns -11/70 -at -.Tn IIASA . -Later the driver ran on the first -.Tn VAX -at Evans Hall, UC Berkeley, where the job control details -were greatly modified but the structure definitions and names -remained essentially unchanged. -The second interpretation of the -.Sq l -in lflag -is -.Dq line discipline flag , -which corresponds to the -.Fa c_lflag -of the -.Xr termios 4 -structure. -.Bl -tag -width Fl -.It Cm isig Pq Fl isig -Enable (disable) the checking of -characters against the special control -characters -.Dv INTR , QUIT , -and -.Dv SUSP . -.It Cm icanon Pq Fl icanon -Enable (disable) canonical input -.Dv ( ERASE -and -.Dv KILL -processing). -.It Cm iexten Pq Fl iexten -Enable (disable) any implementation -defined special control characters -not currently controlled by icanon, -isig, or ixon. -.It Cm echo Pq Fl echo -Echo back (do not echo back) every -character typed. -.It Cm echoe Pq Fl echoe -The -.Dv ERASE -character shall (shall -not) visually erase the last character -in the current line from the -display, if possible. -.It Cm echok Pq Fl echok -Echo (do not echo) -.Dv NL -after -.Dv KILL -character. -.It Cm echoke Pq Fl echoke -The -.Dv KILL -character shall (shall -not) visually erase -the current line from the -display, if possible. -.It Cm echonl Pq Fl echonl -Echo (do not echo) -.Dv NL , -even if echo -is disabled. -.It Cm echoctl Pq Fl echoctl -If -.Cm echoctl -is set, echo control characters as ^X. -Otherwise control characters echo as themselves. -.It Cm echoprt Pq Fl echoprt -For printing terminals. -If set, echo erased characters backwards within -.Dq \e -and -.Dq / . -Otherwise, disable this feature. -.It Cm noflsh Pq Fl noflsh -Disable (enable) flush after -.Dv INTR , QUIT , SUSP . -.It Cm tostop Pq Fl tostop -Send (do not send) -.Dv SIGTTOU -for background output. -This causes background jobs to stop if they attempt terminal output. -.It Cm altwerase Pq Fl altwerase -Use (do not use) an alternative word erase algorithm when processing -.Dv WERASE -characters. -This alternative algorithm considers sequences of -alphanumeric/underscores as words. -It also skips the first preceding character in its classification -(as a convenience since the one preceding character could have been -erased with simply an -.Dv ERASE -character). -.It Cm mdmbuf Pq Fl mdmbuf -If set, flow control output based on condition of Carrier Detect. -Otherwise writes return an error if Carrier Detect is low (and Carrier -is not being ignored with the -.Dv CLOCAL -flag). -.It Cm flusho Pq Fl flusho -Indicates output is (is not) being discarded. -.It Cm pendin Pq Fl pendin -Indicates input is (is not) pending after a switch from non-canonical -to canonical mode and will be re-input when a read becomes pending -or more input arrives. -.El -.Ss Control Characters -.Bl -tag -width Fl -.It Ar control-character Ar string -Set -.Ar control-character -to string -.Ar string . -If the string is a single character, -then the control character is set to -that character. -If the string is the -two character sequence "^-" or the -string "undef", then the control character -is disabled (i.e., set to -.Bro Dv _POSIX_VDISABLE Brc ) . -.Pp -Recognized control characters: -.Bd -ragged -offset indent -.Bl -column character Subscript Description -.It control- Ta "" Ta "" -.It character Subscript Description -.It _________ _________ _______________ -.It eof Ta Tn VEOF Ta EOF No character -.It eol Ta Tn VEOL Ta EOL No character -.It eol2 Ta Tn VEOL2 Ta EOL2 No character -.It erase Ta Tn VERASE Ta ERASE No character -.It werase Ta Tn VWERASE Ta WERASE No character -.It kill Ta Tn VKILL Ta KILL No character -.It reprint Ta Tn VREPRINT Ta REPRINT No character -.It intr Ta Tn VINTR Ta INTR No character -.It quit Ta Tn VQUIT Ta QUIT No character -.It susp Ta Tn VSUSP Ta SUSP No character -.It dsusp Ta Tn VDSUSP Ta DSUSP No character -.It start Ta Tn VSTART Ta START No character -.It stop Ta Tn VSTOP Ta STOP No character -.It lnext Ta Tn VLNEXT Ta LNEXT No character -.It status Ta Tn VSTATUS Ta STATUS No character -.It discard Ta Tn VDISCARD Ta DISCARD No character -.El -.Ed -.It Cm min Ar number -.It Cm time Ar number -Set the value of min or time to -.Ar number . -.Dv MIN -and -.Dv TIME -are used in -Non-Canonical mode input processing -(-icanon). -.El -.Ss Combination Modes -.Bl -tag -width Fl -.It Ar saved settings -Set the current terminal characteristics to the saved settings -produced by the -.Fl g -option. -.It Cm evenp No or Cm parity -Enable parenb and cs7; disable parodd. -.It Cm oddp -Enable parenb, cs7, and parodd. -.It Fl parity , evenp , oddp -Disable parenb, and set cs8. -.It Cm \&nl Pq Fl \&nl -Enable (disable) icrnl. -In addition --nl unsets inlcr and igncr. -.It Cm ek -Reset -.Dv ERASE -and -.Dv KILL -characters back to system defaults. -.It Cm sane -Resets all modes to reasonable values for interactive terminal use. -.It Cm insane -Sets all modes to random values, which are very likely -.Pq but not guaranteed -to be unreasonable for interactive terminal use. -.It Cm tty -Set the line discipline to the standard terminal line discipline -.Dv TTYDISC . -.It Cm crt Pq Fl crt -Set (disable) all modes suitable for a CRT display device. -.It Cm kerninfo Pq Fl kerninfo -Enable (disable) the system generated status line associated with -processing a -.Dv STATUS -character (usually set to ^T). -The status line consists of the -system load average, the current command name, its process ID, the -event the process is waiting on (or the status of the process), the user -and system times, percent CPU, and current memory usage. -.It Cm columns Ar number -The terminal size is recorded as having -.Ar number -columns. -.It Cm cols Ar number -An alias for -.Cm columns . -.It Cm rows Ar number -The terminal size is recorded as having -.Ar number -rows. -.It Cm dec -Set modes suitable for users of Digital Equipment Corporation systems -.Dv ( ERASE , -.Dv KILL , -and -.Dv INTR -characters are set to ^?, ^U, and ^C; -.Dv ixany -is disabled, and -.Dv crt -is enabled). -.It Cm extproc Pq Fl extproc -If set, this flag indicates that some amount of terminal processing is being -performed by either the terminal hardware or by the remote side connected -to a pty. -.It Cm raw Pq Fl raw -If set, change the modes of the terminal so that no input or output processing -is performed. -If unset, change the modes of the terminal to some reasonable -state that performs input and output processing. -Note that since the terminal driver no longer has a single -.Dv RAW -bit, it is not possible to intuit what flags were set prior to setting -.Cm raw . -This means that unsetting -.Cm raw -may not put back all the setting that were previously in effect. -To set the terminal into a raw state and then accurately restore it, the following -shell code is recommended: -.Bd -literal -offset indent -save_state=$(stty -g) -stty raw -\&... -stty "$save_state" -.Ed -.It Cm size -The size of the terminal is printed as two numbers on a single line, -first rows, then columns. -.El -.Ss Compatibility Modes -These modes remain for compatibility with the previous version of -the -.Nm -utility. -.Bl -tag -width Fl -.It Cm all -Reports all the terminal modes as with -.Cm stty Fl a -except that the control characters are printed in a columnar format. -.It Cm everything -Same as -.Cm all . -.It Cm cooked -Same as -.Cm sane . -.It Cm cbreak -If set, enables -.Cm brkint , ixon , imaxbel , opost , -.Cm isig , iexten , -and -.Fl icanon . -If unset, same as -.Cm sane . -.It Cm new -Same as -.Cm tty . -.It Cm old -Same as -.Cm tty . -.It Cm newcrt Pq Fl newcrt -Same as -.Cm crt . -.It Cm pass8 -The converse of -.Cm parity . -.It Cm tandem Pq Fl tandem -Same as -.Cm ixoff . -.It Cm decctlq Pq Fl decctlq -The converse of -.Cm ixany . -.It Cm crterase Pq Fl crterase -Same as -.Cm echoe . -.It Cm crtbs Pq Fl crtbs -Same as -.Cm echoe . -.It Cm crtkill Pq Fl crtkill -Same as -.Cm echoke . -.It Cm ctlecho Pq Fl ctlecho -Same as -.Cm echoctl . -.It Cm prterase Pq Fl prterase -Same as -.Cm echoprt . -.It Cm litout Pq Fl litout -The converse of -.Cm opost . -.It Cm tabs Pq Fl tabs -The converse of -.Cm oxtabs . -.It Cm brk Ar value -Same as the control character -.Cm eol . -.It Cm flush Ar value -Same as the control character -.Cm discard . -.It Cm rprnt Ar value -Same as the control character -.Cm reprint . -.El -.Ss Control operations -These operations are not modes, but rather commands to be performed by -the tty layer. -.Bl -tag -width Fl -.It Cm ostart -Performs a "start output" operation, as normally done by an -incoming START character when -.Cm ixon -is set. -.It Cm ostop -Performs a "stop output" operation, as normally done by an -incoming STOP character when -.Cm ixon -is set. -.El -.Sh EXIT STATUS -.Ex -std -.Sh SEE ALSO -.Xr termios 4 , -.Xr tty 4 -.Sh STANDARDS -The -.Nm -utility is expected to be -.St -p1003.2 -compatible. -The -.Fl e -and -.Fl f -flags are -extensions to the standard, as are the operands mentioned in the control -operations section. -.Sh HISTORY -An -.Nm -utility appeared in -.At v2 . diff --git a/bin/stty/stty.c b/bin/stty/stty.c deleted file mode 100644 index a1cbd49ba..000000000 --- a/bin/stty/stty.c +++ /dev/null @@ -1,168 +0,0 @@ -/* $NetBSD: stty.c,v 1.23 2013/09/12 19:47:23 christos Exp $ */ - -/*- - * Copyright (c) 1989, 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1989, 1991, 1993, 1994\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)stty.c 8.3 (Berkeley) 4/2/94"; -#else -__RCSID("$NetBSD: stty.c,v 1.23 2013/09/12 19:47:23 christos Exp $"); -#endif -#endif /* not lint */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "stty.h" -#include "extern.h" - -int -main(int argc, char *argv[]) -{ - struct info i; - enum FMT fmt; - int ch; - - setprogname(argv[0]); - (void)setlocale(LC_ALL, ""); - - fmt = STTY_NOTSET; - i.fd = STDIN_FILENO; - - opterr = 0; - while (optind < argc && - strspn(argv[optind], "-aefg") == strlen(argv[optind]) && - (ch = getopt(argc, argv, "aef:g")) != -1) - switch(ch) { - case 'a': /* undocumented: POSIX compatibility */ - fmt = STTY_POSIX; - break; - case 'e': - fmt = STTY_BSD; - break; - case 'f': - if ((i.fd = open(optarg, O_RDONLY | O_NONBLOCK)) < 0) - err(1, "%s", optarg); - break; - case 'g': - fmt = STTY_GFLAG; - break; - case '?': - default: - goto args; - } - -args: argc -= optind; - argv += optind; - - if (ioctl(i.fd, TIOCGLINED, i.ldisc) < 0) - err(1, "TIOCGLINED"); - if (tcgetattr(i.fd, &i.t) < 0) - err(1, "tcgetattr"); - if (ioctl(i.fd, TIOCGWINSZ, &i.win) < 0) - warn("TIOCGWINSZ"); - if (ioctl(i.fd, TIOCGQSIZE, &i.queue) < 0) - warn("TIOCGQSIZE"); - - switch(fmt) { - case STTY_NOTSET: - if (*argv) - break; - /* FALLTHROUGH */ - case STTY_BSD: - case STTY_POSIX: - print(&i.t, &i.win, i.queue, i.ldisc, fmt); - break; - case STTY_GFLAG: - gprint(&i.t); - break; - } - - for (i.set = i.wset = 0; *argv; ++argv) { - if (ksearch(&argv, &i)) - continue; - - if (csearch(&argv, &i)) - continue; - - if (msearch(&argv, &i)) - continue; - - if (isdigit((unsigned char)**argv)) { - int speed; - - speed = atoi(*argv); - cfsetospeed(&i.t, speed); - cfsetispeed(&i.t, speed); - i.set = 1; - continue; - } - - if (!strncmp(*argv, "gfmt1", sizeof("gfmt1") - 1)) { - gread(&i.t, *argv + sizeof("gfmt1") - 1); - i.set = 1; - continue; - } - - warnx("illegal option -- %s", *argv); - usage(); - } - - if (i.set && tcsetattr(i.fd, 0, &i.t) < 0) - err(1, "tcsetattr"); - if (i.wset && ioctl(i.fd, TIOCSWINSZ, &i.win) < 0) - warn("TIOCSWINSZ"); - exit(0); - /* NOTREACHED */ -} - -void -usage(void) -{ - - (void)fprintf(stderr, "usage: %s [-a|-e|-g] [-f file] [operand ...]\n", getprogname()); - exit(1); - /* NOTREACHED */ -} diff --git a/bin/stty/stty.h b/bin/stty/stty.h deleted file mode 100644 index 8b93cba7e..000000000 --- a/bin/stty/stty.h +++ /dev/null @@ -1,62 +0,0 @@ -/* $NetBSD: stty.h,v 1.11 2013/09/12 19:47:23 christos Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)stty.h 8.1 (Berkeley) 5/31/93 - */ - -#ifndef _STTY_H_ -#define _STTY_H_ - -#include -#include - -struct info { - int fd; /* file descriptor */ - linedn_t ldisc; /* line discipline */ - int queue; /* queue size */ - int off; /* turn off */ - int set; /* need set */ - int wset; /* need window set */ - char *arg; /* argument */ - struct termios t; /* terminal info */ - struct winsize win; /* window info */ -}; - -struct cchar { - const char *name; - int sub; - u_char def; -}; - -enum FMT { STTY_NOTSET, STTY_GFLAG, STTY_BSD, STTY_POSIX }; - -#define LINELENGTH 72 - -#endif /* !_STTY_H_ */ diff --git a/bin/sync/Makefile b/bin/sync/Makefile deleted file mode 100644 index 25ea7e849..000000000 --- a/bin/sync/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# $NetBSD: Makefile,v 1.9 1997/07/20 22:38:07 christos Exp $ -# @(#)Makefile 8.1 (Berkeley) 5/31/93 - -PROG= sync -MAN= sync.8 - -.include diff --git a/bin/sync/sync.8 b/bin/sync/sync.8 deleted file mode 100644 index d3ca6d8e3..000000000 --- a/bin/sync/sync.8 +++ /dev/null @@ -1,72 +0,0 @@ -.\" $NetBSD: sync.8,v 1.16 2016/08/12 02:59:23 sevan Exp $ -.\" -.\" Copyright (c) 1980, 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)sync.8 8.1 (Berkeley) 5/31/93 -.\" -.Dd August 12, 2016 -.Dt SYNC 8 -.Os -.Sh NAME -.Nm sync -.Nd force completion of pending disk writes (flush cache) -.Sh SYNOPSIS -.Nm -.Sh DESCRIPTION -The -.Nm -program can be called to ensure that all disk writes have been -completed before the processor is halted in a way not suitably done by -.Xr reboot 8 -or -.Xr halt 8 . -Generally, it is preferable to use -.Xr reboot 8 -or -.Xr halt 8 -to shut down the system, -as they may perform additional actions -such as resynchronizing the hardware clock -and flushing internal caches before performing a final -.Nm . -.Pp -The -.Nm -program simply invokes the -.Xr sync 2 -system call. -.Sh SEE ALSO -.Xr fsync 2 , -.Xr sync 2 , -.Xr halt 8 , -.Xr reboot 8 -.Sh HISTORY -A -.Nm -command appeared in -.At v4 . diff --git a/bin/sync/sync.c b/bin/sync/sync.c deleted file mode 100644 index 1ae14c1f7..000000000 --- a/bin/sync/sync.c +++ /dev/null @@ -1,57 +0,0 @@ -/* $NetBSD: sync.c,v 1.14 2016/09/05 01:00:07 sevan Exp $ */ - -/* - * Copyright (c) 1987, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef lint -__COPYRIGHT("@(#) Copyright (c) 1987, 1993\ - The Regents of the University of California. All rights reserved."); -#endif /* not lint */ - -#ifndef lint -#if 0 -static char sccsid[] = "@(#)sync.c 8.1 (Berkeley) 5/31/93"; -#else -__RCSID("$NetBSD: sync.c,v 1.14 2016/09/05 01:00:07 sevan Exp $"); -#endif -#endif /* not lint */ - -#include -#include - -/* ARGSUSED */ -int -main(int argc, char *argv[]) -{ - setprogname(argv[0]); - sync(); - exit(0); - /* NOTREACHED */ -} diff --git a/bin/test/Makefile b/bin/test/Makefile deleted file mode 100644 index 315b6c808..000000000 --- a/bin/test/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $NetBSD: Makefile,v 1.11 2007/06/22 03:24:16 simonb Exp $ -# @(#)Makefile 8.1 (Berkeley) 5/31/93 - -PROG= test -SRCS= test.c -LINKS= ${BINDIR}/test ${BINDIR}/[ -MLINKS= test.1 [.1 - -.include diff --git a/bin/test/TEST.csh b/bin/test/TEST.csh deleted file mode 100644 index 672e1a0bd..000000000 --- a/bin/test/TEST.csh +++ /dev/null @@ -1,138 +0,0 @@ -# $NetBSD: TEST.csh,v 1.2 1995/03/21 07:03:59 cgd Exp $ -# @(#)TEST.csh 5.2 (Berkeley) 4/30/93 - -#alias t '/usr/src/bin/test/obj/test \!*; echo $status' -alias t '/bin/test \!*; echo $status' - -echo 't -b /dev/ttyp2' -t -b /dev/ttyp2 -echo 't -b /dev/jb1a' -t -b /dev/jb1a - -echo 't -c test.c' -t -c test.c -echo 't -c /dev/tty' -t -c /dev/tty - -echo 't -d test.c' -t -d test.c -echo 't -d /etc' -t -d /etc - -echo 't -e noexist' -t -e noexist -echo 't -e test.c' -t -e test.c - -echo 't -f noexist' -t -f noexist -echo 't -f /dev/tty' -t -f /dev/tty -echo 't -f test.c' -t -f test.c - -echo 't -g test.c' -t -g test.c -echo 't -g /bin/ps' -t -g /bin/ps - -echo 't -n ""' -t -n "" -echo 't -n "hello"' -t -n "hello" - -echo 't -p test.c' -t -p test.c - -echo 't -r noexist' -t -r noexist -echo 't -r /etc/master.passwd' -t -r /etc/master.passwd -echo 't -r test.c' -t -r test.c - -echo 't -s noexist' -t -s noexist -echo 't -s /dev/null' -t -s /dev/null -echo 't -s test.c' -t -s test.c - -echo 't -t 20' -t -t 20 -echo 't -t 0' -t -t 0 - -echo 't -u test.c' -t -u test.c -echo 't -u /bin/rcp' -t -u /bin/rcp - -echo 't -w noexist' -t -w noexist -echo 't -w /etc/master.passwd' -t -w /etc/master.passwd -echo 't -w /dev/null' -t -w /dev/null - -echo 't -x noexist' -t -x noexist -echo 't -x /bin/ps' -t -x /bin/ps -echo 't -x /etc/motd' -t -x /etc/motd - -echo 't -z ""' -t -z "" -echo 't -z "foo"' -t -z "foo" - -echo 't "foo"' -t "foo" -echo 't ""' -t "" - -echo 't "hello" = "hello"' -t "hello" = "hello" -echo 't "hello" = "goodbye"' -t "hello" = "goodbye" - -echo 't "hello" != "hello"' -t "hello" != "hello" -echo 't "hello" != "goodbye"' -t "hello" != "goodbye" - -echo 't 200 -eq 200' -t 200 -eq 200 -echo 't 34 -eq 222' -t 34 -eq 222 - -echo 't 200 -ne 200' -t 200 -ne 200 -echo 't 34 -ne 222' -t 34 -ne 222 - -echo 't 200 -gt 200' -t 200 -gt 200 -echo 't 340 -gt 222' -t 340 -gt 222 - -echo 't 200 -ge 200' -t 200 -ge 200 -echo 't 34 -ge 222' -t 34 -ge 222 - -echo 't 200 -lt 200' -t 200 -lt 200 -echo 't 34 -lt 222' -t 34 -lt 222 - -echo 't 200 -le 200' -t 200 -le 200 -echo 't 340 -le 222' -t 340 -le 222 - -echo 't 700 -le 1000 -a -n "1" -a "20" = "20"' -t 700 -le 1000 -a -n "1" -a "20" = "20" -echo 't ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \)' -t ! \( 700 -le 1000 -a -n "1" -a "20" = "20" \) diff --git a/bin/test/test.1 b/bin/test/test.1 deleted file mode 100644 index 6ea7d6dbe..000000000 --- a/bin/test/test.1 +++ /dev/null @@ -1,330 +0,0 @@ -.\" $NetBSD: test.1,v 1.30 2016/08/12 03:17:41 sevan Exp $ -.\" -.\" Copyright (c) 1991, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Institute of Electrical and Electronics Engineers, Inc. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)test.1 8.1 (Berkeley) 5/31/93 -.\" -.Dd August 12, 2016 -.Dt TEST 1 -.Os -.Sh NAME -.Nm test , -.Nm \&[ -.Nd condition evaluation utility -.Sh SYNOPSIS -.Nm -.Ar expression -.Nm \&[ -.Ar expression Cm \&] -.Sh DESCRIPTION -The -.Nm -utility evaluates -.Ar expression -and, if it evaluates -to true, returns a zero (true) exit status; otherwise -it returns 1 (false). -If -.Ar expression -is not given, -.Nm -also -returns 1 (false). -.Pp -All operators and flags are separate arguments to the -.Nm -utility. -.Pp -The following primaries are used to construct -.Ar expression : -.Bl -tag -width Ar -.It Fl b Ar file -True if -.Ar file -exists and is a block special -file. -.It Fl c Ar file -True if -.Ar file -exists and is a character -special file. -.It Fl d Ar file -True if -.Ar file -exists and is a directory. -.It Fl e Ar file -True if -.Ar file -exists (regardless of type). -.It Fl f Ar file -True if -.Ar file -exists and is a regular file. -.It Fl g Ar file -True if -.Ar file -exists and its set group ID flag -is set. -.It Fl h Ar file -True if -.Ar file -exists and is a symbolic link. -.It Fl k Ar file -True if -.Ar file -exists and its sticky bit is set. -.It Fl n Ar string -True if the length of -.Ar string -is nonzero. -.It Fl p Ar file -True if -.Ar file -exists and is a named pipe -.Po Tn FIFO Pc . -.It Fl r Ar file -True if -.Ar file -exists and is readable. -.It Fl s Ar file -True if -.Ar file -exists and has a size greater -than zero. -.It Fl t Ar file_descriptor -True if the file whose file descriptor number -is -.Ar file_descriptor -is open and is associated with a terminal. -.It Fl u Ar file -True if -.Ar file -exists and its set user ID flag -is set. -.It Fl w Ar file -True if -.Ar file -exists and is writable. -True -indicates only that the write flag is on. -The file is not writable on a read-only file -system even if this test indicates true. -.It Fl x Ar file -True if -.Ar file -exists and is executable. -True -indicates only that the execute flag is on. -If -.Ar file -is a directory, true indicates that -.Ar file -can be searched. -.It Fl z Ar string -True if the length of -.Ar string -is zero. -.It Fl L Ar file -True if -.Ar file -exists and is a symbolic link. -This operator is retained for compatibility with previous versions of -this program. -Do not rely on its existence; use -.Fl h -instead. -.It Fl O Ar file -True if -.Ar file -exists and its owner matches the effective user id of this process. -.It Fl G Ar file -True if -.Ar file -exists and its group matches the effective group id of this process. -.It Fl S Ar file -True if -.Ar file -exists and is a socket. -.It Ar file1 Fl nt Ar file2 -True if -.Ar file1 -exists and is newer than -.Ar file2 . -.It Ar file1 Fl ot Ar file2 -True if -.Ar file1 -exists and is older than -.Ar file2 . -.It Ar file1 Fl ef Ar file2 -True if -.Ar file1 -and -.Ar file2 -exist and refer to the same file. -.It Ar string -True if -.Ar string -is not the null -string. -.It Ar \&s\&1 Cm \&= Ar \&s\&2 -True if the strings -.Ar \&s\&1 -and -.Ar \&s\&2 -are identical. -.It Ar \&s\&1 Cm \&!= Ar \&s\&2 -True if the strings -.Ar \&s\&1 -and -.Ar \&s\&2 -are not identical. -.It Ar \&s\&1 Cm \&\*[Lt] Ar \&s\&2 -True if string -.Ar \&s\&1 -comes before -.Ar \&s\&2 -based on the ASCII value of their characters. -.It Ar \&s\&1 Cm \&\*[Gt] Ar \&s\&2 -True if string -.Ar \&s\&1 -comes after -.Ar \&s\&2 -based on the ASCII value of their characters. -.It Ar \&n\&1 Fl \&eq Ar \&n\&2 -True if the integers -.Ar \&n\&1 -and -.Ar \&n\&2 -are algebraically -equal. -.It Ar \&n\&1 Fl \&ne Ar \&n\&2 -True if the integers -.Ar \&n\&1 -and -.Ar \&n\&2 -are not -algebraically equal. -.It Ar \&n\&1 Fl \> Ar \&n\&2 -True if the integer -.Ar \&n\&1 -is algebraically -greater than the integer -.Ar \&n\&2 . -.It Ar \&n\&1 Fl \&ge Ar \&n\&2 -True if the integer -.Ar \&n\&1 -is algebraically -greater than or equal to the integer -.Ar \&n\&2 . -.It Ar \&n\&1 Fl \< Ar \&n\&2 -True if the integer -.Ar \&n\&1 -is algebraically less -than the integer -.Ar \&n\&2 . -.It Ar \&n\&1 Fl \&le Ar \&n\&2 -True if the integer -.Ar \&n\&1 -is algebraically less -than or equal to the integer -.Ar \&n\&2 . -.El -.Pp -These primaries can be combined with the following operators: -.Bl -tag -width Ar -.It Cm \&! Ar expression -True if -.Ar expression -is false. -.It Ar expression1 Fl a Ar expression2 -True if both -.Ar expression1 -and -.Ar expression2 -are true. -.It Ar expression1 Fl o Ar expression2 -True if either -.Ar expression1 -or -.Ar expression2 -is true. -.It Cm \&( Ar expression Cm \&) -True if -.Ar expression -is true. -.El -.Pp -The -.Fl a -operator has higher precedence than the -.Fl o -operator. -.Pp -Note that all file tests with the exception of -.Fl h -and -.Fl L -follow symbolic links and thus evaluate the test for the file pointed at. -.Sh EXIT STATUS -The -.Nm -utility exits with one of the following values: -.Bl -tag -width Ds -.It 0 -.Ar expression -evaluated to true. -.It 1 -.Ar expression -evaluated to false or was missing. -.It \*[Gt]1 -An error occurred. -.El -.Sh STANDARDS -The -.Nm -utility implements a superset of the -.St -p1003.2 -specification. -.Sh HISTORY -A -.Nm -utility appeared in -.At v7 . -.Sh CAVEATS -The -.Nm -grammar is inherently ambiguous. -In order to assure a degree of consistency, the cases described in -.St -p1003.2 -section 4.62.4, -are evaluated consistently according to the rules specified in the -standards document. -All other cases are subject to the ambiguity in the command semantics. diff --git a/bin/test/test.c b/bin/test/test.c deleted file mode 100644 index 26e756f68..000000000 --- a/bin/test/test.c +++ /dev/null @@ -1,717 +0,0 @@ -/* $NetBSD: test.c,v 1.41 2016/09/05 01:00:07 sevan Exp $ */ - -/* - * test(1); version 7-like -- author Erik Baalbergen - * modified by Eric Gisin to be used as built-in. - * modified by Arnold Robbins to add SVR3 compatibility - * (-x -c -b -p -u -g -k) plus Korn's -L -nt -ot -ef and new -S (socket). - * modified by J.T. Conklin for NetBSD. - * - * This program is in the Public Domain. - */ - -#include -#ifndef lint -__RCSID("$NetBSD: test.c,v 1.41 2016/09/05 01:00:07 sevan Exp $"); -#endif - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* test(1) accepts the following grammar: - oexpr ::= aexpr | aexpr "-o" oexpr ; - aexpr ::= nexpr | nexpr "-a" aexpr ; - nexpr ::= primary | "!" primary - primary ::= unary-operator operand - | operand binary-operator operand - | operand - | "(" oexpr ")" - ; - unary-operator ::= "-r"|"-w"|"-x"|"-f"|"-d"|"-c"|"-b"|"-p"| - "-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S"; - - binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"| - "-nt"|"-ot"|"-ef"; - operand ::= -*/ - -enum token { - EOI, - FILRD, - FILWR, - FILEX, - FILEXIST, - FILREG, - FILDIR, - FILCDEV, - FILBDEV, - FILFIFO, - FILSOCK, - FILSYM, - FILGZ, - FILTT, - FILSUID, - FILSGID, - FILSTCK, - FILNT, - FILOT, - FILEQ, - FILUID, - FILGID, - STREZ, - STRNZ, - STREQ, - STRNE, - STRLT, - STRGT, - INTEQ, - INTNE, - INTGE, - INTGT, - INTLE, - INTLT, - UNOT, - BAND, - BOR, - LPAREN, - RPAREN, - OPERAND -}; - -enum token_types { - UNOP, - BINOP, - BUNOP, - BBINOP, - PAREN -}; - -struct t_op { - const char *op_text; - short op_num, op_type; -}; - -static const struct t_op cop[] = { - {"!", UNOT, BUNOP}, - {"(", LPAREN, PAREN}, - {")", RPAREN, PAREN}, - {"<", STRLT, BINOP}, - {"=", STREQ, BINOP}, - {">", STRGT, BINOP}, -}; - -static const struct t_op cop2[] = { - {"!=", STRNE, BINOP}, -}; - -static const struct t_op mop3[] = { - {"ef", FILEQ, BINOP}, - {"eq", INTEQ, BINOP}, - {"ge", INTGE, BINOP}, - {"gt", INTGT, BINOP}, - {"le", INTLE, BINOP}, - {"lt", INTLT, BINOP}, - {"ne", INTNE, BINOP}, - {"nt", FILNT, BINOP}, - {"ot", FILOT, BINOP}, -}; - -static const struct t_op mop2[] = { - {"G", FILGID, UNOP}, - {"L", FILSYM, UNOP}, - {"O", FILUID, UNOP}, - {"S", FILSOCK,UNOP}, - {"a", BAND, BBINOP}, - {"b", FILBDEV,UNOP}, - {"c", FILCDEV,UNOP}, - {"d", FILDIR, UNOP}, - {"e", FILEXIST,UNOP}, - {"f", FILREG, UNOP}, - {"g", FILSGID,UNOP}, - {"h", FILSYM, UNOP}, /* for backwards compat */ - {"k", FILSTCK,UNOP}, - {"n", STRNZ, UNOP}, - {"o", BOR, BBINOP}, - {"p", FILFIFO,UNOP}, - {"r", FILRD, UNOP}, - {"s", FILGZ, UNOP}, - {"t", FILTT, UNOP}, - {"u", FILSUID,UNOP}, - {"w", FILWR, UNOP}, - {"x", FILEX, UNOP}, - {"z", STREZ, UNOP}, -}; - -static char **t_wp; -static struct t_op const *t_wp_op; - -__dead static void syntax(const char *, const char *); -static int oexpr(enum token); -static int aexpr(enum token); -static int nexpr(enum token); -static int primary(enum token); -static int binop(void); -static int test_access(struct stat *, mode_t); -static int filstat(char *, enum token); -static enum token t_lex(char *); -static int isoperand(void); -static long long getn(const char *); -static int newerf(const char *, const char *); -static int olderf(const char *, const char *); -static int equalf(const char *, const char *); - -#if defined(SHELL) -extern void error(const char *, ...) __dead __printflike(1, 2); -extern void *ckmalloc(size_t); -#else -static void error(const char *, ...) __dead __printflike(1, 2); - -static void -error(const char *msg, ...) -{ - va_list ap; - - va_start(ap, msg); - verrx(2, msg, ap); - /*NOTREACHED*/ - va_end(ap); -} - -static void *ckmalloc(size_t); -static void * -ckmalloc(size_t nbytes) -{ - void *p = malloc(nbytes); - - if (!p) - error("Not enough memory!"); - return p; -} -#endif - -#ifdef SHELL -int testcmd(int, char **); - -int -testcmd(int argc, char **argv) -#else -int -main(int argc, char *argv[]) -#endif -{ - int res; - const char *argv0; - -#ifdef SHELL - argv0 = argv[0]; -#else - setprogname(argv[0]); - (void)setlocale(LC_ALL, ""); - argv0 = getprogname(); -#endif - if (strcmp(argv0, "[") == 0) { - if (strcmp(argv[--argc], "]")) - error("missing ]"); - argv[argc] = NULL; - } - - if (argc < 2) - return 1; - - t_wp = &argv[1]; - res = !oexpr(t_lex(*t_wp)); - - if (*t_wp != NULL && *++t_wp != NULL) - syntax(*t_wp, "unexpected operator"); - - return res; -} - -static void -syntax(const char *op, const char *msg) -{ - - if (op && *op) - error("%s: %s", op, msg); - else - error("%s", msg); -} - -static int -oexpr(enum token n) -{ - int res; - - res = aexpr(n); - if (*t_wp == NULL) - return res; - if (t_lex(*++t_wp) == BOR) - return oexpr(t_lex(*++t_wp)) || res; - t_wp--; - return res; -} - -static int -aexpr(enum token n) -{ - int res; - - res = nexpr(n); - if (*t_wp == NULL) - return res; - if (t_lex(*++t_wp) == BAND) - return aexpr(t_lex(*++t_wp)) && res; - t_wp--; - return res; -} - -static int -nexpr(enum token n) -{ - - if (n == UNOT) - return !nexpr(t_lex(*++t_wp)); - return primary(n); -} - -static int -primary(enum token n) -{ - enum token nn; - int res; - - if (n == EOI) - return 0; /* missing expression */ - if (n == LPAREN) { - if ((nn = t_lex(*++t_wp)) == RPAREN) - return 0; /* missing expression */ - res = oexpr(nn); - if (t_lex(*++t_wp) != RPAREN) - syntax(NULL, "closing paren expected"); - return res; - } - if (t_wp_op && t_wp_op->op_type == UNOP) { - /* unary expression */ - if (*++t_wp == NULL) - syntax(t_wp_op->op_text, "argument expected"); - switch (n) { - case STREZ: - return strlen(*t_wp) == 0; - case STRNZ: - return strlen(*t_wp) != 0; - case FILTT: - return isatty((int)getn(*t_wp)); - default: - return filstat(*t_wp, n); - } - } - - if (t_lex(t_wp[1]), t_wp_op && t_wp_op->op_type == BINOP) { - return binop(); - } - - return strlen(*t_wp) > 0; -} - -static int -binop(void) -{ - const char *opnd1, *opnd2; - struct t_op const *op; - - opnd1 = *t_wp; - (void) t_lex(*++t_wp); - op = t_wp_op; - - if ((opnd2 = *++t_wp) == NULL) - syntax(op->op_text, "argument expected"); - - switch (op->op_num) { - case STREQ: - return strcmp(opnd1, opnd2) == 0; - case STRNE: - return strcmp(opnd1, opnd2) != 0; - case STRLT: - return strcmp(opnd1, opnd2) < 0; - case STRGT: - return strcmp(opnd1, opnd2) > 0; - case INTEQ: - return getn(opnd1) == getn(opnd2); - case INTNE: - return getn(opnd1) != getn(opnd2); - case INTGE: - return getn(opnd1) >= getn(opnd2); - case INTGT: - return getn(opnd1) > getn(opnd2); - case INTLE: - return getn(opnd1) <= getn(opnd2); - case INTLT: - return getn(opnd1) < getn(opnd2); - case FILNT: - return newerf(opnd1, opnd2); - case FILOT: - return olderf(opnd1, opnd2); - case FILEQ: - return equalf(opnd1, opnd2); - default: - abort(); - /* NOTREACHED */ - } -} - -/* - * The manual, and IEEE POSIX 1003.2, suggests this should check the mode bits, - * not use access(): - * - * True shall indicate only that the write flag is on. The file is not - * writable on a read-only file system even if this test indicates true. - * - * Unfortunately IEEE POSIX 1003.1-2001, as quoted in SuSv3, says only: - * - * True shall indicate that permission to read from file will be granted, - * as defined in "File Read, Write, and Creation". - * - * and that section says: - * - * When a file is to be read or written, the file shall be opened with an - * access mode corresponding to the operation to be performed. If file - * access permissions deny access, the requested operation shall fail. - * - * and of course access permissions are described as one might expect: - * - * * If a process has the appropriate privilege: - * - * * If read, write, or directory search permission is requested, - * access shall be granted. - * - * * If execute permission is requested, access shall be granted if - * execute permission is granted to at least one user by the file - * permission bits or by an alternate access control mechanism; - * otherwise, access shall be denied. - * - * * Otherwise: - * - * * The file permission bits of a file contain read, write, and - * execute/search permissions for the file owner class, file group - * class, and file other class. - * - * * Access shall be granted if an alternate access control mechanism - * is not enabled and the requested access permission bit is set for - * the class (file owner class, file group class, or file other class) - * to which the process belongs, or if an alternate access control - * mechanism is enabled and it allows the requested access; otherwise, - * access shall be denied. - * - * and when I first read this I thought: surely we can't go about using - * open(O_WRONLY) to try this test! However the POSIX 1003.1-2001 Rationale - * section for test does in fact say: - * - * On historical BSD systems, test -w directory always returned false - * because test tried to open the directory for writing, which always - * fails. - * - * and indeed this is in fact true for Seventh Edition UNIX, UNIX 32V, and UNIX - * System III, and thus presumably also for BSD up to and including 4.3. - * - * Secondly I remembered why using open() and/or access() are bogus. They - * don't work right for detecting read and write permissions bits when called - * by root. - * - * Interestingly the 'test' in 4.4BSD was closer to correct (as per - * 1003.2-1992) and it was implemented efficiently with stat() instead of - * open(). - * - * This was apparently broken in NetBSD around about 1994/06/30 when the old - * 4.4BSD implementation was replaced with a (arguably much better coded) - * implementation derived from pdksh. - * - * Note that modern pdksh is yet different again, but still not correct, at - * least not w.r.t. 1003.2-1992. - * - * As I think more about it and read more of the related IEEE docs I don't like - * that wording about 'test -r' and 'test -w' in 1003.1-2001 at all. I very - * much prefer the original wording in 1003.2-1992. It is much more useful, - * and so that's what I've implemented. - * - * (Note that a strictly conforming implementation of 1003.1-2001 is in fact - * totally useless for the case in question since its 'test -w' and 'test -r' - * can never fail for root for any existing files, i.e. files for which 'test - * -e' succeeds.) - * - * The rationale for 1003.1-2001 suggests that the wording was "clarified" in - * 1003.1-2001 to align with the 1003.2b draft. 1003.2b Draft 12 (July 1999), - * which is the latest copy I have, does carry the same suggested wording as is - * in 1003.1-2001, with its rationale saying: - * - * This change is a clarification and is the result of interpretation - * request PASC 1003.2-92 #23 submitted for IEEE Std 1003.2-1992. - * - * That interpretation can be found here: - * - * http://www.pasc.org/interps/unofficial/db/p1003.2/pasc-1003.2-23.html - * - * Not terribly helpful, unfortunately. I wonder who that fence sitter was. - * - * Worse, IMVNSHO, I think the authors of 1003.2b-D12 have mis-interpreted the - * PASC interpretation and appear to be gone against at least one widely used - * implementation (namely 4.4BSD). The problem is that for file access by root - * this means that if test '-r' and '-w' are to behave as if open() were called - * then there's no way for a shell script running as root to check if a file - * has certain access bits set other than by the grotty means of interpreting - * the output of 'ls -l'. This was widely considered to be a bug in V7's - * "test" and is, I believe, one of the reasons why direct use of access() was - * avoided in some more recent implementations! - * - * I have always interpreted '-r' to match '-w' and '-x' as per the original - * wording in 1003.2-1992, not the other way around. I think 1003.2b goes much - * too far the wrong way without any valid rationale and that it's best if we - * stick with 1003.2-1992 and test the flags, and not mimic the behaviour of - * open() since we already know very well how it will work -- existance of the - * file is all that matters to open() for root. - * - * Unfortunately the SVID is no help at all (which is, I guess, partly why - * we're in this mess in the first place :-). - * - * The SysV implementation (at least in the 'test' builtin in /bin/sh) does use - * access(name, 2) even though it also goes to much greater lengths for '-x' - * matching the 1003.2-1992 definition (which is no doubt where that definition - * came from). - * - * The ksh93 implementation uses access() for '-r' and '-w' if - * (euid==uid&&egid==gid), but uses st_mode for '-x' iff running as root. - * i.e. it does strictly conform to 1003.1-2001 (and presumably 1003.2b). - */ -static int -test_access(struct stat *sp, mode_t stmode) -{ - gid_t *groups; - register int n; - uid_t euid; - int maxgroups; - - /* - * I suppose we could use access() if not running as root and if we are - * running with ((euid == uid) && (egid == gid)), but we've already - * done the stat() so we might as well just test the permissions - * directly instead of asking the kernel to do it.... - */ - euid = geteuid(); - if (euid == 0) /* any bit is good enough */ - stmode = (stmode << 6) | (stmode << 3) | stmode; - else if (sp->st_uid == euid) - stmode <<= 6; - else if (sp->st_gid == getegid()) - stmode <<= 3; - else { - /* XXX stolen almost verbatim from ksh93.... */ - /* on some systems you can be in several groups */ - if ((maxgroups = getgroups(0, NULL)) <= 0) - maxgroups = NGROUPS_MAX; /* pre-POSIX system? */ - groups = ckmalloc((maxgroups + 1) * sizeof(gid_t)); - n = getgroups(maxgroups, groups); - while (--n >= 0) { - if (groups[n] == sp->st_gid) { - stmode <<= 3; - break; - } - } - free(groups); - } - - return sp->st_mode & stmode; -} - -static int -filstat(char *nm, enum token mode) -{ - struct stat s; - - if (mode == FILSYM ? lstat(nm, &s) : stat(nm, &s)) - return 0; - - switch (mode) { - case FILRD: - return test_access(&s, S_IROTH); - case FILWR: - return test_access(&s, S_IWOTH); - case FILEX: - return test_access(&s, S_IXOTH); - case FILEXIST: - return 1; /* the successful lstat()/stat() is good enough */ - case FILREG: - return S_ISREG(s.st_mode); - case FILDIR: - return S_ISDIR(s.st_mode); - case FILCDEV: - return S_ISCHR(s.st_mode); - case FILBDEV: - return S_ISBLK(s.st_mode); - case FILFIFO: - return S_ISFIFO(s.st_mode); - case FILSOCK: - return S_ISSOCK(s.st_mode); - case FILSYM: - return S_ISLNK(s.st_mode); - case FILSUID: - return (s.st_mode & S_ISUID) != 0; - case FILSGID: - return (s.st_mode & S_ISGID) != 0; - case FILSTCK: - return (s.st_mode & S_ISVTX) != 0; - case FILGZ: - return s.st_size > (off_t)0; - case FILUID: - return s.st_uid == geteuid(); - case FILGID: - return s.st_gid == getegid(); - default: - return 1; - } -} - -#define VTOC(x) (const unsigned char *)((const struct t_op *)x)->op_text - -static int -compare1(const void *va, const void *vb) -{ - const unsigned char *a = va; - const unsigned char *b = VTOC(vb); - - return a[0] - b[0]; -} - -static int -compare2(const void *va, const void *vb) -{ - const unsigned char *a = va; - const unsigned char *b = VTOC(vb); - int z = a[0] - b[0]; - - return z ? z : (a[1] - b[1]); -} - -static struct t_op const * -findop(const char *s) -{ - if (s[0] == '-') { - if (s[1] == '\0') - return NULL; - if (s[2] == '\0') - return bsearch(s + 1, mop2, __arraycount(mop2), - sizeof(*mop2), compare1); - else if (s[3] != '\0') - return NULL; - else - return bsearch(s + 1, mop3, __arraycount(mop3), - sizeof(*mop3), compare2); - } else { - if (s[1] == '\0') - return bsearch(s, cop, __arraycount(cop), sizeof(*cop), - compare1); - else if (strcmp(s, cop2[0].op_text) == 0) - return cop2; - else - return NULL; - } -} - -static enum token -t_lex(char *s) -{ - struct t_op const *op; - - if (s == NULL) { - t_wp_op = NULL; - return EOI; - } - - if ((op = findop(s)) != NULL) { - if (!((op->op_type == UNOP && isoperand()) || - (op->op_num == LPAREN && *(t_wp+1) == 0))) { - t_wp_op = op; - return op->op_num; - } - } - t_wp_op = NULL; - return OPERAND; -} - -static int -isoperand(void) -{ - struct t_op const *op; - char *s, *t; - - if ((s = *(t_wp+1)) == 0) - return 1; - if ((t = *(t_wp+2)) == 0) - return 0; - if ((op = findop(s)) != NULL) - return op->op_type == BINOP && (t[0] != ')' || t[1] != '\0'); - return 0; -} - -/* atoi with error detection */ -static long long -getn(const char *s) -{ - char *p; - long long r; - - errno = 0; - r = strtoll(s, &p, 10); - - if (errno != 0) - if (errno == ERANGE && (r == LLONG_MAX || r == LLONG_MIN)) - error("%s: out of range", s); - - while (isspace((unsigned char)*p)) - p++; - - if (*p || p == s) - error("%s: bad number", s); - - return r; -} - -static int -newerf(const char *f1, const char *f2) -{ - struct stat b1, b2; - - return (stat(f1, &b1) == 0 && - stat(f2, &b2) == 0 && - timespeccmp(&b1.st_mtim, &b2.st_mtim, >)); -} - -static int -olderf(const char *f1, const char *f2) -{ - struct stat b1, b2; - - return (stat(f1, &b1) == 0 && - stat(f2, &b2) == 0 && - timespeccmp(&b1.st_mtim, &b2.st_mtim, <)); -} - -static int -equalf(const char *f1, const char *f2) -{ - struct stat b1, b2; - - return (stat(f1, &b1) == 0 && - stat(f2, &b2) == 0 && - b1.st_dev == b2.st_dev && - b1.st_ino == b2.st_ino); -}