home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume35 / zsh / part17 < prev    next >
Text File  |  1993-02-20  |  56KB  |  2,300 lines

  1. Newsgroups: comp.sources.misc
  2. From: zsh-list@cs.uow.edu.au (The Zsh Mailing List)
  3. Subject: v35i067:  zsh - The Z Shell, version 2.3.1, Part17/22
  4. Message-ID: <1993Feb20.212754.29286@sparky.imd.sterling.com>
  5. X-Md4-Signature: ceaaa9f6e26a57c085f8974ff8feb0c1
  6. Date: Sat, 20 Feb 1993 21:27:54 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: zsh-list@cs.uow.edu.au (The Zsh Mailing List)
  10. Posting-number: Volume 35, Issue 67
  11. Archive-name: zsh/part17
  12. Environment: UNIX
  13. Supersedes: zsh2.2: Volume 29, Issue 97-113
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  20. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  21. # Contents:  help/popd man/man1/zsh.1.03 src/builtin.c.02 src/subst.c
  22. # Wrapped by mattson@odin on Sat Feb  6 14:41:55 1993
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 17 (of 22)."'
  26. if test -f 'help/popd' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'help/popd'\"
  28. else
  29.   echo shar: Extracting \"'help/popd'\" \(609 characters\)
  30.   sed "s/^X//" >'help/popd' <<'END_OF_FILE'
  31. X     popd [ +-n ]
  32. X          Removes entries from  the  directory  stack.   With  no
  33. X          arguments,  removes  the  top directory from the stack,
  34. X          and performs a cd to the new top  directory.   With  an
  35. X          argument  of the form +n, remove the nth entry counting
  36. X          from the left of the list shown by  the  dirs  command,
  37. X          starting with zero, and change to that directory.  With
  38. X          an argument of the form -n, remove the nth entry count-
  39. X          ing  from the right.  If the PUSHD_MINUS option is set,
  40. X          the meanings of + and - in this context are swapped.
  41. END_OF_FILE
  42.   if test 609 -ne `wc -c <'help/popd'`; then
  43.     echo shar: \"'help/popd'\" unpacked with wrong size!
  44.   fi
  45.   # end of 'help/popd'
  46. fi
  47. if test -f 'man/man1/zsh.1.03' -a "${1}" != "-c" ; then 
  48.   echo shar: Will not clobber existing file \"'man/man1/zsh.1.03'\"
  49. else
  50.   echo shar: Extracting \"'man/man1/zsh.1.03'\" \(17067 characters\)
  51.   sed "s/^X//" >'man/man1/zsh.1.03' <<'END_OF_FILE'
  52. X\fBlet\fP \fIarg\fP ...
  53. XEvaluate each \fIarg\fP as an arithmetic expression.
  54. XSee \fBARITHMETIC EVALUATION\fP above for a description
  55. Xof arithmetic expressions.  The exit status is 0 if the
  56. Xvalue of the last expression is nonzero, and 1 otherwise.
  57. X.TP
  58. X.PD 0
  59. X\fBlimit\fP [ \-\fBh\fP ] [ \fIresource\fP [ \fIlimit\fP ] ] ...
  60. X.TP
  61. X\fBlimit\fP \-\fBs\fP
  62. X.PD
  63. XLimit the resource consumption of children of the current shell.
  64. XIf \fIlimit\fP is not specified, print the current limit placed
  65. Xon \fIresource\fP; otherwise
  66. Xset the limit to the specified value.  If the \-\fBh\fP flag
  67. Xis given, use hard limits instead of soft limits.
  68. XIf no \fIresource\fP is given, print all limits.
  69. X.RS
  70. X.PP
  71. X\fIresource\fP is one of:
  72. X.PP
  73. X.PD 0
  74. X.TP
  75. X.B cputime
  76. XMaximum CPU seconds per process.
  77. X.TP
  78. X.B filesize
  79. XLargest single file allowed.
  80. X.TP
  81. X.B datasize
  82. XMaximum data size (including stack) for each process.
  83. X.TP
  84. X.B stacksize
  85. XMaximum stack size for each process.
  86. X.TP
  87. X.B coredumpsize
  88. XMaximum size of a core dump.
  89. X.TP
  90. X.B resident
  91. XMaximum resident set size.
  92. X.TP
  93. X.B descriptors
  94. XMaximum value for a file descriptor.
  95. X.PD
  96. X.PP
  97. X\fIlimit\fP is a number, with an optional scaling factor, as follows:
  98. X.PP
  99. X.PD 0
  100. X.TP
  101. X\fIn\fPh
  102. Xhours.
  103. X.TP
  104. X\fIn\fPk
  105. Xkilobytes. 
  106. XThis is the default for all but cputime.
  107. X.TP
  108. X\fIn\fPm
  109. Xmegabytes or minutes.
  110. X.TP
  111. X\fImm\fP:\fBss\fP
  112. Xminutes and seconds.
  113. X.PD
  114. X.RE
  115. X.TP
  116. X\fBlocal\fP
  117. XSame as \fBtypeset\fP.
  118. X.TP
  119. X\fBlog\fP
  120. XList all users currently logged in who are affected by
  121. Xthe current setting of the \fBwatch\fP parameter.
  122. X.TP
  123. X\fBlogout\fP
  124. XExit the shell, if this is a login shell.
  125. X.TP
  126. X\fBpopd\fP [ \(+-\fIn\fP ]
  127. XRemoves entries from the directory stack.  With no arguments,
  128. Xremoves the top directory from the stack, and performs a \fBcd\fP
  129. Xto the new top directory.  With an argument of the form +\fIn\fP,
  130. Xremove the \fIn\fPth entry counting from the left of the list
  131. Xshown by the \fBdirs\fP command, starting with zero, and change
  132. Xto that directory.  With an argument of the form \-\fIn\fP,
  133. Xremove the \fIn\fPth entry counting from the right.
  134. XIf the \fBPUSHD_MINUS\fP option is set, the meanings of +
  135. Xand \- in this context are swapped.
  136. X.TP
  137. X\fBprint\fP [ \-\fBRnrslzpNDP\fP ] [ \-\fBu\fP\fIn\fP ] [ \fIarg\fP ... ]
  138. XWith no flags or with flag \-, the arguments are printed on
  139. Xthe standard output as described by \fBecho\fP.
  140. X.RS
  141. X.PD 0
  142. X.TP
  143. X\-\fBR\fP, \-\fBr\fP
  144. Xignore the escape conventions of \fBecho\fP.
  145. XThe \-\fBR\fP option will print all subsequent
  146. Xarguments and options.
  147. X.TP
  148. X\-\fBs\fP
  149. Xplace the results in the history list instead of on the standard output.
  150. X.TP
  151. X\-\fBn\fP
  152. Xdo not add a newline to the output.
  153. X.TP
  154. X\-\fBl\fP
  155. Xprint the arguments separated by newlines instead of spaces.
  156. X.TP
  157. X\-\fBN\fP
  158. Xprint the arguments separated and terminated by nulls.
  159. X.TP
  160. X\-\fBu\fP\fIn\fP
  161. Xprint the arguments to file descriptor \fIn\fP.
  162. X.TP
  163. X\-\fBp\fP
  164. Xprint the arguments to the input of the coprocess.
  165. X.TP
  166. X\-\fBz\fP
  167. Xpush the arguments onto the editing buffer stack, separated by spaces;
  168. Xno escape sequences are recognized.
  169. X.TP
  170. X\-\fBD\fP
  171. Xtreat the arguments as directory names, replacing prefixes with ~
  172. Xexpressions, as appropriate.
  173. X.TP
  174. X\-\fBP\fP
  175. Xrecognize the same escape sequences as in the \fBPROMPT\fP parameter.
  176. X.PD
  177. X.RE
  178. X.TP
  179. X.PD 0
  180. X\fBpushd\fP [ \fIarg\fP ]
  181. X.TP
  182. X\fBpushd\fP \fIold\fP \fInew\fP
  183. X.TP
  184. X\fBpushd\fP \(+-\fBn\fP
  185. X.PD
  186. XChange the current directory, and push the old current directory
  187. Xonto the directory stack.  In the first form, change the
  188. Xcurrent directory to \fIarg\fP.
  189. XIf \fIarg\fP is not specified, change to the second directory
  190. Xon the stack (that is, exchange the top two entries), or
  191. Xchange to the value of \fBHOME\fP if the \fBPUSHD_TO_HOME\fP
  192. Xoption is set or if there is only one entry on the stack.
  193. XIf \fIarg\fP is \-, change to the
  194. Xvalue of \fBOLDPWD\fP, the previous directory.
  195. XIf a directory named \fIarg\fP is not found in the current directory
  196. Xand \fIarg\fP does not contain a slash,
  197. Xsearch each component of the shell parameter \fBcdpath\fP.
  198. XIf the option \fBCDABLEVARS\fP is set, and a parameter named \fIarg\fP
  199. Xexists whose value begins with a slash, treat its value as
  200. Xthe directory.
  201. XIf the option \fBPUSHD_SILENT\fP is not set, the directory
  202. Xstack will be printed after a \fBpushd\fP is performed.
  203. X.RS
  204. X.PP
  205. XThe second form of \fBpushd\fP substitutes the string \fInew\fP
  206. Xfor the string \fIold\fP in the name of the current directory,
  207. Xand tries to change to this new directory.
  208. X.PP
  209. XThe third form of \fBpushd\fP is equivalent to \fBpopd\fP.
  210. X.RE
  211. X.TP
  212. X\fBpwd\fP
  213. XEquivalent to \fBprint \-R $PWD\fP.
  214. X.TP
  215. X\fBr\fP
  216. XEquivalent to \fBfc \-e \-\fP.
  217. X.TP
  218. X\fBread\fP [ \-\fBrzp\fP ] [ \-\fBu\fIn\fR ] [ \fIname\fP?\fIprompt\fP ] [ \fIname\fP ...  ]
  219. XRead one line and break it into fields using the characters
  220. Xin \fBIFS\fP as separators.  In raw mode, \-\fBr\fP, a \e
  221. Xat the end of a line does not signify line continuation.
  222. XIf the \-\fBz\fP flag is set, read from the editor buffer stack.
  223. XThe first field is assigned to the first \fIname\fP, the second field
  224. Xto the second \fIname\fP, etc., with leftover
  225. Xfields assigned to the last \fIname\fP.
  226. XIf \fIname\fP is omitted then \fBREPLY\fP is used.
  227. XIf \-\fBu\fIn\fR is specified, then input is read from file
  228. Xdescriptor \fIn\fP; if \-\fBp\fP is specified, then input is
  229. Xread from the coprocess.
  230. XThe exit status is 0 unless end-of-file is encountered.
  231. XIf the first argument contains a \fB?\fP, the remainder of this
  232. Xword is used as a \fIprompt\fP on standard error when the shell
  233. Xis interactive.  The exit status is 0 unless an end-of-file
  234. Xis encountered.
  235. X.TP
  236. X\fBreadonly\fP [ \fIname\fP[=\fIvalue\fP] ] ...
  237. XThe given \fInames\fP are marked readonly; these names
  238. Xcannot be changed by subsequent assignment.
  239. X.TP
  240. X\fBrehash\fP [ \-\fBf\fP ]
  241. XThrow out the command hash table and start over.
  242. XIf the \-\fBf\fP option is set, rescan the command path
  243. Ximmediately, instead of rebuilding the hash table incrementally.
  244. X.TP
  245. X\fBreturn\fP [ \fIn\fP ]
  246. XCauses a shell function or \fB\&.\fP script to return to
  247. Xthe invoking script
  248. Xwith the return status specified by \fIn\fP.  If \fIn\fP
  249. Xis omitted then the return status is that of the last command
  250. Xexecuted.
  251. X.TP
  252. X.PD 0
  253. X\fBsched\fP [+]\fIhh\fP:\fImm\fP \fIcommand\fP ...
  254. X.TP
  255. X\fBsched\fP [ \-\fIitem\fP ]
  256. X.PD
  257. XMake an entry in the scheduled list of commands to execute.
  258. XThe time may be specified in either absolute or relative time.
  259. XWith no arguments, prints the list of scheduled commands.
  260. XWith the argument \-\fIitem\fP, removes the given item
  261. Xfrom the list.
  262. X.TP
  263. X\fBset\fP [ \(+-\fIoptions\fP ] [ \(+-\fBo\fP \fIoption name\fP ] ... [ \-\fBA\fP \fIname\fP ] [ \fIarg\fP ] ...
  264. XSet the options for the shell and/or set the positional parameters, or
  265. Xdeclare an array.  For the meaning of the flags, see
  266. X\fBOPTIONS\fP above.
  267. XFlags may be specified by name using the \-\fBo\fP option.
  268. XIf the \-\fBA\fP flag is specified, \fIname\fP is set to an
  269. Xarray containing the given \fIarg\fPs.
  270. XOtherwise the positional parameters are set.
  271. XIf no arguments are given, then the names and values
  272. Xof all parameters are printed on the standard output.
  273. XIf the only argument is +, the names of all parameters are printed.
  274. X.TP
  275. X\fBsetopt\fP [ \(+-\fIoptions\fP ] [ \fIname\fP ... ]
  276. XSet the options for the shell.  All options specified either
  277. Xwith flags or by name are set.  If no arguments are supplied,
  278. Xthe names of all options currently set are printed.
  279. XIn option names, case is insignificant, and all underscore
  280. Xcharacters are ignored.
  281. X.TP
  282. X\fBshift\fP [ \fIn\fP ]
  283. XThe positional parameters from $\fIn\fP+\fB1\fP ... are renamed
  284. X$\fB1\fP, where \fIn\fP is an arithmetic expression that
  285. Xdefaults to 1.
  286. X.TP
  287. X\fBsource\fP
  288. XSame as \fB.\fP.
  289. X.TP
  290. X\fBsuspend\fP [ \-\fBf\fP ]
  291. XSuspend the execution of the shell (send it a \fBSIGTSTP\fP)
  292. Xuntil it receives a \fBSIGCONT\fP.
  293. XIf the \-\fBf\fP option is not given, complain if this is a login shell.
  294. X.TP
  295. X.PD 0
  296. X\fBtest\fP \fIarg\fP ...
  297. X.TP
  298. X\fB[\fP \fIarg\fP ... \fB]\fP
  299. X.PD
  300. XLike the system version of \fBtest\fP.  Added for compatibility;
  301. Xuse conditional expressions instead.
  302. X.TP
  303. X\fBtimes\fP
  304. XPrint the accumulated user and system times for the shell
  305. Xand for processes run from the shell.
  306. X.TP
  307. X\fBtrap\fP [ \fIarg\fP ] [ \fIsig\fP ] ...
  308. X\fIarg\fP is a command to be read and executed when the shell
  309. Xreceives \fIsig\fP.  Each \fIsig\fP can be given as a number
  310. Xor as the name of a signal.
  311. XIf \fIarg\fP is \-, then all traps \fIsig\fP are reset to their
  312. Xdefault values.  If \fIarg\fP is the null string, then this signal
  313. Xis ignored by the shell and by the commands it invokes.
  314. XIf \fIsig\fP is \fBERR\fP then \fIarg\fP will be executed
  315. Xafter each command.
  316. XIf \fIsig\fP is \fB0\fP or \fBEXIT\fP
  317. Xand the \fBtrap\fP statement is executed inside the body of a function,
  318. Xthen the command \fIarg\fP is executed after the function completes.
  319. XIf \fIsig\fP is \fB0\fP or \fBEXIT\fP
  320. Xand the \fBtrap\fP statement is not executed inside the body of a function,
  321. Xthen the command \fIarg\fP is executed when the shell terminates.
  322. XThe \fBtrap\fP command with no arguments prints a list of commands
  323. Xassociated with each signal.
  324. X.TP
  325. X\fBtrue\fP
  326. XDo nothing and return an exit code of 0.
  327. X.TP
  328. X\fBttyctl\fP \-\fBfu\fP
  329. XThe \-\fBf\fP option freezes the tty, and \-\fBu\fP unfreezes it.
  330. XWhen the tty is frozen, no changes made to the tty settings by
  331. Xexternal programs will be honored by the shell; the shell will
  332. Xsimply reset the settings to their previous values as soon as each
  333. Xcommand exits.  Thus, \fBstty\fP and similar programs have no
  334. Xeffect when the tty is frozen.
  335. X.TP
  336. X\fBtype\fP
  337. XSame as \fBwhence\fP \-\fBv\fP.
  338. X.TP
  339. X\fBtypeset\fP [ \(+-\fBLRZfilrtux [\fIn\fP]] [ \fIname\fP[=\fIvalue\fP] ] ...
  340. XSet attributes and values for shell parameters.
  341. XWhen invoked inside a function, if \fIname\fP is not already
  342. Xdefined, a new parameter is created which will be unset when the
  343. Xfunction completes.
  344. XThe following attributes are valid:
  345. X.RS
  346. X.PD 0
  347. X.TP
  348. X\-\fBL\fP
  349. XLeft justify and remove leading blanks from \fIvalue\fP.
  350. XIf \fIn\fP is nonzero, it defines the width of the field;
  351. Xotherwise it is determined by the width of the value of the first
  352. Xassignment.
  353. XWhen the parameter is printed, it is filled on the right with
  354. Xblanks or truncated if necessary to fit the field.
  355. XLeading zeros are removed if the \-\fBZ\fP flag is also set.
  356. X.TP
  357. X\-\fBR\fP
  358. XRight justify and fill with leading blanks.  If \fIn\fP is nonzero
  359. Xif defines the width of the field;
  360. Xotherwise it is determined by the width of the value of the first
  361. Xassignment.
  362. XWhen the parameter is printed, the field is left filled with
  363. Xblanks or truncated from the end.
  364. X.TP
  365. X\-\fBZ\fP
  366. XRight justify and fill with leading zeros if the first non-blank
  367. Xcharacter is a digit and the \-\fBL\fP flag has not been set.
  368. XIf \fIn\fP is nonzero it defines the width of the field;
  369. Xotherwise it is determined by the width of the value of the
  370. Xfirst assignment.
  371. X.TP
  372. X\-\fBf\fP
  373. XThe names refer to functions rather than parameters.  No assignments
  374. Xcan be made, and the only other valid flags are \-\fBt\fP
  375. Xand \-\fBu\fP.  The flag \-\fBt\fP turns on execution tracing for this
  376. Xfunction.  The flag \-\fBu\fP causes this function to be marked
  377. Xfor autoloading.  The \fBfpath\fP parameter will be searched to find the
  378. Xfunction definition when the function is first referenced.
  379. X.TP
  380. X\-\fBi\fP
  381. XUse an internal integer representation.  If \fBi\fP is nonzero
  382. Xit defines the output arithmetic base, otherwise it is determined by the first
  383. Xassignment.
  384. X.TP
  385. X\-\fBl\fP
  386. XConvert to lower case.
  387. X.TP
  388. X\-\fBr\fP
  389. XThe given \fIname\fPs are marked readonly.
  390. X.TP
  391. X\-\fBt\fP
  392. XTags the named parameters.  Tags have no special meaning to the shell.
  393. X.TP
  394. X\-\fBu\fP
  395. XConvert to upper case.
  396. X.TP
  397. X\-\fBx\fP
  398. XMark for automatic export to the environment of subsequently
  399. Xexecuted commands.
  400. X.RE
  401. X.PD
  402. X.PP
  403. XUsing + rather than \- causes these flags to be turned off.
  404. XIf no arguments are given but flags are specified,
  405. Xa list of named parameters which have these flags set is printed.
  406. XUsing + instead of \- keeps their values from being printed.
  407. XIf no arguments or options are given, the names and attributes
  408. Xof all parameters are printed.
  409. X.TP
  410. X\fBulimit\fP [ \-\fBHSacdfmnt\fP ] [ \fIlimit\fP ]
  411. XSet or display a resource limit.  The value of limit can be a number
  412. Xin the unit specified below or the value \fBunlimited\fP.
  413. XThe \fBH\fP and \fBS\fP flags specify whether the hard limit
  414. Xor the soft limit for the given resource is set.
  415. X.RS
  416. X.PD 0
  417. X.TP
  418. X\-\fBa\fP
  419. XLists all of the current resource limits.
  420. X.TP
  421. X\-\fBc\fP
  422. XThe number of 512-byte blocks on the size of core dumps.
  423. X.TP
  424. X\-\fBd\fP
  425. XThe number of K-bytes on the size of the data segment.
  426. X.TP
  427. X\-\fBf\fP
  428. XThe number of 512-byte blocks on the size of files written.
  429. X.TP
  430. X\-\fBm\fP
  431. XThe number of K-bytes on the size of physical memory.
  432. X.TP
  433. X\-\fBn\fP
  434. XThe number of file descriptors.
  435. X.TP
  436. X\-\fBs\fP
  437. XThe number of K-bytes on the size of the stack.
  438. X.TP
  439. X\-\fBt\fP
  440. XThe number of CPU seconds to be used.
  441. X.RE
  442. X.PD
  443. X.TP
  444. X\fBumask\fP [ \fImask\fP ]
  445. XThe umask is set to \fImask\fP.  \fImask\fP can be either
  446. Xan octal number or a symbolic value as described in \fBchmod\fP(1).
  447. XIf \fImask\fP is omitted, the current value is printed.
  448. X.TP
  449. X\fBunalias\fP \fIname\fP ...
  450. XThe alias definition, if any, for each \fIname\fP is removed.
  451. X.TP
  452. X\fBunfunction\fP \fIname\fP ...
  453. XThe function definition, if any, for each \fIname\fP is removed.
  454. X.TP
  455. X\fBunhash\fP \fIname\fP ...
  456. XThe entry in the command hash table, if any, for each \fIname\fP
  457. Xis removed.
  458. X.TP
  459. X\fBunlimit\fP [ \-\fBh\fP ] \fIresource\fP ...
  460. XThe resource limit for each \fIresource\fP is set to the hard limit.
  461. XIf the \-\fBh\fP flag is given and the shell is running as root,
  462. Xthe hard resource limit for each \fIresource\fP is removed.
  463. X.TP
  464. X\fBunset\fP \fIname\fP ...
  465. XEach named parameter is unset.
  466. X.TP
  467. X\fBunsetopt\fP [ \(+-\fIoptions\fP ] [ \fIname\fP ... ]
  468. XUnset the options for the shell.  All options specified either
  469. Xwith flags or by name are unset.
  470. X.TP
  471. X\fBvared\fP \fIname\fP
  472. XThe value of the parameter \fIname\fP is loaded into the edit
  473. Xbuffer, and the line editor is invoked.  When the editor exits,
  474. X\fIname\fP is set to the string value returned by the editor.
  475. X.TP
  476. X\fBwait\fP [ \fIjob\fP ... ]
  477. XWait for the specified jobs or processes.  If \fIjob\fP is not given
  478. Xthen all currently active child processes are waited for.
  479. XEach \fIjob\fP can be either a job specification or the process-id
  480. Xof a job in the job table.
  481. XThe exit status from this command is that of the job waited for.
  482. X.TP
  483. X\fBwhence\fP [ \-\fBacpv\fP ] \fIname\fP ...
  484. XFor each name, indicate how it would be interpreted if used
  485. Xas a command name.  The \-\fBv\fP flag produces a more verbose
  486. Xreport.  The \-\fBp\fP flag does a path search for \fIname\fP
  487. Xeven if it is a shell function, alias, or reserved word.
  488. XThe \-\fBc\fP flag prints the results in a csh-like format.
  489. XThe \-\fBa\fP flag does a search for all occurences of \fIname\fP
  490. Xthroughout the command path.
  491. X.TP
  492. X\fBwhich\fP
  493. XSame as \fBwhence \-c\fP.
  494. X.RE
  495. X.SH INVOCATION
  496. XCommands are first read from /etc/zshenv.
  497. XThen, if the \fBNO_RCS\fP option is unset, commands are read
  498. Xfrom $ZDOTDIR/.zshenv.
  499. X(If \fBZDOTDIR\fP is unset, \fBHOME\fP is used instead).
  500. XIf the first character of argument zero passed to the shell
  501. Xis \-, or if the \-\fBl\fP flag is present, then the shell is
  502. Xassumed to be a login shell, and commands
  503. Xare read from /etc/zprofile and then $ZDOTDIR/.zprofile.
  504. XThen, if the shell is interactive and the \fBNO_RCS\fP option is unset,
  505. Xcommands are read from /etc/zshrc and then $ZDOTDIR/.zshrc.
  506. XFinally, if the shell is a login shell, /etc/zlogin and $ZDOTDIR/.zlogin
  507. Xare read.
  508. X.PP
  509. XIf the \fBNO_RCS\fP option is set within /etc/zshenv, then only /etc/zprofile,
  510. X/etc/zshrc, and /etc/zlogin are read, and the $ZDOTDIR files are skipped.
  511. XIf the \-\fBf\fP flag is present, only /etc/zshenv is read, and all other
  512. Xinitialization files are skipped.
  513. X.PP
  514. XIf the \-\fBs\fP flag is not present and an argument is given,
  515. Xthe first argument is taken to be the pathname of a script to
  516. Xexecute.  The remaining arguments are assigned to the positional
  517. Xparameters.  The following flags are interpreted by the shell
  518. Xwhen invoked:
  519. X.TP
  520. X.PD 0
  521. X\-\fBc\fP \fIstring\fP
  522. XRead commands from \fIstring\fP.
  523. X.TP
  524. X\-\fBs\fP
  525. XRead command from the standard input.
  526. X.TP
  527. X\-\fBi\fP
  528. XIf this flag is present or the shell input and output
  529. Xare attached to a terminal, this shell is interactive.
  530. X.PD
  531. X.SH "SEE ALSO"
  532. Xsh(1),
  533. Xcsh(1),
  534. Xtcsh(1),
  535. Xitcsh(1),
  536. Xrc(1),
  537. Xbash(1),
  538. Xash(1),
  539. Xksh(1),
  540. Xclam(1),
  541. Xstrftime(3).
  542. X.SH FILES
  543. X$ZDOTDIR/.zshenv
  544. X.br
  545. X$ZDOTDIR/.zprofile
  546. X.br
  547. X$ZDOTDIR/.zshrc
  548. X.br
  549. X$ZDOTDIR/.zlogin
  550. X.br
  551. X$ZDOTDIR/.zlogout
  552. X.br
  553. X/tmp/zsh*
  554. X.br
  555. X/etc/zshenv
  556. X.br
  557. X/etc/zprofile
  558. X.br
  559. X/etc/zshrc
  560. X.br
  561. X/etc/zlogin
  562. X.SH AUTHOR
  563. XPaul Falstad (pf@ttisms.com)
  564. X.SH AVAILABILITY
  565. XThe latest official release of zsh is available via anonymous ftp from
  566. Xcs.ucsd.edu (132.239.51.3), in the directory pub/zsh.  The beta release
  567. Xof zsh 2.4 is available from carlo.phys.uva.nl (145.18.220.25), in the
  568. Xdirectory pub/bas/zsh.  This man page is current to zsh 2.3.1.
  569. X.SH "UNDOCUMENTED FEATURES"
  570. XKnown only to the recipients of the zsh mailing list, zsh-list@cs.uow.edu.au. 
  571. XIf you run into problems, please send your questions and patches to the
  572. Xmailing list.  To join the list, send email to zsh-request@cs.uow.edu.au.
  573. END_OF_FILE
  574.   if test 17067 -ne `wc -c <'man/man1/zsh.1.03'`; then
  575.     echo shar: \"'man/man1/zsh.1.03'\" unpacked with wrong size!
  576.   fi
  577.   # end of 'man/man1/zsh.1.03'
  578. fi
  579. if test -f 'src/builtin.c.02' -a "${1}" != "-c" ; then 
  580.   echo shar: Will not clobber existing file \"'src/builtin.c.02'\"
  581. else
  582.   echo shar: Extracting \"'src/builtin.c.02'\" \(16952 characters\)
  583.   sed "s/^X//" >'src/builtin.c.02' <<'END_OF_FILE'
  584. Xchar *s;char *t;
  585. Xstruct param *pm;
  586. X
  587. X    if (!(s = getsparam(args[0]))) {
  588. X        zerrnam(name,"no such variable: %s",args[0],0);
  589. X        return 1;
  590. X    }
  591. X    permalloc();
  592. X    pushnode(bufstack,ztrdup(s));
  593. X    heapalloc();
  594. X    t = (char *) zleread((unsigned char *)"> ",NULL,2);
  595. X    if (!t || errflag)
  596. X        return 1;
  597. X    if (t[strlen(t)-1] == '\n')
  598. X        t[strlen(t)-1] = '\0';
  599. X    pm = gethnode(args[0],paramtab);
  600. X    if (pmtype(pm) == PMFLAG_A)
  601. X        setaparam(args[0],spacesplit(t));
  602. X    else
  603. X        setsparam(args[0],t);
  604. X    return 0;
  605. X}
  606. X
  607. X#define fset(X) (flags & X)
  608. X
  609. X/* execute a builtin handler function after parsing the arguments */
  610. X
  611. Xint execbin(args,cnode) /**/
  612. XLklist args;Cmdnam cnode;
  613. X{
  614. Xstruct bincmd *b;
  615. Xchar ops[128],*arg,*pp,*name,**argv,**oargv,*optstr;
  616. Xint t0,flags,sense,argc = 0,op;
  617. XLknode n;
  618. X
  619. X    auxdata = NULL;
  620. X    auxlen = 0;
  621. X    for (t0 = 0; t0 != 128; t0++)
  622. X        ops[t0] = 0;
  623. X    name = ugetnode(args);
  624. X    b = builtins+cnode->u.binnum;
  625. X
  626. X/* the 'builtin' builtin is handled specially */
  627. X
  628. X    if (b->funcid == BIN_BUILTIN)
  629. X        {
  630. X        if (!(name = ugetnode(args)))
  631. X            {
  632. X            zerrnam("builtin","command name expected",NULL,0);
  633. X            return 1;
  634. X            }
  635. X        for (b = builtins; b->name; b++)
  636. X            if (!strcmp(name,b->name))
  637. X                break;
  638. X        if (!b->name)
  639. X            {
  640. X            zerrnam("builtin","no such builtin: %s",name,0);
  641. X            return 1;
  642. X            }
  643. X        }
  644. X    flags = b->flags;
  645. X    arg = ugetnode(args);
  646. X    optstr = b->optstr;
  647. X    if (flags & BINF_ECHOPTS && arg && strcmp(arg,"-n"))
  648. X        optstr = NULL;
  649. X    if (optstr)
  650. X        while (arg &&
  651. X                ((sense = *arg == '-') || (fset(BINF_PLUSOPTS) && *arg == '+')) &&
  652. X                (fset(BINF_PLUSOPTS) || !atoi(arg)))
  653. X            {
  654. X            if (arg[1] == '-')
  655. X                arg++;
  656. X            if (!arg[1])
  657. X                {
  658. X                ops['-'] = 1;
  659. X                if (!sense)
  660. X                    ops['+'] = 1;
  661. X                }
  662. X            else
  663. X                ops['@'] = 1;
  664. X            op = -1;
  665. X            while (*++arg)
  666. X                if (strchr(b->optstr,op = *arg))
  667. X                    ops[(int)*arg] = (sense) ? 1 : 2;
  668. X                else
  669. X                    break;
  670. X            if (*arg)
  671. X                {
  672. X                zerr("bad option: %c",NULL,*arg);
  673. X                return 1;
  674. X                }
  675. X            arg = ugetnode(args);
  676. X            if (fset(BINF_SETOPTS) && op == 'o')
  677. X                {
  678. X                int c;
  679. X                
  680. X                if (!arg)
  681. X                    prtopt();
  682. X                else
  683. X                    {
  684. X                    c = optlookup(arg);
  685. X                    if (c == -1)
  686. X                        {
  687. X                        zerr("bad option: %s",arg,0);
  688. X                        return 1;
  689. X                        }
  690. X                    else
  691. X                        {
  692. X                        if (c == INTERACTIVE)
  693. X                            zerr("can't change option: %s",arg,0);
  694. X                        else
  695. X                            ops[c] = ops['o'];
  696. X                        arg = ugetnode(args);
  697. X                        }
  698. X                    }
  699. X                }
  700. X            if ((fset(BINF_PRINTOPTS) && ops['R']) || ops['-'])
  701. X                break;
  702. X            if (fset(BINF_SETOPTS) && ops['A'])
  703. X                {
  704. X                auxdata = arg;
  705. X                arg = ugetnode(args);
  706. X                break;
  707. X                }
  708. X            if (fset(BINF_FCOPTS) && op == 'e')
  709. X                {
  710. X                auxdata = arg;
  711. X                arg = ugetnode(args);
  712. X                }
  713. X            if (fset(BINF_TYPEOPT) && (op == 'L' || op == 'R' ||
  714. X                    op == 'Z' || op == 'i') && arg && idigit(*arg))
  715. X                {
  716. X                auxlen = atoi(arg);
  717. X                arg = ugetnode(args);
  718. X                }
  719. X            }
  720. X    if (fset(BINF_R))
  721. X        auxdata = "-";
  722. X    if (pp = b->defopts)
  723. X        while (*pp)
  724. X            ops[(int)*pp++] = 1;
  725. X    if (arg)
  726. X        {
  727. X        argc = 1;
  728. X        n = firstnode(args);
  729. X        while (n)
  730. X            argc++,incnode(n);
  731. X        }
  732. X    oargv = argv = (char **) ncalloc(sizeof(char **) * (argc+1));
  733. X    if (*argv++ = arg)
  734. X        while (*argv++ = ugetnode(args));
  735. X    argv = oargv;
  736. X    if (errflag)
  737. X        return 1;
  738. X    if (argc < b->minargs || (argc > b->maxargs && b->maxargs != -1)) {
  739. X        zerrnam(name,(argc < b->minargs)
  740. X            ? "not enough arguments" : "too many arguments",NULL,0);
  741. X        return 1;
  742. X    }
  743. X    if (isset(XTRACE)) {
  744. X        char **pp = argv;
  745. X        fprintf(stderr,"%s%s",(prompt4) ? prompt4 : "",name);
  746. X        while (*pp) fprintf(stderr," %s",*pp++);
  747. X        fputc('\n',stderr);
  748. X        fflush(stderr);
  749. X    }
  750. X    return (*(b->handlerfunc))(name,argv,ops,b->funcid);
  751. X}
  752. X
  753. Xstruct asgment *getasg(s) /**/
  754. Xchar *s;
  755. X{
  756. Xstatic struct asgment asg;
  757. X
  758. X    if (!s)
  759. X        return NULL;
  760. X    if (*s == '=')
  761. X        {
  762. X        zerr("bad assignment",NULL,0);
  763. X        return NULL;
  764. X        }
  765. X    asg.name = s;
  766. X    for (; *s && *s != '='; s++);
  767. X    if (*s)
  768. X        {
  769. X        *s = '\0';
  770. X        asg.value = s+1;
  771. X        }
  772. X    else
  773. X        asg.value = NULL;
  774. X    return &asg;
  775. X}
  776. X
  777. X/* ., source */
  778. X
  779. Xint bin_dot(name,argv,ops,func) /**/
  780. Xchar *name;char **argv;char *ops;int func;
  781. X{
  782. Xchar **old,*old0;
  783. Xint ret;
  784. Xchar buf[MAXPATHLEN];
  785. Xchar *s,**t,*enam;
  786. X
  787. X    if (!*argv)
  788. X        return 0;
  789. X    old = pparams;
  790. X    old0 = argzero;
  791. X    if (argv[1]) {
  792. X        permalloc();
  793. X        pparams = arrdup(argv+1);
  794. X        heapalloc();
  795. X    }
  796. X    enam = argzero = ztrdup(*argv);
  797. X    errno = ENOENT;
  798. X    ret = 1;
  799. X    for (s = argzero; *s; s++)
  800. X        if (*s == '/') {
  801. X            ret = source(argzero);
  802. X            break;
  803. X        }
  804. X    if (!*s) {
  805. X        for (t = path; *t; t++)
  806. X            if ((*t)[0] == '.' && !(*t)[1]) {
  807. X                ret = source(argzero);
  808. X                break;
  809. X            } else {
  810. X                sprintf(buf,"%s/%s",*t,argzero);
  811. X                if (access(buf,F_OK) == 0) {
  812. X                    ret = source(enam = buf);
  813. X                    break;
  814. X                }
  815. X            }
  816. X        if (!*t && access(argzero,F_OK) == 0)
  817. X            ret = source(enam = argzero);
  818. X    }
  819. X    if (argv[1]) {
  820. X        freearray(pparams);
  821. X        pparams = old;
  822. X    }
  823. X    if (ret) zerrnam(name,"%e: %s",enam,errno);
  824. X    free(argzero);
  825. X    argzero = old0;
  826. X    return ret;
  827. X}
  828. X
  829. Xint bin_set(name,argv,ops,func) /**/
  830. Xchar *name;char **argv;char *ops;int func;
  831. X{
  832. Xstruct option *opp;
  833. Xchar **x;
  834. X
  835. X    if (((ops['+'] && ops['-']) || !ops['-']) && !ops['@'] && !*argv)
  836. X        {
  837. X        showflag = ~0;
  838. X        showflag2 = ops['+'];
  839. X        listhtable(paramtab,(HFunc) printparam);
  840. X        }
  841. X   for (opp = optns; opp->name; opp++)
  842. X      if (ops[(int)opp->id] == 1)
  843. X         opts[(int)opp->id] = OPT_SET;
  844. X      else if (ops[(int)opp->id] == 2)
  845. X         opts[(int)opp->id] = OPT_UNSET;
  846. X    if (!*argv && !ops['-'])
  847. X        return 0;
  848. X    permalloc();
  849. X    x = arrdup(argv);
  850. X    heapalloc();
  851. X    if (ops['A'])
  852. X        setaparam(auxdata,x);
  853. X    else {
  854. X        freearray(pparams);
  855. X        pparams = x;
  856. X    }
  857. X    return 0;
  858. X}
  859. X
  860. X#define pttime(X) printf("%dm%ds",(X)/3600,(X)/60%60)
  861. X
  862. Xint bin_times(name,argv,ops,func) /**/
  863. Xchar *name;char **argv;char *ops;int func;
  864. X{
  865. Xstruct tms buf;
  866. X
  867. X    if (times(&buf) == -1)
  868. X        return 1;
  869. X    pttime(buf.tms_utime);
  870. X    putchar(' ');
  871. X    pttime(buf.tms_stime);
  872. X    putchar('\n');
  873. X    pttime(buf.tms_cutime);
  874. X    putchar(' ');
  875. X    pttime(buf.tms_cstime);
  876. X    putchar('\n');
  877. X    return 0;
  878. X}
  879. X
  880. Xint bin_getopts(name,argv,ops,func) /**/
  881. Xchar *name;char **argv;char *ops;int func;
  882. X{
  883. Xchar *optstr = *argv++,*var = *argv++;
  884. Xchar **args = (*argv) ? argv : pparams;
  885. Xstatic int optcind = 1,quiet;
  886. Xchar *str,optbuf[3],*opch = optbuf+1;
  887. X
  888. X    if (zoptind < 1) zoptind = 1;
  889. X    optbuf[0] = '+'; optbuf[1] = optbuf[2] = '\0';
  890. X    if (optarg) free(optarg);
  891. X    optarg = ztrdup("");
  892. X    setsparam(var,ztrdup(""));
  893. X    if (*optstr == ':') {
  894. X        quiet = 1;
  895. X        optstr++;
  896. X    }
  897. X    if (zoptind > arrlen(args)) return 1;
  898. X    str = args[zoptind-1];
  899. X    if ((*str != '+' && *str != '-') || optcind >= strlen(str) ||
  900. X            !strcmp("--",str)) {
  901. X        if (*str == '+' || *str == '-')
  902. X            zoptind++;
  903. X        optcind = 0;
  904. X        return 1;
  905. X    }
  906. X    if (!optcind)
  907. X        optcind = 1;
  908. X    *opch = str[optcind++];
  909. X    if (!args[zoptind-1][optcind]) {
  910. X        zoptind++;
  911. X        optcind = 0;
  912. X    }
  913. X    for (; *optstr; optstr++)
  914. X        if (*opch == *optstr)
  915. X            break;
  916. X    if (!*optstr) {
  917. X        setsparam(var,ztrdup("?"));
  918. X        if (quiet) {
  919. X            free(optarg); optarg = ztrdup(opch);
  920. X            return 0;
  921. X        }
  922. X        zerr("bad option: %c",NULL,*opch); errflag = 0;
  923. X        return 0;
  924. X    }
  925. X    setsparam(var,ztrdup(opch-(*str == '+')));
  926. X    if (optstr[1] == ':') {
  927. X        if (!args[zoptind-1]) {
  928. X            if (quiet) {
  929. X                free(optarg); optarg = ztrdup(opch);
  930. X                setsparam(var,ztrdup(":"));
  931. X                return 0;
  932. X            }
  933. X            setsparam(var,ztrdup("?"));
  934. X            zerr("argument expected after %c option",NULL,*opch); errflag = 0;
  935. X            return 0;
  936. X        }
  937. X        free(optarg);
  938. X        optarg = ztrdup(args[zoptind-1]+optcind);
  939. X        zoptind++;
  940. X        optcind = 0;
  941. X    }
  942. X    return 0;
  943. X}
  944. X
  945. X/* get a signal number from a string */
  946. X
  947. Xint getsignum(s) /**/
  948. Xchar *s;
  949. X{
  950. Xint x = atoi(s),t0;
  951. X
  952. X    if (idigit(*s) && x >= 0 && x < VSIGCOUNT)
  953. X        return x;
  954. X    for (t0 = 0; t0 != VSIGCOUNT; t0++)
  955. X        if (!strcmp(s,sigs[t0]))
  956. X            return t0;
  957. X    return -1;
  958. X}
  959. X
  960. Xint bin_trap(name,argv,ops,func) /**/
  961. Xchar *name;char **argv;char *ops;int func;
  962. X{
  963. XList l;
  964. Xchar *arg;
  965. X
  966. X    if (!*argv) {
  967. X        int t0;
  968. X
  969. X        for (t0 = 0; t0 != VSIGCOUNT; t0++)
  970. X            if (sigtrapped[t0])
  971. X                if (!sigfuncs[t0])
  972. X                    printf("TRAP%s () {}\n",sigs[t0]);
  973. X                else {
  974. X                    char *s = getpermtext((vptr) sigfuncs[t0]);
  975. X                    printf("TRAP%s () {\n\t%s\n}\n",sigs[t0],s);
  976. X                    free(s);
  977. X                }
  978. X        return 0;
  979. X    }
  980. X    if (!strcmp(*argv,"-")) {
  981. X        int t0;
  982. X
  983. X        argv++;
  984. X        if (!*argv)
  985. X            for (t0 = 0; t0 != VSIGCOUNT; t0++) unsettrap(t0);
  986. X        else
  987. X            while (*argv) unsettrap(getsignum(*argv++));
  988. X        return 0;
  989. X    }
  990. X    arg = *argv++;
  991. X    if (!*arg) l = NULL;
  992. X    else if (!(l = parselstring(arg))) {
  993. X        zerrnam(name,"couldn't parse trap command",NULL,0);
  994. X        popheap();
  995. X        return 1;
  996. X    }
  997. X    for (; *argv; argv++) {
  998. X        int sg = getsignum(*argv);
  999. X        if (sg == -1) {
  1000. X            zerrnam(name,"undefined signal: %s",*argv,0);
  1001. X            break;
  1002. X        }
  1003. X        settrap(sg,l);
  1004. X    }
  1005. X    if (l) popheap();
  1006. X    return errflag;
  1007. X}
  1008. X
  1009. Xvoid printulimit(lim,hard) /**/
  1010. Xint lim;int hard;
  1011. X{
  1012. Xlong t0;
  1013. X
  1014. X#ifdef RLIM_INFINITY
  1015. X    t0 = (hard) ? limits[lim].rlim_max : limits[lim].rlim_cur;
  1016. X    switch (lim)
  1017. X        {
  1018. X        case RLIMIT_CPU: printf("cpu time (seconds)         "); break;
  1019. X        case RLIMIT_FSIZE: printf("file size (blocks)         "); t0 /= 512; break;
  1020. X        case RLIMIT_DATA: printf("data seg size (kbytes)     "); t0 /= 1024; break;
  1021. X        case RLIMIT_STACK: printf("stack size (kbytes)        "); t0 /= 1024; break;
  1022. X        case RLIMIT_CORE: printf("core file size (blocks)    "); t0 /= 512; break;
  1023. X#ifdef RLIMIT_RSS
  1024. X        case RLIMIT_RSS: printf("resident set size (kbytes) "); t0 /= 1024; break;
  1025. X#endif
  1026. X#ifdef RLIMIT_MEMLOCK
  1027. X        case RLIMIT_MEMLOCK: printf("locked-in-memory size (kb) "); t0 /= 1024; break;
  1028. X#endif
  1029. X#ifdef RLIMIT_NPROC
  1030. X        case RLIMIT_NPROC: printf("processes                  "); break;
  1031. X#endif
  1032. X#ifdef RLIMIT_OFILE
  1033. X        case RLIMIT_OFILE: printf("open files                 "); break;
  1034. X#endif
  1035. X#ifdef RLIMIT_NOFILE
  1036. X        case RLIMIT_NOFILE: printf("file descriptors           "); break;
  1037. X#endif
  1038. X        }
  1039. X    printf("%ld\n",t0);
  1040. X#endif
  1041. X}
  1042. X
  1043. Xint bin_ulimit(name,argv,ops,func) /**/
  1044. Xchar *name;char **argv;char *ops;int func;
  1045. X{
  1046. Xint res,hard;
  1047. X
  1048. X#ifndef RLIM_INFINITY
  1049. X    zerrnam(name,"not available on this system",NULL,0);
  1050. X    return 1;
  1051. X#else
  1052. X    hard = ops['H'];
  1053. X    if (ops['a'] || !ops['@'])
  1054. X        res = -1;
  1055. X    else if (ops['t'])
  1056. X        res = RLIMIT_CPU;
  1057. X    else if (ops['f'])
  1058. X        res = RLIMIT_FSIZE;
  1059. X    else if (ops['d'])
  1060. X        res = RLIMIT_DATA;
  1061. X    else if (ops['s'])
  1062. X        res = RLIMIT_STACK;
  1063. X    else if (ops['c'])
  1064. X        res = RLIMIT_CORE;
  1065. X#ifdef RLIMIT_RSS
  1066. X    else if (ops['m'])
  1067. X        res = RLIMIT_RSS;
  1068. X#endif
  1069. X#ifdef RLIMIT_MEMLOCK
  1070. X    else if (ops['l'])
  1071. X        res = RLIMIT_MEMLOCK;
  1072. X#endif
  1073. X#ifdef RLIMIT_NPROC
  1074. X    else if (ops['p'])
  1075. X        res = RLIMIT_NPROC;
  1076. X#endif
  1077. X#ifdef RLIMIT_OFILE
  1078. X    else if (ops['o'])
  1079. X        res = RLIMIT_OFILE;
  1080. X#endif
  1081. X#ifdef RLIMIT_NOFILE
  1082. X    else if (ops['n'])
  1083. X        res = RLIMIT_NOFILE;
  1084. X#endif
  1085. X    else
  1086. X        {
  1087. X        zerrnam(name,"no such limit",NULL,0);
  1088. X        return 1;
  1089. X        }
  1090. X    if (res == -1)
  1091. X        if (*argv)
  1092. X            {
  1093. X            zerrnam(name,"no arguments required after -a",NULL,0);
  1094. X            return 1;
  1095. X            }
  1096. X        else
  1097. X            {
  1098. X            int t0;
  1099. X
  1100. X            for (t0 = 0; t0 != RLIM_NLIMITS; t0++)
  1101. X                printulimit(t0,hard);
  1102. X            return 0;
  1103. X            }
  1104. X    if (!*argv)
  1105. X        printulimit(res,hard);
  1106. X    else if (strcmp(*argv,"unlimited"))
  1107. X        {
  1108. X        long t0;
  1109. X        
  1110. X        t0 = atol(*argv);
  1111. X        switch(res)
  1112. X            {
  1113. X            case RLIMIT_FSIZE: case RLIMIT_CORE: t0 *= 512; break;
  1114. X            case RLIMIT_DATA: case RLIMIT_STACK:
  1115. X#ifdef RLIMIT_RSS
  1116. X            case RLIMIT_RSS:
  1117. X#endif
  1118. X#ifdef RLIMIT_MEMLOCK
  1119. X            case RLIMIT_MEMLOCK:
  1120. X#endif
  1121. X                t0 *= 1024; break;
  1122. X            }
  1123. X        if (hard)
  1124. X            {
  1125. X            if (t0 > limits[res].rlim_max && geteuid())
  1126. X                {
  1127. X                zerrnam(name,"can't raise hard limits",NULL,0);
  1128. X                return 1;
  1129. X                }
  1130. X            limits[res].rlim_max = t0;
  1131. X            }
  1132. X        else
  1133. X            {
  1134. X            if (t0 > limits[res].rlim_max)
  1135. X                {
  1136. X                if (geteuid())
  1137. X                    {
  1138. X                    zerrnam(name,"value exceeds hard limit",NULL,0);
  1139. X                    return 1;
  1140. X                    }
  1141. X                limits[res].rlim_max = limits[res].rlim_cur = t0;
  1142. X                }
  1143. X            else
  1144. X                limits[res].rlim_cur = t0;
  1145. X            }
  1146. X        }
  1147. X    else
  1148. X        {
  1149. X        if (hard)
  1150. X            {
  1151. X            if (geteuid())
  1152. X                {
  1153. X                zerrnam(name,"can't remove hard limits",NULL,0);
  1154. X                return 1;
  1155. X                }
  1156. X            limits[res].rlim_max = RLIM_INFINITY;
  1157. X            }
  1158. X        else
  1159. X            limits[res].rlim_cur = limits[res].rlim_max;
  1160. X        }
  1161. X    return 0;
  1162. X#endif
  1163. X}
  1164. X
  1165. Xint putraw(c) /**/
  1166. Xint c;
  1167. X{
  1168. X    putchar(c);
  1169. X    return 0;
  1170. X}
  1171. X
  1172. Xint bin_echotc(name,argv,ops,func) /**/
  1173. Xchar *name;char **argv;char *ops;int func;
  1174. X{
  1175. Xchar *s,buf[2048],*t,*u;
  1176. Xint num,argct,t0;
  1177. X
  1178. X    s = *argv++;
  1179. X    if (!termok)
  1180. X        return 1;
  1181. X    if ((num = tgetnum(s)) != -1)
  1182. X        {
  1183. X        printf("%d\n",num);
  1184. X        return 0;
  1185. X        }
  1186. X    u = buf;
  1187. X    t = tgetstr(s,&u);
  1188. X    if (!t || !*t)
  1189. X        {
  1190. X        zerrnam(name,"no such capability: %s",s,0);
  1191. X        return 1;
  1192. X        }
  1193. X    for (argct = 0, u = t; *u; u++)
  1194. X        if (*u == '%')
  1195. X            {
  1196. X            if (u++, (*u == 'd' || *u == '2' || *u == '3' || *u == '.' ||
  1197. X                    *u == '+'))
  1198. X                argct++;
  1199. X            }
  1200. X    if (arrlen(argv) != argct)
  1201. X        {
  1202. X        zerrnam(name,(arrlen(argv) < argct) ? "not enough arguments" :
  1203. X            "too many arguments",NULL,0);
  1204. X        return 1;
  1205. X        }
  1206. X    if (!argct)
  1207. X        tputs(t,1,putraw);
  1208. X    else
  1209. X        {
  1210. X        t0 = (argv[1]) ? atoi(argv[1]) : atoi(*argv);
  1211. X        tputs(tgoto(t,atoi(*argv),t0),t0,putraw);
  1212. X        }
  1213. X    return 0;
  1214. X}
  1215. X
  1216. Xint bin_pwd(name,argv,ops,func) /**/
  1217. Xchar *name;char **argv;char *ops;int func;
  1218. X{
  1219. X    printf("%s\n",pwd);
  1220. X    return 0;
  1221. X}
  1222. X
  1223. X#define TEST_END 0
  1224. X#define TEST_INPAR 1
  1225. X#define TEST_OUTPAR 2
  1226. X#define TEST_STR 3
  1227. X#define TEST_AND 4
  1228. X#define TEST_OR 5
  1229. X#define TEST_NOT 6
  1230. X
  1231. Xstatic char **tsp;
  1232. Xstatic int *tip;
  1233. X
  1234. Xint bin_test(name,argv,ops,func) /**/
  1235. Xchar *name;char **argv;char *ops;int func;
  1236. X{
  1237. Xchar **s;
  1238. Xint cnt,*arr,*ap;
  1239. XCond c;
  1240. X
  1241. X    if (func == BIN_BRACKET)
  1242. X        {
  1243. X        for (s = argv; *s; s++);
  1244. X        if (s == argv || strcmp(s[-1],"]"))
  1245. X            {
  1246. X            zerrnam(name,"']' expected",NULL,0);
  1247. X            return 1;
  1248. X            }
  1249. X        s[-1] = NULL;
  1250. X        }
  1251. X    for (s = argv, cnt = 0; *s; s++,cnt++);
  1252. X    ap = arr = alloc((cnt+1)*sizeof *arr);
  1253. X    for (s = argv; *s; s++,ap++)
  1254. X        if (!strcmp(*s,"("))
  1255. X            *ap = TEST_INPAR;
  1256. X        else if (!strcmp(*s,")"))
  1257. X            *ap = TEST_OUTPAR;
  1258. X        else if (!strcmp(*s,"-a"))
  1259. X            *ap = TEST_AND;
  1260. X        else if (!strcmp(*s,"-o"))
  1261. X            *ap = TEST_OR;
  1262. X        else if (!strcmp(*s,"!"))
  1263. X            *ap = TEST_NOT;
  1264. X        else
  1265. X            *ap = TEST_STR;
  1266. X    *ap = TEST_END;
  1267. X    tsp = argv;
  1268. X    tip = arr;
  1269. X    c = partest(0);
  1270. X    if (*tip != TEST_END || errflag)
  1271. X        {
  1272. X        zerrnam(name,"parse error",NULL,0);
  1273. X        return 1;
  1274. X        }
  1275. X    return (c) ? !evalcond(c) : 1;
  1276. X}
  1277. X
  1278. XCond partest(level) /**/
  1279. Xint level;
  1280. X{
  1281. XCond a,b;
  1282. X
  1283. X    switch (level)
  1284. X        {
  1285. X        case 0:
  1286. X            a = partest(1);
  1287. X            if (*tip == TEST_OR)
  1288. X                {
  1289. X                tip++,tsp++;
  1290. X                b = makecond();
  1291. X                b->left = a;
  1292. X                b->right = partest(0);
  1293. X                b->type = COND_OR;
  1294. X                return b;
  1295. X                }
  1296. X            return a;
  1297. X        case 1:
  1298. X            a = partest(2);
  1299. X            if (*tip == TEST_AND)
  1300. X                {
  1301. X                tip++,tsp++;
  1302. X                b = makecond();
  1303. X                b->left = a;
  1304. X                b->right = partest(1);
  1305. X                b->type = COND_AND;
  1306. X                return b;
  1307. X                }
  1308. X            return a;
  1309. X        case 2:
  1310. X            if (*tip == TEST_NOT)
  1311. X                {
  1312. X                tip++,tsp++;
  1313. X                b = makecond();
  1314. X                b->left = partest(2);
  1315. X                b->type = COND_NOT;
  1316. X                return b;
  1317. X                }
  1318. X        case 3:
  1319. X            if (*tip == TEST_INPAR)
  1320. X                {
  1321. X                tip++,tsp++;
  1322. X                b = partest(0);
  1323. X                if (*tip != TEST_OUTPAR)
  1324. X                    {
  1325. X                    zerrnam("test","parse error",NULL,0);
  1326. X                    return NULL;
  1327. X                    }
  1328. X                tip++,tsp++;
  1329. X                return b;
  1330. X                }
  1331. X            if (tip[0] != TEST_STR)
  1332. X                {
  1333. X                zerrnam("test","parse error",NULL,0);
  1334. X                return NULL;
  1335. X                }
  1336. X            else if (tip[1] != TEST_STR)
  1337. X                {
  1338. X                b = makecond();
  1339. X                if (!strcmp(*tsp,"-t"))
  1340. X                    {
  1341. X                    b->left = strdup("1");
  1342. X                    b->type = 't';
  1343. X                    }
  1344. X                else
  1345. X                    {
  1346. X                    b->left = tsp[0];
  1347. X                    b->type = 'n';
  1348. X                    }
  1349. X                tip++,tsp++;
  1350. X                return b;
  1351. X                }
  1352. X            else if (tip[2] != TEST_STR)
  1353. X                {
  1354. X                b = par_cond_double(tsp[0],tsp[1]);
  1355. X                tip += 2,tsp += 2;
  1356. X                return b;
  1357. X                }
  1358. X            else
  1359. X                {
  1360. X                b = par_cond_triple(tsp[0],tsp[1],tsp[2]);
  1361. X                tip += 3,tsp += 3;
  1362. X                return b;
  1363. X                }
  1364. X        }
  1365. X   return NULL;
  1366. X}
  1367. X
  1368. Xint bin_compctl(name,argv,ops,func) /**/
  1369. Xchar *name;char **argv;char *ops;int func;
  1370. X{
  1371. Xint flags = 0;
  1372. XCompctl cc = NULL;
  1373. Xchar *usrkeys = NULL;
  1374. X
  1375. X    for (; *argv && **argv == '-'; argv++)
  1376. X        while (*++(*argv)) switch(**argv) {
  1377. X        case 'c': flags |= CC_COMMPATH; break;
  1378. X        case 'f': flags |= CC_FILES; break;
  1379. X        case 'h': flags |= CC_HOSTS; break;
  1380. X        case 'o': flags |= CC_OPTIONS; break;
  1381. X        case 'v': flags |= CC_VARS; break;
  1382. X        case 'b': flags |= CC_BINDINGS; break;
  1383. X        case 'k':
  1384. X            flags |= CC_USRKEYS;
  1385. X            if ((*argv)[1]) { usrkeys = (*argv)+1; *argv = "\0"; }
  1386. X            else if (!argv[1]) {
  1387. X                zerrnam(name,"variable name expected after -k",NULL,0);
  1388. X                return 1;
  1389. X            } else { usrkeys = *++argv; *argv = "\0"; }
  1390. X            break;
  1391. X        case 'C': cc = &cc_compos; break;
  1392. X        case 'D': cc = &cc_default; break;
  1393. X        default: zerrnam(name,"bad option: %c",NULL,**argv); return 1;
  1394. X        }
  1395. X    if (cc) {
  1396. X        cc->mask = flags;
  1397. X        if (cc->keyvar) free(cc->keyvar);
  1398. X        cc->keyvar  = ztrdup(usrkeys);
  1399. X    }
  1400. X    if (!*argv) {
  1401. X        if (!cc) {
  1402. X            showflag = flags;
  1403. X            listhtable(compctltab,(HFunc) printcompctl);
  1404. X            printcompctl("COMMAND",&cc_compos);
  1405. X            printcompctl("DEFAULT",&cc_default);
  1406. X        }
  1407. X        return 0;
  1408. X    }
  1409. X    compctl_process(argv,flags,usrkeys);
  1410. X    return 0;
  1411. X}
  1412. X
  1413. Xvoid printcompctl(s,cc) /**/
  1414. Xchar *s;Compctl cc;
  1415. X{
  1416. Xchar *css = "fchovb";
  1417. X
  1418. X    if (cc->mask & showflag) {
  1419. X        puts(s);
  1420. X    } else if (!showflag) {
  1421. X        int flags = cc->mask;
  1422. X        printf("%s -",s);
  1423. X        while (*css) {
  1424. X            if (flags & 1) putchar(*css);
  1425. X            css++; flags >>= 1;
  1426. X        }
  1427. X        if (flags & 1) printf("k %s",cc->keyvar);
  1428. X        putchar('\n');
  1429. X    }
  1430. X}
  1431. X
  1432. Xvoid compctl_process(s,mask,uk) /**/
  1433. Xchar **s;int mask;char *uk;
  1434. X{
  1435. XCompctl cc;
  1436. X
  1437. X    for (;*s;s++) {
  1438. X        cc = zalloc(sizeof *cc);
  1439. X        cc->mask = mask; cc->keyvar = ztrdup(uk);
  1440. X        addhnode(ztrdup(*s),cc,compctltab,freecompctl);
  1441. X    }
  1442. X}
  1443. X
  1444. Xint bin_ttyctl(name,argv,ops,func) /**/
  1445. Xchar *name;char **argv;char *ops;int func;
  1446. X{
  1447. X    if (ops['f'] || !ops['@']) ttyfrozen = 1;
  1448. X    else if (ops['u']) ttyfrozen = 0;
  1449. X    return 0;
  1450. X}
  1451. END_OF_FILE
  1452.   if test 16952 -ne `wc -c <'src/builtin.c.02'`; then
  1453.     echo shar: \"'src/builtin.c.02'\" unpacked with wrong size!
  1454.   fi
  1455.   # end of 'src/builtin.c.02'
  1456. fi
  1457. if test -f 'src/subst.c' -a "${1}" != "-c" ; then 
  1458.   echo shar: Will not clobber existing file \"'src/subst.c'\"
  1459. else
  1460.   echo shar: Extracting \"'src/subst.c'\" \(16309 characters\)
  1461.   sed "s/^X//" >'src/subst.c' <<'END_OF_FILE'
  1462. X/*
  1463. X *
  1464. X * subst.c - various substitutions
  1465. X *
  1466. X * This file is part of zsh, the Z shell.
  1467. X *
  1468. X * This software is Copyright 1992 by Paul Falstad
  1469. X *
  1470. X * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  1471. X * use this software as long as: there is no monetary profit gained
  1472. X * specifically from the use or reproduction of this software, it is not
  1473. X * sold, rented, traded or otherwise marketed, and this copyright notice is
  1474. X * included prominently in any copy made. 
  1475. X *
  1476. X * The author make no claims as to the fitness or correctness of this software
  1477. X * for any use whatsoever, and it is provided as is. Any use of this software
  1478. X * is at the user's own risk. 
  1479. X *
  1480. X */
  1481. X
  1482. X#include "zsh.h"
  1483. X#include <pwd.h>
  1484. X
  1485. X/* do substitutions before fork */
  1486. X
  1487. Xvoid prefork(list) /**/
  1488. XLklist list;
  1489. X{
  1490. XLknode node = firstnode(list);
  1491. Xint qt;
  1492. X
  1493. X    while (node)
  1494. X        {
  1495. X        char *str,*str3;
  1496. X        
  1497. X        str = str3 = getdata(node);
  1498. X        if ((*str == Inang || *str == Outang || *str == Equals) &&
  1499. X                str[1] == Inpar)
  1500. X            {
  1501. X            if (*str == Inang)
  1502. X                setdata(node,getoutproc(str+2));        /* <(...) */
  1503. X            else if (*str == Equals)
  1504. X                setdata(node,getoutputfile(str+2));    /* =(...) */
  1505. X            else
  1506. X                setdata(node,getinproc(str+2));        /* >(...) */
  1507. X            if (!getdata(node))
  1508. X                {
  1509. X                zerr("parse error in process substitution",NULL,0);
  1510. X                return;
  1511. X                }
  1512. X            }
  1513. X        else while (*str)
  1514. X            {
  1515. X            if ((qt = *str == Qstring) || *str == String)
  1516. X                if (str[1] != Inpar)
  1517. X                    if (str[1] == Inbrack)
  1518. X                        {
  1519. X                        arithsubst((vptr*) &str,&str3);    /* $[...] */
  1520. X                        setdata(node,str3);
  1521. X                        str = str3;
  1522. X                        continue;
  1523. X                        }
  1524. X                    else
  1525. X                        {
  1526. X                        paramsubst(list,node,str,str3,qt);
  1527. X                        if (errflag)
  1528. X                            return;
  1529. X                        str3 = str = getdata(node);
  1530. X                        continue;
  1531. X                        }
  1532. X            str++;
  1533. X            if (errflag)
  1534. X                return;
  1535. X            }
  1536. X        if (*(char *) getdata(node))
  1537. X            remnulargs(getdata(node));
  1538. X        if (unset(IGNOREBRACES))
  1539. X            while (hasbraces(getdata(node)))
  1540. X                xpandbraces(list,&node);
  1541. X        filesub((char **) getaddrdata(node));
  1542. X        if (errflag)
  1543. X            return;
  1544. X        incnode(node);
  1545. X        }
  1546. X}
  1547. X
  1548. Xvoid postfork(list,doglob) /**/
  1549. XLklist list;int doglob;
  1550. X{
  1551. XLknode node = firstnode(list);
  1552. Xint glb = 1;
  1553. X
  1554. X    badcshglob = 0;
  1555. X    if (isset(NOGLOBOPT) || !doglob)
  1556. X        glb = 0;
  1557. X    while (node)
  1558. X        {
  1559. X        char *str3,*str;
  1560. X        
  1561. X        str = str3 = getdata(node);
  1562. X        while (*str)
  1563. X            {
  1564. X            if (((*str == String || *str == Qstring) && str[1] == Inpar) ||
  1565. X                    *str == Tick || *str == Qtick)
  1566. X                {
  1567. X                Lknode n = prevnode(node);
  1568. X
  1569. X                commsubst(list,node,str,str3,
  1570. X                    (*str == Qstring || *str == Qtick));    /* `...`,$(...) */
  1571. X                if (errflag)
  1572. X                    return;
  1573. X                str = str3 = getdata(node = nextnode(n));
  1574. X                continue;
  1575. X                }
  1576. X            str++;
  1577. X            }
  1578. X        if (glb)
  1579. X            {
  1580. X            if (haswilds(getdata(node)))
  1581. X                glob(list,&node);
  1582. X            if (errflag)
  1583. X                return;
  1584. X            }
  1585. X        incnode(node);
  1586. X        }
  1587. X    if (badcshglob == 1) zerr("no match",NULL,0);
  1588. X}
  1589. X
  1590. X/* perform substitution on a single word */
  1591. X
  1592. Xvoid singsub(s) /**/
  1593. Xchar **s;
  1594. X{
  1595. XLklist foo;
  1596. Xchar *t;
  1597. X
  1598. X    for (t = *s; *t; t++)
  1599. X        if (*t == String)
  1600. X            *t = Qstring;
  1601. X        else if (*t == Tick)
  1602. X            *t = Qtick;
  1603. X    foo = newlist();
  1604. X    addnode(foo,*s);
  1605. X    prefork(foo);
  1606. X    if (errflag)
  1607. X        return;
  1608. X    postfork(foo,0);
  1609. X    if (errflag)
  1610. X        return;
  1611. X    *s = ugetnode(foo);
  1612. X    if (firstnode(foo))
  1613. X        zerr("ambiguous: %s",*s,0);
  1614. X}
  1615. X
  1616. X/* strdup, but returns "Nularg" if this is a null string */
  1617. X
  1618. Xvptr nstrdup(s) /**/
  1619. Xvptr s;
  1620. X{
  1621. Xchar *t = s;
  1622. X
  1623. X    if (!*t)
  1624. X        return strdup(nulstring);
  1625. X    return strdup(t);
  1626. X}
  1627. X
  1628. Xchar *dynread(stop) /**/
  1629. Xint stop;
  1630. X{
  1631. Xint bsiz = 256,ct = 0,c;
  1632. Xchar *buf = zalloc(bsiz),*ptr;
  1633. X    ptr = buf;
  1634. X    while ((c = hgetc()) != stop)
  1635. X        {
  1636. X        *ptr++ = c;
  1637. X        if (++ct == bsiz)
  1638. X            {
  1639. X            buf = realloc(buf,bsiz *= 2);
  1640. X            ptr = buf+ct;
  1641. X            }
  1642. X        }
  1643. X    *ptr = 0;
  1644. X    return buf;
  1645. X}
  1646. X
  1647. Xint filesub(namptr) /**/
  1648. Xchar **namptr;
  1649. X{
  1650. Xchar *str = *namptr,*cnam;
  1651. X
  1652. X    if (*str == Tilde && str[1] != '=')
  1653. X        {
  1654. X        if (str[1] == '+' && (str[2] == '/' || str[2] == '\0'))
  1655. X            {
  1656. X            char *foo = strdup(pwd);    /* ~+ */
  1657. X
  1658. X            str+=2;
  1659. X            modify(&foo,&str);
  1660. X            *namptr = dyncat(pwd,str);
  1661. X            return 1;
  1662. X            }
  1663. X        else if (str[1] == '-' && (str[2] == '/' || str[2] == '\0'))
  1664. X            {
  1665. X            char *foo;                /* ~- */
  1666. X
  1667. X            if (cnam = oldpwd)
  1668. X                foo = cnam;
  1669. X            else
  1670. X                foo = pwd;
  1671. X            str += 2;
  1672. X            foo = strdup(foo);
  1673. X            modify(&foo,&str);
  1674. X            *namptr = dyncat(foo,str);
  1675. X            return 1;
  1676. X            }
  1677. X        if (ialpha(str[1]))        /* ~foo */
  1678. X            {
  1679. X            char *ptr,*hom;
  1680. X            for (ptr = ++str; *ptr && iuser(*ptr); ptr++)
  1681. X                if (*ptr == '-')
  1682. X                    *ptr = '-';
  1683. X            if (*ptr && *ptr != '/') return 0;
  1684. X            if (!(hom = gethome(str,ptr-str)))
  1685. X                {
  1686. X                zerr("user not found: %l",str,ptr-str);
  1687. X                return 0;
  1688. X                }
  1689. X            modify(&hom,&ptr);
  1690. X            *namptr = dyncat(hom,ptr);
  1691. X            return 1;
  1692. X            }
  1693. X        else if (str[1] == '/')    /* ~/foo */
  1694. X            {
  1695. X            *namptr = dyncat(home,str+1);
  1696. X            return 1;
  1697. X            }
  1698. X        else if (!str[1])        /* ~ by itself */
  1699. X            {
  1700. X            *namptr = strdup(home);
  1701. X            return 1;
  1702. X            }
  1703. X        }
  1704. X    if (*str == Equals && iuser(str[1]) && unset(NOEQUALS))
  1705. X        {
  1706. X        char *ptr,*s,*ds;
  1707. X        int val;
  1708. X        
  1709. X        if (ialpha(str[1]))        /* =foo */
  1710. X            {
  1711. X            char sav,*pp;
  1712. X            for (pp = str+1; *pp && *pp != ':'; pp++);
  1713. X            sav = *pp;
  1714. X            *pp = '\0';
  1715. X            if (!(cnam = findcmd(str+1)))
  1716. X                {
  1717. X                zerr("%s not found",str+1,0);
  1718. X                return 0;
  1719. X                }
  1720. X            *namptr = strdup(cnam);
  1721. X            free(cnam);
  1722. X            if ((*pp = sav) == ':')
  1723. X                {
  1724. X                modify(namptr,&pp);
  1725. X                s = *namptr;
  1726. X                *namptr = dyncat(*namptr,pp);
  1727. X                }
  1728. X            return 1;
  1729. X            }
  1730. X        if (str[1] == '-')     /* =- */
  1731. X            {
  1732. X            val = -1;
  1733. X            ptr = str+2;
  1734. X            }
  1735. X        else
  1736. X            val = zstrtol(str+1,&ptr,10);    /* =# */
  1737. X        ds = dstackent(val);
  1738. X        if (!ds)
  1739. X            return 1;
  1740. X        s = strdup(ds);
  1741. X        modify(&s,&ptr);
  1742. X        *namptr = dyncat(s,ptr);
  1743. X        return 1;
  1744. X        }
  1745. X    return 0;
  1746. X}
  1747. X
  1748. X/* get a named directory */
  1749. X
  1750. Xchar *gethome(user,len) /**/
  1751. Xchar *user;int len;
  1752. X{
  1753. Xchar sav,*str,*ret_val;
  1754. Xstruct passwd *pw;
  1755. X    if (len == 0)
  1756. X        return strdup(home);
  1757. X    sav = user[len];
  1758. X    user[len] = '\0';
  1759. X    if ((getparamtype(user,len) == PMFLAG_s) &&
  1760. X            (str = getsparamval(user,len)) && *str == '/')
  1761. X        {
  1762. X        str = strdup(str);
  1763. X        adduserdir(user,str);
  1764. X        user[len] = sav;
  1765. X        return str;
  1766. X        }
  1767. X    permalloc(); /* fixes iris bug--getpwnam calls strdup! */
  1768. X    pw = getpwnam(user);
  1769. X    lastalloc();
  1770. X    if (!pw) {
  1771. X        user[len] = sav;
  1772. X        return NULL;
  1773. X    }
  1774. X    str = xsymlink(pw->pw_dir);
  1775. X    adduserdir(user,str);
  1776. X    user[len] = sav;
  1777. X    ret_val = strdup(str);
  1778. X    free(str);
  1779. X    return ret_val;
  1780. X}
  1781. X
  1782. X/* `...`, $(...) */
  1783. X
  1784. Xvoid commsubst(l,n,str3,str,qt) /**/
  1785. XLklist l;Lknode n;char *str3;char *str;int qt;
  1786. X{
  1787. Xchar *str2;
  1788. XLknode where = prevnode(n);
  1789. XLklist pl;
  1790. X
  1791. X    if (*str3 == Tick || *str3 == Qtick)
  1792. X        {
  1793. X        *str3 = '\0';
  1794. X        for (str2 = ++str3; *str3 != Tick && *str3 != Qtick; str3++);
  1795. X        *str3++ = '\0';
  1796. X        }
  1797. X    else
  1798. X        {
  1799. X        *str3++ = '\0';
  1800. X        for (str2 = ++str3; *str3 != Outpar; str3++);
  1801. X        *str3++ = '\0';
  1802. X        }
  1803. X    uremnode(l,n);
  1804. X    if (!(pl = getoutput(str2,qt)))
  1805. X        {
  1806. X        if (!errflag)
  1807. X            zerr("parse error in command substitution",NULL,0);
  1808. X        return;
  1809. X        }
  1810. X    if (full(pl))
  1811. X        {
  1812. X        setdata(firstnode(pl),dyncat(str,peekfirst(pl)));
  1813. X        setdata(lastnode(pl),dyncat(getdata(lastnode(pl)),str3));
  1814. X        inslist(pl,where,l);
  1815. X        }
  1816. X    else
  1817. X        insnode(l,where,dyncat(str,str3));
  1818. X}
  1819. X
  1820. X/* parameter substitution */
  1821. X
  1822. X#define    isstring(c)    (c == '$' || c == String || c == Qstring)
  1823. X#define    isbrace(c)    (c == '{' || c == Inbrace)
  1824. X
  1825. Xvoid paramsubst(l,n,aptr,bptr,qt) /**/
  1826. XLklist l;Lknode n;char *aptr;char *bptr;int qt;
  1827. X{
  1828. Xchar *s = aptr,*u,*idbeg,*idend,*ostr = bptr;
  1829. Xint brs;            /* != 0 means ${...}, otherwise $... */
  1830. Xint colf;        /* != 0 means we found a colon after the name */
  1831. Xint doub = 0;    /* != 0 means we have %%, not %, or ##, not # */
  1832. Xint isarr = 0;
  1833. Xint plan9 = isset(RCEXPANDPARAM);
  1834. Xint getlen = 0;
  1835. Xint vunset = 0;
  1836. Xint spbreak = isset(SHWORDSPLIT) && !qt;
  1837. Xchar *val = NULL,**aval = NULL;
  1838. Xint vlen;
  1839. Xint fwidth = 0;
  1840. XValue v;
  1841. X
  1842. X    *s++ = '\0';
  1843. X    if (!ialnum(*s) && *s != '#' && *s != Pound && *s != '-' &&
  1844. X            *s != '!' && *s != '$' && *s != String && *s != Qstring &&
  1845. X            *s != '?' && *s != Quest && *s != '_' &&
  1846. X            *s != '*' && *s != Star && *s != '@' && *s != '{' &&
  1847. X            *s != Inbrace && *s != '=' && *s != Hat && *s != '^') {
  1848. X        s[-1] = '$';
  1849. X        return;
  1850. X    }
  1851. X    if (brs = (*s == '{' || *s == Inbrace)) s++;
  1852. X    for (;;) {
  1853. X        if (*s == '^' || *s == Hat)
  1854. X            plan9 ^= 1,s++;
  1855. X        else if (*s == '=')
  1856. X            spbreak ^= 1,s++;
  1857. X        else if ((*s == '#' || *s == Pound) && (iident(s[1])
  1858. X                || s[1] == '*' || s[1] == Star || s[1] == '@'
  1859. X                || (isstring(s[1]) && isbrace(s[2]) && iident(s[3]))))
  1860. X            getlen = 1,s++;
  1861. X        else
  1862. X            break;
  1863. X    }
  1864. X
  1865. X    idbeg = s;
  1866. X    if (isstring(*s) && isbrace(s[1])) {
  1867. X        int bct, sav;
  1868. X
  1869. X        val = s;
  1870. X        for (bct = 1, s += 2; *s && bct; ++s)
  1871. X            if (*s == Inbrace || *s == '{')
  1872. X                ++bct;
  1873. X            else if (*s == Outbrace || *s == '}')
  1874. X                --bct;
  1875. X        sav = *s;
  1876. X        *s = 0;
  1877. X        singsub(&val);
  1878. X        *s = sav;
  1879. X        isarr = 0;
  1880. X        v = (Value) NULL;
  1881. X    } else if (!(v = getvalue(&s,1))) {
  1882. X        vunset = 1;
  1883. X    } else
  1884. X        if (isarr = v->isarr) {
  1885. X            aval = getarrvalue(v);
  1886. X            if (qt && isarr > 0) {
  1887. X                val = spacejoin(aval);
  1888. X                isarr = 0;
  1889. X            }
  1890. X        }
  1891. X        else {
  1892. X            val = getstrvalue(v);
  1893. X            fwidth = v->pm->ct;
  1894. X            switch (v->pm->flags & (PMFLAG_L | PMFLAG_R | PMFLAG_Z)) {
  1895. X                char *t;
  1896. X                int t0;
  1897. X
  1898. X                case PMFLAG_L:
  1899. X                case PMFLAG_L|PMFLAG_Z:
  1900. X                    t = val;
  1901. X                    if (v->pm->flags & PMFLAG_Z)
  1902. X                        while (*t == '0') t++;
  1903. X                    else
  1904. X                        while (isep(*t)) t++;
  1905. X                    val = ncalloc(fwidth+1);
  1906. X                    val[fwidth] = '\0';
  1907. X                    if ((t0 = strlen(t)) > fwidth)
  1908. X                        t0 = fwidth;
  1909. X                    memset(val,' ',fwidth);
  1910. X                    strncpy(val,t,t0);
  1911. X                    break;
  1912. X                case PMFLAG_R:
  1913. X                case PMFLAG_Z:
  1914. X                case PMFLAG_Z|PMFLAG_R:
  1915. X                    if (strlen(val) < fwidth) {
  1916. X                        t = ncalloc(fwidth+1);
  1917. X                        memset(t,(v->pm->flags & PMFLAG_R) ? ' ' : '0',fwidth);
  1918. X                        if ((t0 = strlen(val)) > fwidth)
  1919. X                            t0 = fwidth;
  1920. X                        strcpy(t+(fwidth-t0),val);
  1921. X                        val = t;
  1922. X                    } else {
  1923. X                        t = ncalloc(fwidth+1);
  1924. X                        t[fwidth] = '\0';
  1925. X                        strncpy(t,val+strlen(val)-fwidth,fwidth);
  1926. X                        val = t;
  1927. X                    }
  1928. X                    break;
  1929. X                }
  1930. X            switch (v->pm->flags & (PMFLAG_l | PMFLAG_u)) {
  1931. X                char *t;
  1932. X
  1933. X                case PMFLAG_l:
  1934. X                    t = val;
  1935. X                    for (;*t;t++)
  1936. X                        *t = tulower(*t);
  1937. X                    break;
  1938. X                case PMFLAG_u:
  1939. X                    t = val;
  1940. X                    for (;*t;t++)
  1941. X                        *t = tuupper(*t);
  1942. X                    break;
  1943. X            }
  1944. X        }
  1945. X    idend = s;
  1946. X    if (colf = *s == ':') s++;
  1947. X    
  1948. X    /* check for ${..?...} or ${..=..} or one of those.  Only works
  1949. X        if the name is in braces. */
  1950. X
  1951. X    if (brs && (*s == '-' || *s == '=' || *s == '?' || *s == '+' || *s == '#' ||
  1952. X            *s == '%' || *s == Quest || *s == Pound)) {
  1953. X        if (v && isarr && (*s == '%' || *s == '#' || *s == Pound)) {
  1954. X            zerr("operator requires a scalar",NULL,0);
  1955. X            return;
  1956. X        }
  1957. X        if (*s == s[1]) {
  1958. X            s++;
  1959. X            doub = 1;
  1960. X        }
  1961. X        u = ++s;
  1962. X        if (brs) {
  1963. X            int bct = 1;
  1964. X
  1965. X            for (;;) {
  1966. X                if (*s == '{' || *s == Inbrace)
  1967. X                    bct++;
  1968. X                else if (*s == '}' || *s == Outbrace)
  1969. X                    bct--;
  1970. X                if (!bct || !*s)
  1971. X                    break;
  1972. X                s++;
  1973. X            }
  1974. X        } else {
  1975. X            while (*s++);
  1976. X            s--;
  1977. X        }
  1978. X        if (*s) *s++ = '\0';
  1979. X        if (colf && !vunset)
  1980. X            vunset = (isarr) ? !*aval : !*val;
  1981. X        switch ((int)(unsigned char)u[-1]) {
  1982. X            case '-':
  1983. X                if (vunset)
  1984. X                    val = strdup(u), isarr = 0;
  1985. X                break;
  1986. X            case '=':
  1987. X                if (vunset) {
  1988. X                    char sav = *idend;
  1989. X
  1990. X                    *idend = '\0';
  1991. X                    setsparam(idbeg,ztrdup(val = strdup(u)));
  1992. X                    *idend = sav;
  1993. X                    isarr = 0;
  1994. X                }
  1995. X                break;
  1996. X            case '?':
  1997. X            case (int)STOUC(Quest):
  1998. X                if (vunset) {
  1999. X                    zerr("%s",(*u) ? u : "parameter not set",0);
  2000. X                    if (!interact)
  2001. X                        exit(1);
  2002. X                    return;
  2003. X                }
  2004. X                break;
  2005. X            case '+':
  2006. X                if (vunset)
  2007. X                    val = strdup("");
  2008. X                else
  2009. X                    val = strdup(u);
  2010. X                isarr = 0;
  2011. X                break;
  2012. X            case '#':
  2013. X            case (int)STOUC(Pound):
  2014. X                if (vunset)
  2015. X                    val = strdup("");
  2016. X                singsub(&u);
  2017. X                getmatch(&val,u,doub);
  2018. X                break;
  2019. X            case '%':
  2020. X                if (vunset)
  2021. X                    val = strdup("");
  2022. X                singsub(&u);
  2023. X                getmatch(&val,u,doub+2);
  2024. X                break;
  2025. X        }
  2026. X    } else {        /* no ${...=...} or anything, but possible modifiers. */
  2027. X        if (vunset) {
  2028. X            if (isset(NOUNSET)) {
  2029. X                zerr("parameter not set",NULL,0);
  2030. X                return;
  2031. X            }
  2032. X            val = strdup("");
  2033. X        }
  2034. X        if (colf) {
  2035. X            s--;
  2036. X            if (!isarr) modify(&val,&s);
  2037. X            else {
  2038. X                char *ss = s;
  2039. X                char **ap = aval;
  2040. X                char **pp = aval = (char **)ncalloc(sizeof(char *)*(arrlen(aval)+1));
  2041. X                while (*pp = *ap++) {
  2042. X                    ss = s;
  2043. X                    modify(pp++,&ss);
  2044. X                }
  2045. X                s = ss;
  2046. X            }
  2047. X        }
  2048. X        if (brs) {
  2049. X            if (*s != '}' && *s != Outbrace) {
  2050. X                zerr("closing brace expected",NULL,0);
  2051. X                return;
  2052. X            }
  2053. X            s++;
  2054. X        }
  2055. X    }
  2056. X    if (errflag)
  2057. X        return;
  2058. X    if (getlen) {
  2059. X        long len = 0;
  2060. X        char buf[14];
  2061. X
  2062. X        if (isarr) {
  2063. X            char **ctr;
  2064. X            for (ctr = aval; *ctr; ctr++,len++);
  2065. X        } else
  2066. X            len = strlen(val);
  2067. X        sprintf(buf,"%ld",len);
  2068. X        val = strdup(buf);
  2069. X        isarr = 0;
  2070. X    }
  2071. X    if (isarr)
  2072. X        if (!aval || !aval[0]) {
  2073. X            val = strdup("");
  2074. X            isarr = 0;
  2075. X        } else if (!aval[1]) {
  2076. X            val = aval[0];
  2077. X            isarr = 0;
  2078. X        }
  2079. X    if (!qt && spbreak) {
  2080. X        if (isarr)
  2081. X            val = spacejoin(aval);
  2082. X        isarr = 1;
  2083. X        aval = spacesplit(val);
  2084. X        if (!aval || !aval[0]) {
  2085. X            val = strdup("");
  2086. X            isarr = 0;
  2087. X        } else if (!aval[1]) {
  2088. X            val = aval[0];
  2089. X            isarr = 0;
  2090. X        }
  2091. X        /* if only one member, not really an array */
  2092. X        if (!aval[1])
  2093. X            isarr = 0;
  2094. X    }
  2095. X    if (isarr)
  2096. X        if (plan9) {
  2097. X            int dlen;
  2098. X            char *y;
  2099. X            char *x;
  2100. X
  2101. X            vlen = strlen(aval[0]);
  2102. X            if (qt && vlen == 0)
  2103. X                y = ncalloc((dlen = (char *) aptr-bptr+strlen(s)+1)+nulstrlen);
  2104. X            else
  2105. X                y = ncalloc((dlen = (char *) aptr-bptr+strlen(s)+1)+vlen);
  2106. X            setdata(n,y);
  2107. X            strcpy(y,ostr);
  2108. X            strcat(y, (qt && vlen == 0) ? nulstring : aval[0]);
  2109. X            strcat(y,s);
  2110. X            while (*++aval) {
  2111. X                vlen = strlen(*aval);
  2112. X                if (qt && vlen == 0)
  2113. X                    x = ncalloc(dlen+nulstrlen);
  2114. X                else
  2115. X                    x = ncalloc(dlen+vlen);
  2116. X                strcpy(x,ostr);
  2117. X                strcat(x, (qt && vlen == 0) ? nulstring : *aval);
  2118. X                strcat(x,s);
  2119. X                insnode(l,n,x), incnode(n);
  2120. X            }
  2121. X        } else {
  2122. X            char *zz;
  2123. X
  2124. X            vlen = strlen(aval[0]);
  2125. X            if (qt && vlen == 0)
  2126. X                zz = ncalloc((char *) aptr-(bptr)+nulstrlen+1);
  2127. X            else
  2128. X                zz = ncalloc((char *) aptr-(bptr)+vlen+1);
  2129. X            setdata(n,zz);
  2130. X            strcpy(zz,ostr);
  2131. X            strcat(zz, (qt && vlen == 0) ? nulstring : *aval);
  2132. X            aval++;
  2133. X            while (aval[1]) {
  2134. X                insnode(l,n,
  2135. X                    (qt && strlen(*aval) == 0) ? strdup(nulstring) : *aval);
  2136. X                incnode(n);
  2137. X                aval++;
  2138. X            }
  2139. X            vlen = strlen(*aval);
  2140. X            if (qt && vlen == 0) {
  2141. X                zz = ncalloc(nulstrlen+strlen(s)+1);
  2142. X                strcpy(zz,nulstring);
  2143. X            }
  2144. X            else {
  2145. X                zz = ncalloc(vlen+strlen(s)+1);
  2146. X                strcpy(zz,*aval);
  2147. X            }
  2148. X            strcat(zz,s);
  2149. X            insnode(l,n,zz);
  2150. X        }
  2151. X    else {
  2152. X        vlen = strlen(val);
  2153. X        if (qt && vlen == 0)
  2154. X            bptr = ncalloc((char *) aptr-bptr+nulstrlen+strlen(s)+1);
  2155. X        else
  2156. X            bptr = ncalloc((char *) aptr-bptr+vlen+strlen(s)+1);
  2157. X        setdata(n,bptr);
  2158. X        strcpy(bptr,ostr);
  2159. X        strcat(bptr, (qt && vlen == 0) ? nulstring : val);
  2160. X        strcat(bptr,s);
  2161. X    }
  2162. X}
  2163. X
  2164. X/* arithmetic substitution */
  2165. X
  2166. Xvoid arithsubst(aptr,bptr) /**/
  2167. Xvptr *aptr;char **bptr;
  2168. X{
  2169. Xchar *s = *aptr,*t,buf[16];
  2170. Xlong v;
  2171. X
  2172. X    *s = '\0';
  2173. X    for (; *s != Outbrack; s++);
  2174. X    *s++ = '\0';
  2175. X    v = matheval((char *) *aptr+2);
  2176. X    sprintf(buf,"%ld",v);
  2177. X    t = ncalloc(strlen(*bptr)+strlen(buf)+strlen(s)+1);
  2178. X    strcpy(t,*bptr);
  2179. X    strcat(t,buf);
  2180. X    strcat(t,s);
  2181. X    *bptr = t;
  2182. X}
  2183. X
  2184. Xvoid modify(str,ptr) /**/
  2185. Xchar **str;char **ptr;
  2186. X{
  2187. Xchar *ptr1,*ptr2,*ptr3,del,*lptr, sav;
  2188. Xint gbal;
  2189. X
  2190. X    if (**ptr == ':')
  2191. X        *str = strdup(*str);
  2192. X    while (**ptr == ':')
  2193. X        {
  2194. X        lptr = *ptr;
  2195. X        (*ptr)++;
  2196. X        gbal = 0;
  2197. Xhere:
  2198. X        switch(*(*ptr)++)
  2199. X            {
  2200. X            case 'h': remtpath(str); break;
  2201. X            case 'r': remtext(str); break;
  2202. X            case 'e': rembutext(str); break;
  2203. X            case 't': remlpaths(str); break;
  2204. X            case 'l': downcase(str); break;
  2205. X            case 'u': upcase(str); break;
  2206. X            case 's':
  2207. X                if (hsubl)
  2208. X                    free(hsubl);
  2209. X                if (hsubr)
  2210. X                    free(hsubr);
  2211. X                ptr1 = *ptr;
  2212. X                del = *ptr1++;
  2213. X                for (ptr2 = ptr1; *ptr2 != del && *ptr2; ptr2++);
  2214. X                if (!*ptr2)
  2215. X                    {
  2216. X                    zerr("bad subtitution",NULL,0);
  2217. X                    return;
  2218. X                    }
  2219. X                *ptr2++ = '\0';
  2220. X                for (ptr3 = ptr2; *ptr3 != del && *ptr3; ptr3++);
  2221. X                if (sav = *ptr3)
  2222. X                    *ptr3++ = '\0';
  2223. X                hsubl = ztrdup(ptr1);
  2224. X                hsubr = ztrdup(ptr2);
  2225. X                ptr2[-1] = del;
  2226. X                if (sav)
  2227. X                    ptr3[-1] = sav;
  2228. X                *ptr = ptr3;
  2229. X            case '&':
  2230. X                if (hsubl && hsubr)
  2231. X                    subst(str,hsubl,hsubr,gbal);
  2232. X                break;
  2233. X            case 'g': gbal = 1; goto here;
  2234. X            default: *ptr = lptr; return;
  2235. X            }
  2236. X        }
  2237. X}
  2238. X
  2239. X/* get a directory stack entry */
  2240. X
  2241. Xchar *dstackent(val) /**/
  2242. Xint val;
  2243. X{
  2244. XLknode node;
  2245. X    if ((val < 0 && !firstnode(dirstack)) || !val--)
  2246. X        return pwd;
  2247. X    if (val < 0)
  2248. X        node = lastnode(dirstack);
  2249. X    else
  2250. X        for (node = firstnode(dirstack); node && val; val--,incnode(node));
  2251. X    if (!node)
  2252. X        {
  2253. X        zerr("not enough dir stack entries.",NULL,0);
  2254. X        return NULL;
  2255. X        }
  2256. X    return getdata(node);
  2257. X}
  2258. X
  2259. X/* make an alias hash table node */
  2260. X
  2261. Xstruct alias *mkanode(txt,cmflag) /**/
  2262. Xchar *txt;int cmflag;
  2263. X{
  2264. Xstruct alias *ptr = (Alias) zcalloc(sizeof *ptr);
  2265. X
  2266. X    ptr->text  = txt;
  2267. X    ptr->cmd = cmflag;
  2268. X    ptr->inuse = 0;
  2269. X    return ptr;
  2270. X}
  2271. END_OF_FILE
  2272.   if test 16309 -ne `wc -c <'src/subst.c'`; then
  2273.     echo shar: \"'src/subst.c'\" unpacked with wrong size!
  2274.   fi
  2275.   # end of 'src/subst.c'
  2276. fi
  2277. echo shar: End of archive 17 \(of 22\).
  2278. cp /dev/null ark17isdone
  2279. MISSING=""
  2280. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; do
  2281.     if test ! -f ark${I}isdone ; then
  2282.     MISSING="${MISSING} ${I}"
  2283.     fi
  2284. done
  2285. if test "${MISSING}" = "" ; then
  2286.     echo You have unpacked all 22 archives.
  2287.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2288. else
  2289.     echo You still must unpack the following archives:
  2290.     echo "        " ${MISSING}
  2291. fi
  2292. exit 0
  2293.  
  2294. exit 0 # Just in case...
  2295.