home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume29 / parsearg / part04 < prev    next >
Encoding:
Text File  |  1992-05-18  |  69.1 KB  |  2,220 lines

  1. Newsgroups: comp.sources.misc
  2. From: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
  3. Subject:  v29i119:  parseargs - functions to parse command line arguments, Part04/10
  4. Message-ID: <1992May17.182342.28709@sparky.imd.sterling.com>
  5. X-Md4-Signature: 8d0fbe66797e91e23bae8aeec8652cd8
  6. Date: Sun, 17 May 1992 18:23:42 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: brad@hcx1.ssd.csd.harris.com (Brad Appleton)
  10. Posting-number: Volume 29, Issue 119
  11. Archive-name: parseargs/part04
  12. Environment: UNIX, VMS, MS-DOS, OS/2, Amiga
  13. Supersedes: parseargs: Volume 17, Issue 46-57
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 4 (of 10)."
  22. # Contents:  doc/parseargs.man1 doc/parseargs.man3 pgopen.c stest.c
  23. #   unix_man.c useful.h
  24. # Wrapped by brad@hcx1 on Thu May  7 12:12:22 1992
  25. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  26. if test -f 'doc/parseargs.man1' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'doc/parseargs.man1'\"
  28. else
  29. echo shar: Extracting \"'doc/parseargs.man1'\" \(13778 characters\)
  30. sed "s/^X//" >'doc/parseargs.man1' <<'END_OF_FILE'
  31. X.\" $Header: parseargs.1,v 1.0 90/07/24 Brad Appleton $
  32. X.de SS
  33. X.sp 8p
  34. X\s+1\fB\\$1\fP\s-1
  35. X.br
  36. X..
  37. X.TH PARSEARGS 1
  38. X.nh
  39. X.SH NAME
  40. Xparseargs \- parse command line arguments in shell scripts
  41. X.\"-----------------------------------------------------------
  42. X.SH SYNOPSIS
  43. X.TP 12
  44. X\fBparseargs\fP
  45. X[\fB\-#UMCAlouip1\fP]
  46. X[\fB\-S\fP\ \fIseparator\fP]
  47. X[\fB\-T\fP\ \fIstring\fP]
  48. X[\fB\-F\fP\ \fIstring\fP]
  49. X[\fB\-a\fP\ \fIarg-spec\fP]
  50. X[\fB\-e\fP\ \fIname\fP]
  51. X[\fB\-f\fP\ \fIfile\fP]
  52. X[\fB\-s\fP\ \fIshell\fP\^]
  53. X\fB\-\^\-\fP
  54. X\fIname\fP
  55. X[\fIarguments\fP\ .\^.\^.\^]
  56. X.\"-----------------------------------------------------------
  57. X.SH OPTIONS
  58. X.TP 14
  59. X\fB\-#\fP
  60. Xjust print the version and patchlevel, do not parse the command line
  61. X.TP 14
  62. X\fB\-U\fP
  63. Xjust print program usage, do not parse the command line
  64. X.TP 14
  65. X\fB\-M\fP
  66. Xjust print (n|t)roff \-man manual page template, do not parse the command line
  67. X.TP 14
  68. X\fB-S\fP\ \fIseparator\fP
  69. Xfield-separator-string used to delimit array elements  (\fIdefault=``\0''\fP\|)
  70. X.TP 14
  71. X\fB\-T\fP \fIstring\fP
  72. Xstring to use for true boolean arguments\|  (\fIdefault=``\s-1TRUE\s+1\^''\fP\|)
  73. X.TP 14
  74. X\fB\-F\fP \fIstring\fP
  75. Xstring to use for false boolean arguments  (\fIdefault=``\^''\fP\|)
  76. X.TP 14
  77. X\fB\-C\fP
  78. XIgnore the difference between upper and lower case when parsing single
  79. Xcharacter options.
  80. X.TP 14
  81. X\fB\-A\fP
  82. Xmodify array behavior for the specified shell.
  83. X.TP 14
  84. X\fB\-a\fP \fIarg-spec\fP
  85. Xargument specification string
  86. X.TP 14
  87. X\fB\-e\fP\ \fIname\fP
  88. Xread the arg-spec string from the environment variable named \fIname\fP
  89. X.TP 14
  90. X\fB\-f\fP \fIfile\fP
  91. Xread the arg-spec from \fIfile\fP  (\fIdefault=stdin\fP)
  92. X.TP 14
  93. X\fB\-l\fP
  94. XLong-options only. Disable the parsing of (single-character) options.
  95. X.TP 14
  96. X\fB\-o\fP
  97. XOptions only. Disable the parsing of long-options (keywords).
  98. X.TP 14
  99. X\fB\-s\fP \fIshell\fP
  100. Xuse \fIshell\fP command syntax\|  (\fIdefault=``sh''\fP\|)
  101. X.TP 14
  102. X\fB\-u\fP
  103. Xunset positional parameters before assigning variables
  104. X.TP 14
  105. X\fB\-p\fP
  106. Xprompt the user for missing required arguments
  107. X.TP 14
  108. X\fB\-i\fP
  109. Xignore bad command-line syntax and continue processing (instead of aborting)
  110. X.TP 14
  111. X\fB\-1\fP
  112. XForce any and all non-positional parameters to be specified before any
  113. Xpositional parameters on the command-line.
  114. X.\"-----------------------------------------------------------
  115. X.SH ARGUMENTS
  116. X.TP 14
  117. X\fI\-\^\-\fP
  118. XIndicates that any remaining options are intended for the calling program.
  119. X.TP 14
  120. X\fIname\fP
  121. Xname of calling program
  122. X.TP 14
  123. X\fIarguments\fP
  124. Xarguments to calling program
  125. X.\"-----------------------------------------------------------
  126. X.so parseargs1.inc
  127. X.\"-----------------------------------------------------------
  128. X.PP
  129. XThe argument specification string contains one entry for each possible flag.
  130. XEntries in the argument specification string are separated by commas.
  131. XEach entry has five comma-separated fields:
  132. Xa name, some flags, a type, a variable-name, and a prompt.
  133. XEach of these fields are described below:
  134. X.TP 10
  135. X\fIname\fP
  136. XThe single character name of the associated flag.
  137. XFor example, to indicate that the program is expecting a ``\-x'' flag,
  138. Xthis field would contain \'x\'.
  139. XPositional arguments (those without a ``\-\fIx\fP'' prefix)
  140. Xare indicated by passing a ``space'' character.
  141. X.TP 10
  142. X\fIflags\fP
  143. XFlags modifying the semantics of this entry.
  144. XThese should have one of
  145. X\s-1ARGREQ\s+1
  146. Xto indicate a required argument or
  147. X\s-1ARGOPT\s+1
  148. Xto indicate an optional argument
  149. X(\s-1ARGOPT\s+1 is the default unless \s-1ARGREQ\s+1 is specified).
  150. X\s-1ARGPOS\s+1
  151. Xmay be ``ored'' in to indicate a positional argument that may also
  152. Xbe keyword matched.
  153. X\s-1ARGVALOPT\s+1
  154. Xmay be ``ored'' in to indicate that an argument to the option may be
  155. Xoptionally supplied on the command-line, but is not required.
  156. X\s-1ARGVALREQ\s+1
  157. Xmay be ``ored'' in to indicate that an argument to the option is required
  158. X(this is the default behavior for options that take arguments).
  159. X\s-1ARGLIST\s+1
  160. Xmay be ``ored'' in (using the `\^|\^' character) to indicate that an argument
  161. Xis actually a list of one or more arguments from the command line.
  162. X\s-1ARGHIDDEN\s+1
  163. Xmay be ``ored'' in to indicate a flag that should not be printed
  164. Xin usage messages \(em
  165. Xfor example, flags intended for internal debugging purposes.
  166. X.TP 10
  167. X\fItype\fP
  168. XThe type of the argument.
  169. XExisting types include
  170. X\fIargUsage\fP (print usage message and exit),
  171. X\fIargBool\fP and \fIargSBool\fP (set Boolean flags),
  172. X\fIargUBool\fP (unset Boolean flags),
  173. X\fIargStr\fP (string-valued arguments),
  174. X\fIargChar\fP (char-valued arguments),
  175. X\fIargInt\fP (native integer arguments),
  176. X\fIargShort\fP (short integer arguments),
  177. X\fIargLong\fP (long integer arguments),
  178. X\fIargFloat\fP (short floating point arguments),
  179. X\fIargDouble\fP (long floating point arguments), and
  180. X\fIargDummy\fP (only used as part of usage message,
  181. Xnot matched on command-line).
  182. X.TP 10
  183. X\fIvariable\fP
  184. XThe name of the shell variable that should receive the converted value.
  185. X.TP 10
  186. X\fIprompt\fP
  187. XThe string used when prompting interactively for argument values,
  188. Xand printed in usage messages. This string may be followed by a
  189. Xtextual description that is enclosed in parentheses, square brackets,
  190. Xcurly braces, or angle brackets.
  191. X
  192. XThe prompt-string may be specifed
  193. Xin two parts: a keyword name and an argument name. The argument
  194. Xname may be separated from the keyword name by a single equal sign
  195. X('='). No whitespace is allowed before or after the equal sign.
  196. X
  197. XAlternatatively, the keyword name may be distinguished from the
  198. Xargument name by character case: if the long-name contains any
  199. Xuppercase characters, then the substring of long-name consisting of
  200. Xall uppercase characters is used as the argument keyword and the
  201. Xentire long-name is used as the name of the argument (if a value may
  202. Xbe supplied). The long-name may be matched by supplying a unique
  203. Xprefix of either the argument keyword or the argument name.
  204. X.PP
  205. XThe argument specification string must be terminated by the single string:
  206. X``ENDOFARGS''.
  207. X.PP
  208. XNote that the comma character (',') is used to separate all fields
  209. Xwithin an entry, and to separate the entries themselves.
  210. XFor this reason, \fIno field in any entry may contain a comma unless
  211. Xit appears inside of double or single quotes\fP.
  212. X.PP
  213. X.B Parseargs
  214. Xwill parse all command-line arguments for the calling script and match
  215. Xthem against the argument specification string provided. The argument
  216. Xspecification string is read from standard input by default but may not
  217. Xcome from a terminal. The argument specification string may be supplied as
  218. Xa single string argument by using the \fB\-a\fP ``\fIstring\fP'' flag.
  219. XLong argument specification strings however, may limit the number of arguments
  220. Xto the script if there is a limit to the number of arguments and/or characters
  221. Xthat may appear on the command line.
  222. XFor this reason, the argument specification string may be stored: in an
  223. Xenvironment variable using the \fB\-e\fP \fIname\fP option; in a file
  224. Xand read using the \fB\-f\fP \fIfile\fP option; or read from standard input.
  225. XWhen using the \fB\-e\fP option, the user must remember to use the name
  226. Xof an environment variable (not a mere shell variable)!
  227. XThe default behavior is to read the argument specification from standard input.
  228. X.\"-----------------------------------------------------------
  229. X.so shells.inc
  230. X.\"-----------------------------------------------------------
  231. X.PP
  232. XThe double-dash (``\fB\-\^\-\fP'') which precedes the name and arguments of
  233. Xthe calling program is needed in order for \fBparseargs\fP to be able to
  234. Xdistinguish options to itself from options for the calling program.
  235. X.PP
  236. XThe default behavior of parseargs is to allow both single-character options and
  237. Xlong-options (keywords) on the command-line. The user may specify that only
  238. Xoptions (long-options) are to be permitted by specifying the \fB\-o\fP
  239. X(\fB\-l\fP) option on the command-line.
  240. X.\"----------------------------------------------------------------
  241. X.SH "SPECIFYING PARSE-BEHAVIOR"
  242. X.PP
  243. XThe \fB\-C\fP, \fB\-p\fP, \fB\-i\fP, and \fB\-1\fP switches may be used to
  244. Xmodify the command-line parsing behavior of the invoking script. Specifying
  245. X\fB\-C\fP will cause case-differences in single-character options to be
  246. Xignored. Specifying \fB\-p\fP will cause the user to be interactively prompted
  247. Xfor any missing required arguments. Specifying \fB\-i\fP will cause
  248. Xsyntactically incorrect arguments to be ignored (instead of having a usage
  249. Xmessage printed and execution terminated). Specifying \fB\-1\fP will force
  250. Xall non-positional parameters to precede any positional parameters on the
  251. Xcommand-line (hence anything on the command-line after a positional parameter
  252. Xthat resembles a keyword parameter will nevertheless be interpreted as a
  253. Xpositional parameter).
  254. X.\"----------------------------------------------------------------
  255. X.so argvalopt.inc
  256. X.\"----------------------------------------------------------------
  257. X.so sh_arrays.inc
  258. X.\"----------------------------------------------------------------
  259. X.so env_args.inc
  260. X.\"----------------------------------------------------------------
  261. X.so env_parse.inc
  262. X.\"----------------------------------------------------------------
  263. X.so env_usage.inc
  264. X.\"----------------------------------------------------------------
  265. X.SH EXAMPLES
  266. X.PP
  267. XAs a first example, consider the following argument specification for a
  268. XBourne shell script:
  269. X.PP
  270. X.nf
  271. X.\" *** font 4 is the "typewriter-style" non-proportional font on my machine ***
  272. X.ft 4
  273. X.sp 8p
  274. X#!/bin/sh
  275. X.sp 8p
  276. XRepCount=2;
  277. XVerbose="";
  278. X.sp 8p
  279. XARGSPEC="
  280. X    'c', ARGOPT,         argInt,  RepCount, 'count {# times to repeat}',
  281. X    'v', ARGOPT,         argBool, Verbose,  'verbose {turn on verbose mode}',
  282. X    ' ', ARGREQ,         argStr,  InFile,   'input {file to read from}',
  283. X    ' ', ARGOPT,         argStr,  OutFile,  'output {file to write to}',
  284. X    'X', ARGHIDDEN,      argBool, XRated,   'xrated {naughty! naughty!}',
  285. X    ' ', ARGOPT|ARGLIST, listStr, Files,    'files {files to process}',
  286. XENDOFARGS
  287. X"
  288. X.sp 8p
  289. Xeval `echo "$ARGSPEC" | parseargs \-s sh \-\|\- $0 "$@"`
  290. X.sp 8p
  291. X.ft R
  292. X.fi
  293. X.PP
  294. XThis describes a Bourne shell script accepting up to three flag arguments and
  295. Xone or two positional arguments, plus a list of additional file arguments.
  296. XOnly the first positional argument is required.
  297. XThe possible flags (in UNIX) are:
  298. X.RS
  299. X.TP 10
  300. X\fB\-c\fP \fIcount\fP
  301. XAn integer repetition count.
  302. XThis defaults to two.
  303. X.TP 10
  304. X\fB\-v\fP
  305. XA Boolean ``verbose'' flag.
  306. XIt defaults to \s-1FALSE\s+1 (an empty string).
  307. X.TP 10
  308. X\fB\-X\fP
  309. XA Boolean ``X Rated'' flag.
  310. XThis is not printed in the usage message.
  311. X.RE
  312. X.PP
  313. XThe two positional arguments are both strings, as is the final list.
  314. XIf we were to invoke the above script with the following command line:
  315. X.sp 8p
  316. X.RS
  317. X\f4cmdname  \-v  input_file  output_file  file1  file2\fP
  318. X.RE
  319. X.sp 8p
  320. XThen, after invoking \fBparseargs\fP, the following shell variables would
  321. Xcontain the following values:
  322. X.sp 8p
  323. X.RS
  324. X\f4$RepCount\fP would evaluate to ``\f42\fP\^''
  325. X.sp 4p
  326. X\f4$Verbose\fP would evaluate to ``\f4\s-1TRUE\s+1\fP\^''
  327. X.sp 4p
  328. X\f4$InFile\fP would evaluate to ``\f4input_file\fP\^''
  329. X.sp 4p
  330. X\f4$OutFile\fP would evaluate to ``\f4output_file'\fP\^'
  331. X.sp 4p
  332. X\f4$Files\fP would evaluate to ``\f4file1  file2\fP\^''
  333. X.sp 4p
  334. X\f4$XRated\fP would be unset and would evaluate to an empty string (``\^'').
  335. X.RE
  336. X.sp
  337. X.PP
  338. XNow let's present a more complete example. The following page shows a
  339. XBourne shell script which uses \fBparseargs\fP to parse its command line,
  340. Xechoes the settings of all its associated command line variables, and
  341. Xthen prints its command usage.
  342. X
  343. X.nf
  344. X.\" *** font 4 is the "typewriter-style" non-proportional font on my machine ***
  345. X.ft 4
  346. X.so ../test.sh
  347. X.ft R
  348. X.fi
  349. X.\"-----------------------------------------------------------
  350. X.SH DIAGNOSTICS
  351. X\fBParseargs\fP may exit with one of the following status codes:
  352. X
  353. X.TP 5
  354. X-1
  355. XSome type of system error occurred during execution, causing the program
  356. Xto exit prematurely.
  357. X.TP 5
  358. X\|\|0
  359. XNormal exit status (no problems were encountered).
  360. X.TP 5
  361. X\|\|1
  362. XThe calling program specified the \fB\-#\fP, the \fB\-U\fP or the \fB\-M\fP
  363. Xoption to \fBparseargs\fP, or specified an \fIargUsage\fP flag on the command
  364. Xline.  Only the appropriate message is displayed.
  365. X.TP 5
  366. X\|\|2
  367. XA command line syntax error was encountered by \fBparseargs\fP. The offending
  368. Xcommand line argument may have been intended for either \fBparseargs\fP or
  369. Xfor the calling program.
  370. X.TP 5
  371. X\|\|3
  372. XThe environment variable that was specified with the \fB\-e\fP option
  373. Xis either \s-1NULL\s+1 (has an empty value) or does not exist. Perhaps
  374. Xthe user specified a shell variable and/or forgot to export it.
  375. X.TP 5
  376. X\|\|4
  377. XA syntax error was encountered in the argument specification string that was
  378. Xspecified to \fBparseargs\fP.
  379. X.\"-----------------------------------------------------------
  380. X.SH FILES
  381. X.IP "\fI/usr/local/parseargs.pl\fP"
  382. XThis file defines a \fIperl\fP function named \fIparseargs\fP to parse
  383. Xarguments more conveniently for perl-scripts. The function is 
  384. Xboth documented and implemented in this file. The user should
  385. X``require'' this file in his/her perl-script before invoking the
  386. Xfunction.
  387. X.IP "\fI/usr/local/parseargs.awk\fP"
  388. XThis file defines an \fIawk\fP function named \fIparseargs\fP to parse
  389. Xarguments more conveniently for awk-scripts. The function is 
  390. Xboth documented and implemented in this file. The user should
  391. Xinclude this file in his/her awk-script before invoking the
  392. Xfunction.
  393. X.\"-----------------------------------------------------------
  394. X.SH SEE ALSO
  395. X.IR argtype (3),
  396. X.IR parseargs (3),
  397. X.IR parsecntl (3)
  398. X.\"-----------------------------------------------------------
  399. X.so caveats.inc
  400. X.\"-----------------------------------------------------------
  401. X.so bugs.inc
  402. X.\"-----------------------------------------------------------
  403. X.SH AUTHOR
  404. X.nf
  405. XBrad Appleton  (\fIbrad@ssd.csd.harris.com\fP)
  406. XHarris Computer Systems, Fort Lauderdale, FL USA
  407. X.fi
  408. END_OF_FILE
  409. if test 13778 -ne `wc -c <'doc/parseargs.man1'`; then
  410.     echo shar: \"'doc/parseargs.man1'\" unpacked with wrong size!
  411. fi
  412. # end of 'doc/parseargs.man1'
  413. fi
  414. if test -f 'doc/parseargs.man3' -a "${1}" != "-c" ; then 
  415.   echo shar: Will not clobber existing file \"'doc/parseargs.man3'\"
  416. else
  417. echo shar: Extracting \"'doc/parseargs.man3'\" \(11684 characters\)
  418. sed "s/^X//" >'doc/parseargs.man3' <<'END_OF_FILE'
  419. X.\" $Header: parseargs.3,v 2.0 89/12/24 00:56:26 eric Exp $
  420. X.TH PARSEARGS 3
  421. X.\"-----------------------------------------------------------
  422. X.SH NAME
  423. Xparseargs \- parse command line argument vectors
  424. X.\"-----------------------------------------------------------
  425. X.SH SYNOPSIS
  426. X#include <parseargs.h>
  427. X.PP
  428. X.nf
  429. Xint  parseargs(  char *argv\f4[]\fP,  ARGDESC *argd  );
  430. Xint  fparseargs(  FILE *fp,  ARGDESC *argd  );
  431. Xint  lparseargs(  ArgList *argls,  ARGDESC *argd  );
  432. Xint  sparseargs(  char *str,  ARGDESC *argd  );
  433. Xint  vparseargs(  ARGDESC *argd, int argc,  ...  );
  434. Xvoid  usage(  const ARGDESC *argd  );
  435. Xextern  const char *ProgName;
  436. X.fi
  437. X.\"-----------------------------------------------------------
  438. X.SH DESCRIPTION
  439. X.so parseargs3.inc
  440. X.so fparseargs3.inc
  441. X.so lparseargs3.inc
  442. X.so sparseargs3.inc
  443. X.so vparseargs3.inc
  444. X.so usage3.inc
  445. X.PP
  446. XAfter returning from any of the aforementioned functions, the global
  447. Xstring \fIProgName\fP will contain the name of the command corresponding
  448. Xto the argument-descriptor array that was most recently operated upon by
  449. Xone the functions in the \fIparseargs\fP(3) function library.
  450. X.\"-----------------------------------------------------------
  451. X.so argdesc.inc
  452. X.\"-----------------------------------------------------------
  453. X.SH DEFINING ARGDESC ARRAYS
  454. XWhen defining an argdesc array, the first item in the list should
  455. Xbe the item STARTOFARGS. Normal arguments (defined by the programmer)
  456. Xmay then be specified as documented in this manual.
  457. XThe list of arguments is terminated using ENDOFARGS.
  458. X.PP
  459. XFor example, consider the description:
  460. X.sp 4p
  461. X.in +2
  462. X.nf
  463. X.ft 4
  464. Xint    RepCount =    2;
  465. XBOOL    Verbose =    FALSE;
  466. Xchar    *InFile;
  467. Xchar    *OutFile =    CHARNULL;
  468. XBOOL    XRated =    FALSE;
  469. XArgList *Files =    ARGLISTNULL;
  470. X
  471. XARGDESC Args[] =
  472. X{
  473. X  STARTOFARGS,
  474. X  'c', ARGOPT,    argInt,  _\|_ &RepCount, "REPcount {# of repetitions}",
  475. X  'v', ARGOPT,    argBool, _\|_ &Verbose,  "Verbose {set verbose mode}",
  476. X  ' ', ARGREQ,    argStr,  _\|_ &InFile,   "INPUTfile {input file}",
  477. X  ' ', ARGOPT,    argStr,  _\|_ &OutFile,  "OUTPUTfile {output file}",
  478. X  'X', ARGHIDDEN, argBool, _\|_ &XRated,   "XratedMODE {naughty stuff!}",
  479. X  ' ', ARGLIST,   listStr, _\|_ &Files,    "File {files to be read}",
  480. X  ENDOFARGS
  481. X};
  482. X.ft R
  483. X.fi
  484. X.in -2
  485. X.PP
  486. XThis describes a program accepting up to three flag arguments and
  487. Xone or two positional arguments, plus a list of additional file arguments.
  488. XOnly the first positional argument is required.
  489. XThe possible flags (in UNIX) are:
  490. X.TP 10
  491. X\fB\-c\fP \fIcount\fP
  492. XAn integer repetition count.
  493. XThis defaults to two.
  494. X.TP 10
  495. X\fB\-v\fP
  496. XA Boolean ``verbose'' flag.
  497. XIt defaults to FALSE.
  498. X.TP 10
  499. X\fB\-X\fP
  500. XA Boolean ``X Rated'' flag.
  501. XThis is not printed in the usage message.
  502. X.PP
  503. XThe two positional arguments are both strings, as is the final list.
  504. XIn AmigaDOS, the options would be
  505. X\fBREP\fP \fBcount\fP,
  506. X\fBV\fP, and
  507. X\fB\s-1XMODE\s+1\fP.
  508. XIn \s-1VAX/VMS\s+1, the qualifiers would be
  509. X\fB\s-1/REP\s+1\fP=\fIcount\fP,
  510. X\fB\s-1/V\s+1\fP, and
  511. X\fB\s-1/XMODE\s+1\fP.
  512. X.\"-----------------------------------------------------------
  513. X.so argflags.inc
  514. X.\"-----------------------------------------------------------
  515. X.so arg_macros.inc
  516. X.\"-----------------------------------------------------------
  517. X.so cmd_macros.inc
  518. X.\"-----------------------------------------------------------
  519. X.so defargs.inc
  520. X.\"-----------------------------------------------------------
  521. X.so env_args.inc
  522. X.\"-----------------------------------------------------------
  523. X.so env_parse.inc
  524. X.\"-----------------------------------------------------------
  525. X.so env_usage.inc
  526. X.\"-----------------------------------------------------------
  527. X.so multivals.inc
  528. X.\"-----------------------------------------------------------
  529. X.SH ARGUMENT TYPE FUNCTIONS
  530. XThe argument types recognized by
  531. X.I parseargs
  532. Xcan be extended by adding new type functions.
  533. XArgument type functions are declared as:
  534. X.RS
  535. X.PP
  536. X.nf
  537. X.ft 4
  538. XBOOL  argXxx(  ARGDESC *ad,  char *vp,  BOOL copyf  )
  539. X.ft R
  540. X.fi
  541. X.RE
  542. X.PP
  543. XThe \f4ad\fP argument points to the descriptor for the argument being
  544. Xconverted. Its main use is to find the location in which to store the
  545. Xconverted value, located in ad\(->ad_valp.
  546. XThe string value to be converted is passed in \f4vp\fP
  547. X(which will be \s-1NULL\s+1 if the \s-1ARGNOVAL\s+1 flag was set for the
  548. Xcorresponding entry in the arg-descriptor table).
  549. XThe \f4copyf\fP flag is TRUE if the \f4vp\fP string value must be copied
  550. Xwhen saved.  Most non-string types are copied implicitly (for example,
  551. Xinteger arguments are stored in binary form, so the original string value
  552. Xneed not be saved), so this argument can usually be ignored.  Put simply,
  553. Xthis flag is TRUE when \f4vp\fP points to a temporary buffer area.
  554. X.PP
  555. XIf the type function successfully converts the value, and uses the entire
  556. Xvalue, it should return TRUE.  If the type function successfully converts
  557. Xthe value, and uses only \fIN\fP characters of the value, it should return
  558. X-\fIN\fP.  Otherwise, it should print a message using
  559. X.IR usrerr (3)
  560. Xand return FALSE. This message should be of the form
  561. X\fB"invalid xxxx option 'yyyy' for Zzzz"\fP, where xxxx is the type of the
  562. Xoption, yyyy is the string passed in \f4vp\fP, and zzzz is the name (taken
  563. Xfrom \f4ad\(->ad_prompt\fP).
  564. XThe \fIargXxxx\fP function is responsible for detecting if the given argument
  565. Xdescriptor is an \s-1ARGVEC\s+1 argument and for taking the appropriate action.
  566. X.PP
  567. XFor example, a type function that took a filename
  568. Xand stored an open file pointer might be coded as:
  569. X.RS
  570. X.PP
  571. X.nf
  572. X.ft 4
  573. X#define REALLOC(ptr,size)  ((! ptr) ? malloc(size) : realloc(ptr, size))
  574. X.sp 8p
  575. Xtypedef ARGVEC_T(FILE *)  FILEvec_t;
  576. X.sp 8p
  577. XBOOL  argReadFile(  ARGDESC *\|ad,  char *\|vp,  BOOL copyf  )
  578. X{
  579. X    register FILE *fp;
  580. X.sp 4p
  581. X    fp = fopen(vp, "r");
  582. X.sp 4p
  583. X    if ( ! fp ) {
  584. X        usrerr("cannot open '%s' for reading", vp);
  585. X        return (FALSE);
  586. X    }
  587. X.sp 4p
  588. X    if ( BTEST(arg_flags(ad), ARGVEC) ) {
  589. X        FILEvec_t  *vec = (FILEvec_t *) arg_valp(ad);
  590. X        size_t  size  = (1 + vec->count) * (sizeof (FILE *));
  591. X.sp 4p
  592. X        vec->array = (FILE **) REALLOC(vec->array, size);
  593. X        if ( ! vec->array )
  594. X            syserr( "(m|re)alloc failed in argReadFile" );
  595. X.sp 4p
  596. X        vec->flags = (FILE **) REALLOC(vec->flags, size);
  597. X        if ( ! vec->flags )
  598. X            syserr( "(m|re)alloc failed in argReadFile" );
  599. X.sp 4p
  600. X        vec->flags[ vec->count ] = arg_flags(ad);
  601. X        vec->array[ (vec->count)++ ] = fp;
  602. X    }
  603. X    else
  604. X        *(FILE *) arg_valp(ad) = fp;
  605. X.sp 4p
  606. X    return (TRUE);
  607. X}
  608. X.ft R
  609. X.fi
  610. X.RE
  611. X.RE
  612. X.\"------------------------------------------------------------------
  613. X.SH LONG OPTIONS
  614. X.PP
  615. XUnder \s-1UNIX\s+1, \s-1MS-DOS\s+1, and \s-1OS\s+1/2,
  616. X\fIparseargs\fP also allows for long
  617. Xoptions in addition to single character options.
  618. XUnder \s-1UNIX\s+1, long options are denoted by a `\fB+\fP' character 
  619. X(unless \fIparseargs\fP was compiled for conformance with POSIX, inc which
  620. Xcase the long option prefix is `\fB\-\|\-\fP').
  621. XUnder \s-1MS-DOS\s+1, and \s-1OS\s+1/2, long options are denoted by the second
  622. Xcharacter in the \s-1SWITCHAR\s+1 environment variable. If there is no second
  623. Xcharacter, then if the first character is `\-', then a `\fB+\fP' is used,
  624. Xotherwise a `\fB/\fP' is used.
  625. XThe keyword that is used is the first word in the prompt field of an
  626. Xargument descriptor entry. Long options are case insensitive!
  627. XUnder \s-1UNIX\s+1, an argument to a long option may be separated
  628. Xfrom the long option by an equal sign (`=') or by one or more
  629. Xwhitespace characters.  Thus, if an entry looks like:
  630. X.RS
  631. X.sp 4p
  632. X.nf
  633. X.ft 4
  634. X\^'c', ARGOPT, argInt, _\|_ &count, "repCOUNT (# of times to repeat)",
  635. X.ft R
  636. X.fi
  637. X.sp 4p
  638. X.RE
  639. Xthen ``\fB\-c4\fP'', ``\fB+repcount=4\fP'', ``\fB+count=4\fP'',
  640. X``\fB+repcount\04\fP'', and ``\fB+count\04\fP'' will all have the same effect.
  641. X.PP
  642. XThe long option names for ``\fB\-?\fP'' in the default argument descriptor
  643. Xare ``\fB+help\fP'' and ``\fB+?\fP'' (respectively). In addition, ``\fB++\fP''
  644. Xmay be used to indicate the end of options so that
  645. Xall remaining arguments will be interpreted as positional parameters
  646. X(even if one begins with a `\fB+\fP' or a `\fB\-\fP').
  647. X.PP
  648. XUnder \s-1MS-DOS\s+1, and \s-1OS\s+1/2, an argument to a long-option must be
  649. Xseparated from the long option by an equal sign (`=') (unless the first
  650. Xcharacter of $SWITCHAR is a `\-', in which case \s-1UNIX\s+1 syntax is used).
  651. XThe long option names for ``\fB/?\fP'' in the default argument descriptor
  652. Xare ``\fB/help\fP'' and ``\fB/?\fP'' (respectively).
  653. X.PP
  654. XUnder VAX/VMS and AmigaDOS, single-character options are not used and the
  655. X``long'' name (in the prompt field of an argument descriptor) is always used
  656. Xto match for possible arguments (or keywords, or qualifiers).
  657. X.PP
  658. XFor all supported operating systems, a long option may be matched in one of
  659. Xtwo ways: it may match all uppercase characters in the prompt field, or it may
  660. Xmatch all characters in the prompt field (as in ``\fB+count=4\fP'' and
  661. X``\fB+repcount=4\fP'').
  662. X.PP
  663. XUnder all systems except AmigaDOS,
  664. Xonly the number of characters required to uniquely identify the desired argument
  665. Xare needed, but at least two characters must be given (unless the prompt field
  666. Xis itself less than two characters long). This means that using the above
  667. Xexample, that ``\fB+rep=4\fP'' and
  668. X``\fB+cou=4\fP'' would also work but ``\fB+c=4\fP'' would \s-1NOT\s+1 (in other words, if
  669. Xyou only want to use one character, use ``\fB\-c4\fP'' instead).
  670. X.PP
  671. XUnder VAX/VMS, the possibilities using the above example would be:
  672. X``\fB/REPCOUNT=4\fP'', ``\fB/COUNT=4\fP'', ``\fB/REP=4\fP'', and ``\fB/COU=4\fP'',
  673. X.PP
  674. XUnder AmigaDOS, no ``shortened'' keywords are accepted and the possibilities
  675. Xusing the above example would be:
  676. X``\fBREPCOUNT 4\fP'', and ``\fBCOUNT 4\fP''
  677. X.\"------------------------------------------------------------------
  678. X.so returns.inc
  679. X.\"------------------------------------------------------------------
  680. X.so effects.inc
  681. X.\"------------------------------------------------------------------
  682. X.SH "DOCUMENTING YOUR COMMANDS"
  683. X.PP
  684. XThe commands that you write with \fIparseargs\fP(3) may be documented
  685. Xusing \fIparseargs\fP(1). Just copy the argument descriptor array
  686. Xinto a separate file, and invoke \fIparseargs\fP(1) with the \fB\-M\fP
  687. Xoption and pass it the command-name (dont forget to redirect input 
  688. Xto come from your newly created file). It is important to note that the
  689. Xonly portion of that argdesc array to insert into your file is the portion
  690. Xstarting with the very first command-line argument, all the way down to
  691. X(and including) the \s-1ENDOFARGS\s+1 or \s-1END_ARGUMENTS\s+1 entry.
  692. X.\"------------------------------------------------------------------
  693. X.SH FILES
  694. X.IP "\fI/usr/local/lib/libparse.a\fP"
  695. XLink library for parseargs.
  696. X.IP "\fI/usr/local/include/parseargs.h\fP"
  697. XInclude file for parseargs.
  698. X.IP "\fI/usr/local/include/useful.h\fP"
  699. XInclude file for portability.
  700. X.\"------------------------------------------------------------------
  701. X.SH SEE ALSO
  702. X.IR argtype (3),
  703. X.IR parseargs (1),
  704. X.IR parsecntl (3)
  705. X.br
  706. XThe ``C Advisor'' column in
  707. X.ul
  708. XUNIX Review
  709. XVol. 7 No. 11.
  710. X.\"-----------------------------------------------------------
  711. X.so caveats.inc
  712. X.\"-----------------------------------------------------------
  713. X.so lib_bugs.inc
  714. X.\"-----------------------------------------------------------
  715. X.SH AUTHOR
  716. XEric Allman, University of California, Berkeley
  717. X.SH MODIFICATIONS
  718. X.PP
  719. XModified to accept a vector of arguments, better error messages,
  720. XUnix keyword matching, and AmigaDOS version by Peter da Silva.
  721. X.PP
  722. XRewritten by Brad Appleton.
  723. XParseargs(1);
  724. Xfunctions parsecntl, sparseargs, fparseargs, lparseargs, and vparseargs;
  725. Xargument types argUsage, argDummy, argUBool, and argTBool;
  726. Xargument flags \s-1ARGPOS\s+1, \s-1ARGVALOPT\s+1, \s-1ARGVALREQ\s+1,
  727. X\s-1ARGVALGIVEN\s+1, \s-1ARGNOVAL\s+1, and \s-1ARGVEC\s+1; and
  728. X\s-1VAX/VMS\s+1 version and IBM-PC version by Brad Appleton
  729. END_OF_FILE
  730. if test 11684 -ne `wc -c <'doc/parseargs.man3'`; then
  731.     echo shar: \"'doc/parseargs.man3'\" unpacked with wrong size!
  732. fi
  733. # end of 'doc/parseargs.man3'
  734. fi
  735. if test -f 'pgopen.c' -a "${1}" != "-c" ; then 
  736.   echo shar: Will not clobber existing file \"'pgopen.c'\"
  737. else
  738. echo shar: Extracting \"'pgopen.c'\" \(12598 characters\)
  739. sed "s/^X//" >'pgopen.c' <<'END_OF_FILE'
  740. X/*************************************************************************
  741. X** ^FILE: pgopen.c - pipe output to a pager for Unix Systems.
  742. X**
  743. X** ^DESCRIPTION:
  744. X**    The functions in this file implement a minimal paging system
  745. X**    using popen() & pclose() to invoke a specified paging program.
  746. X**
  747. X**    The following public functions are defined:
  748. X**
  749. X**       FILE *pgopen( FILE *fp, const char *pager_cmd )
  750. X**           -- attempt to open the pager, return the corresponding
  751. X**              file-pointer to write to (which will be <fp> if
  752. X**              popen(3S) fails).
  753. X**
  754. X**       int pgclose( FILE *pager_fp )
  755. X**           -- close the pager stream, return 0 on success
  756. X**
  757. X**       int pgactive( const FILE *pager_fp )
  758. X**           -- return TRUE if the pager is open.
  759. X**
  760. X** ^HISTORY:
  761. X**    12/03/90     Brad Appleton     <brad@ssd.csd.harris.com>     Created
  762. X***^^**********************************************************************/
  763. X
  764. X#ifdef  USE_PAGER
  765. X
  766. X
  767. X#include <stdio.h>
  768. X#include <errno.h>
  769. X#include <signal.h>
  770. X#include <setjmp.h>
  771. X#include <useful.h>
  772. X
  773. X/* get #defines for access() call */
  774. X#ifndef SYSV
  775. X# include <sys/file.h>
  776. X#endif
  777. X#ifndef X_OK
  778. X#  define X_OK  0x01
  779. X#endif
  780. X
  781. X#include "exit_codes.h"
  782. X
  783. X/*
  784. X**  Implement a state machine that tries first to use a pager
  785. X**  specified by the user, then as a second choice, /usr/ucb/more,
  786. X**  if all else fails use the given file-pointer (which we assume to
  787. X**  be writable)
  788. X**
  789. X**  The following defines the state machine.
  790. X**
  791. X*/
  792. X
  793. Xtypedef enum  {
  794. X   PG_CLOSED,  /* pager not-yet-open */
  795. X   PG_NONE,    /* No pager used */
  796. X   PG_ENV,     /* the given pager name (or $PAGER) was used */
  797. X   PG_DFLT,    /* default pager (more) used */
  798. X   PG_FILE     /* file-pointer used */
  799. X}  pager_t;
  800. X
  801. X#define  DEFAULT_PAGER   "/usr/ucb/more"
  802. X
  803. X#ifndef TRUE
  804. X#  define  TRUE  1
  805. X#endif
  806. X#ifndef FALSE
  807. X#  define  FALSE 0
  808. X#endif
  809. X
  810. X#define MAX_NAME_LEN  512
  811. X#define isTERMINAL(fd)   ( isatty(fd) ) ? TRUE : (errno = 0, FALSE)
  812. X
  813. Xextern  char *strcpy();
  814. Xextern  int   strcmp();
  815. Xextern  int   access();
  816. Xextern  int   isatty();
  817. Xextern  unsigned   sleep();
  818. X
  819. Xstatic void  pg_error();       /* broken-pipe exception handler */
  820. Xstatic jmp_buf pg_recover;     /* jump-buffer for exception handler */
  821. Xstatic pager_t  pg_pathname();
  822. X
  823. Xstatic pager_t  Pager_Type = PG_CLOSED;
  824. Xstatic FILE    *Pager_FP = (FILE *)NULL;
  825. X
  826. X
  827. X/***************************************************************************
  828. X** ^FUNCTION: pgactive - query pager status
  829. X**
  830. X** ^SYNOPSIS:
  831. X*/
  832. X#ifndef __ANSI_C__
  833. X   int pgactive( pager_fp )
  834. X/*
  835. X** ^PARAMETERS:
  836. X*/
  837. X   FILE *pager_fp;
  838. X/*    -- the file-pointer returned by pgopen()
  839. X*/
  840. X#endif  /* !__ANSI_C__ */
  841. X
  842. X/* ^DESCRIPTION:
  843. X**    Pgactive indicates whether or not the given file-pointer is in
  844. X**    use by the paging system.
  845. X**
  846. X** ^REQUIREMENTS:
  847. X**    pgopen() must first be called in order to obtain a valid
  848. X**    pager-file-pointer.
  849. X**
  850. X** ^SIDE-EFFECTS:
  851. X**    None.
  852. X**
  853. X** ^RETURN-VALUE:
  854. X**    Zero if the pager is active; non-zero otherwise.
  855. X**
  856. X** ^ALGORITHM:
  857. X**    Trivial.
  858. X***^^**********************************************************************/
  859. X#ifdef __ANSI_C__
  860. X   int pgactive( const FILE *pager_fp )
  861. X#endif
  862. X{
  863. X   return  ( (Pager_Type != PG_CLOSED)  &&  (pager_fp) );
  864. X}
  865. X
  866. X
  867. X/***************************************************************************
  868. X** ^FUNCTION: pgclose - close the pager.
  869. X**
  870. X** ^SYNOPSIS:
  871. X*/
  872. X#ifndef __ANSI_C__
  873. X   int pgclose( pager_fp )
  874. X/*
  875. X** ^PARAMETERS:
  876. X*/
  877. X   FILE *pager_fp;
  878. X/*    -- the file-pointer returned by pgopen()
  879. X*/
  880. X#endif  /* !__ANSI_C__ */
  881. X
  882. X/* ^DESCRIPTION:
  883. X**    Pgclose will flush any remaining output and close the pager.
  884. X**
  885. X** ^REQUIREMENTS:
  886. X**    pgopen() must first be called in order to obtain a valid
  887. X**    pager-file-pointer.
  888. X**
  889. X** ^SIDE-EFFECTS:
  890. X**    None.
  891. X**
  892. X** ^RETURN-VALUE:
  893. X**    Returns 0 if the pager was succesfully close; non-zero if it wasnt
  894. X**    in use to begin with.
  895. X**
  896. X** ^ALGORITHM:
  897. X**    - if ( pager-not-in-use )  return 1
  898. X**    - flush any remaining pager output
  899. X**    - if we used popen() to open this pager then
  900. X**       - call pclose to close the pager-program
  901. X**       - unset the SIGPIPE signal-handler
  902. X**      end-if
  903. X**    - reset the pager-file-pointer to NULL
  904. X**    - set the pager-state to closed
  905. X**    - return 0
  906. X***^^**********************************************************************/
  907. X#ifdef __ANSI_C__
  908. X   int pgclose( FILE *pager_fp )
  909. X#endif
  910. X{
  911. X   if ( Pager_Type == PG_CLOSED  ||  !Pager_FP  ||  !pager_fp )  return  1;
  912. X
  913. X   fflush( Pager_FP );
  914. X
  915. X   if ( Pager_Type == PG_ENV  ||  Pager_Type == PG_DFLT ) {
  916. X      (VOID) pclose( Pager_FP );
  917. X      (VOID) signal( SIGPIPE, (void (*)())SIG_IGN );
  918. X   }
  919. X
  920. X   Pager_FP = (FILE *)NULL;
  921. X   Pager_Type = PG_CLOSED;
  922. X
  923. X   return  0;
  924. X}
  925. X
  926. X
  927. X/***************************************************************************
  928. X** ^FUNCTION: pgopen - open the pager
  929. X**
  930. X** ^SYNOPSIS:
  931. X*/
  932. X#ifndef __ANSI_C__
  933. X   FILE *pgopen( fp, pager_cmd )
  934. X/*
  935. X** ^PARAMETERS:
  936. X*/
  937. X   FILE *fp;
  938. X/*    -- the file pointer to use if popen() fails
  939. X*/
  940. X   char *pager_cmd;
  941. X/*    -- name of the pager-program to pass to popen()
  942. X*/
  943. X#endif  /* !__ANSI_C__ */
  944. X
  945. X/* ^DESCRIPTION:
  946. X**    Pgopen will attempt to "redirect" output from the given file
  947. X**    pointer to the pager specified by <pager_cmd>.  If <fp> is NOT
  948. X**    connected to a terminal or <pager_cmd> cannot be succesfully
  949. X**    opened, then <fp> is resturned output is sent to it unpaginated.
  950. X**    Otherwise, pgopen will try to open <pager_cmd> for input. If it
  951. X**    cannot succeed it tries to open $PAGER for input. If this also
  952. X**    fails then /usr/ucb/more is tried. If all else fails, return <fp>.
  953. X**
  954. X** ^REQUIREMENTS:
  955. X**    pager_cmd should be the full-pathname name of a valid, executable
  956. X**    program which reads from standard input and writes (one screenful
  957. X**    at a time) to the terminal.
  958. X**
  959. X** ^SIDE-EFFECTS:
  960. X**    If popen() succeeds, the SIGPIPE signal is trapped.
  961. X**
  962. X** ^RETURN-VALUE:
  963. X**    returns 0 upon success, non-zero if the pager is already in use.
  964. X**
  965. X** ^ALGORITHM:
  966. X**    - if the pager is already in use, return 1
  967. X**    - if <fp> is not connected to a terminal, use it for output and return 0
  968. X**    - set up recovery point for SIGPIPE signal
  969. X**    - if we can open the pager_cmd, check for a SIGPIPE error
  970. X**    - if either of the above fails, then try the same with $PAGER
  971. X**    - if either of the above fails, then try the same with /usr/ucb/more
  972. X**    - if either of the above fails, just use <fp> and return
  973. X***^^**********************************************************************/
  974. X#ifdef __ANSI_C__
  975. X   FILE *pgopen( FILE *fp, const char *pager_cmd )
  976. X#endif
  977. X{
  978. X   pager_t  pg_type;
  979. X   char     pg_name[ MAX_NAME_LEN ];
  980. X
  981. X      /* if a pager is already open - ignore this call */
  982. X   if ( Pager_Type != PG_CLOSED  ||  Pager_FP )  return  fp;
  983. X
  984. X      /*
  985. X      ** dont page output if it has been redirected
  986. X      */
  987. X   if ( !isTERMINAL(fileno(fp)) ) {
  988. X      Pager_Type = PG_FILE;
  989. X      Pager_FP = fp;
  990. X      return  fp;
  991. X   }
  992. X
  993. X   *pg_name = '\0';
  994. X   if ( pager_cmd )  strcpy( pg_name, pager_cmd );
  995. X   pg_type = pg_pathname( pg_name );
  996. X   Pager_FP = (FILE *)NULL;
  997. X
  998. X      /* jump here after pg_error fields SIGPIPE */
  999. X   if ( setjmp( pg_recover ) ) {
  1000. X      (void) pclose( Pager_FP );
  1001. X      Pager_FP = (FILE *)NULL;
  1002. X      pg_type = ( pg_type == PG_ENV ) ? PG_DFLT : PG_NONE;
  1003. X   }
  1004. X
  1005. X      /* keep trying till we get a valid file-pointer */
  1006. X   while ( !Pager_FP ) {
  1007. X      switch( pg_type ) {
  1008. X         case PG_DFLT:
  1009. X               /* jump here if both $PAGER and DEFAULT-PAGER fail */
  1010. X            if ( setjmp( pg_recover )) {
  1011. X               (void) pclose( Pager_FP );
  1012. X               Pager_FP = (FILE *)NULL;
  1013. X               pg_type = PG_NONE;
  1014. X               continue;
  1015. X            }
  1016. X               /* fall through to next case */
  1017. X
  1018. X         case PG_ENV:
  1019. X            signal( SIGPIPE, pg_error );
  1020. X            Pager_FP = (FILE *) popen( pg_name, "w" );
  1021. X            if ( !Pager_FP ) {
  1022. X               if ( pg_type == PG_ENV ) {
  1023. X                  Pager_FP = (FILE *)NULL;
  1024. X                  pg_type = PG_DFLT;
  1025. X               }
  1026. X               else {
  1027. X                  Pager_FP = fp;
  1028. X                  pg_type = PG_NONE;
  1029. X               }
  1030. X            }
  1031. X            else {
  1032. X                  /*
  1033. X                  ** Sleep for a bit, just so we block, and the child
  1034. X                  ** process can get moving. Then attempt to write to
  1035. X                  ** the pager pipeline. If the pager is bad then the
  1036. X                  ** pipe will be broken and pg_error() will handle
  1037. X                  ** the broken-pipe signal. Othwerwise, the write will
  1038. X                  ** succeed and we'll reset the handler to ignore the
  1039. X                  ** broken pipe signal.
  1040. X                  */
  1041. X               sleep( 1 );
  1042. X               fputc( '\n', Pager_FP );
  1043. X               fflush( Pager_FP );
  1044. X               signal( SIGPIPE, (void (*)())SIG_IGN );
  1045. X            }
  1046. X            break;
  1047. X
  1048. X         case PG_NONE:
  1049. X         case PG_FILE:
  1050. X            Pager_FP = fp;
  1051. X            break;
  1052. X
  1053. X         default:
  1054. X            fprintf( stderr, "Unrecognized state [%d] in pgopen()\n",
  1055. X                     pg_type );
  1056. X            exit( exit_SYSTEM );
  1057. X      }/*switch*/
  1058. X   }/*while*/
  1059. X
  1060. X   Pager_Type = pg_type;
  1061. X   return  Pager_FP;
  1062. X}
  1063. X
  1064. X
  1065. X/***************************************************************************
  1066. X** ^FUNCTION: pg_error - handle error when trying to open a pager
  1067. X**
  1068. X** ^SYNOPSIS:
  1069. X*/
  1070. X#ifndef __ANSI_C__
  1071. X   static void pg_error()
  1072. X#endif
  1073. X/*
  1074. X** ^PARAMETERS:
  1075. X**    None.
  1076. X**
  1077. X** ^DESCRIPTION:
  1078. X**    Pgerror is called when the SIGPIPE signal is recieved. If SIGPIPE
  1079. X**    is recieved, it means that popen succesfully forked the shell to
  1080. X**    run the pager but the pager-command itself broke the read-end of
  1081. X**    the pipe between us (i.e. it is an invalid pager-program or it crashed).
  1082. X**
  1083. X**    When SIGPIPE is recieved, this routine will reset the signal handler
  1084. X**    to its previous value and jump to the recovery point set up by pgopen.
  1085. X**
  1086. X** ^REQUIREMENTS:
  1087. X**    Pgopen must set up this function is the SIGPIPE handler function.
  1088. X**
  1089. X**    Pgopen must place the address of the desired recovery point in
  1090. X**    pg_recover.
  1091. X**
  1092. X** ^SIDE-EFFECTS:
  1093. X**    Resets SIGPIPE signal-handler and performs a non-local goto.
  1094. X**
  1095. X** ^RETURN-VALUE:
  1096. X**    None.
  1097. X**
  1098. X** ^ALGORITHM:
  1099. X**    Trivial.
  1100. X***^^**********************************************************************/
  1101. X#ifdef __ANSI_C__
  1102. X   static void pg_error( void )
  1103. X#endif
  1104. X{
  1105. X   signal( SIGPIPE, (void (*)())SIG_IGN );
  1106. X   longjmp( pg_recover, 1 );
  1107. X}
  1108. X
  1109. X
  1110. X/***************************************************************************
  1111. X** ^FUNCTION: pg_pathname - get name of pager-program to use
  1112. X**
  1113. X** ^SYNOPSIS:
  1114. X*/
  1115. X#ifndef __ANSI_C__
  1116. X   static pager_t pg_pathname( pager_cmd )
  1117. X/*
  1118. X** ^PARAMETERS:
  1119. X*/
  1120. X   char *pager_cmd;
  1121. X/*    -- name of the pager-program to verify
  1122. X*/
  1123. X#endif  /* !__ANSI_C__ */
  1124. X/* ^DESCRIPTION:
  1125. X**    Pg_pathname will determine the name of the pager-program to attempt to
  1126. X**    open based on the values of pager_cmd, and $PAGER.
  1127. X**
  1128. X** ^REQUIREMENTS:
  1129. X**    pager_cmd must be non-null and be large enough to hold any of the
  1130. X**    possible pager program-names to be opened.
  1131. X**
  1132. X** ^SIDE-EFFECTS:
  1133. X**    pager_cmd is over-written with the name of the pager-command to
  1134. X**    try to open for output
  1135. X**
  1136. X** ^RETURN-VALUE:
  1137. X**    Returns PG_DFLT if /usr/ucb/more is to be used.
  1138. X**    Returns PG_ENV if $PAGER or <pager_cmd> is to be used.
  1139. X**
  1140. X** ^ALGORITHM:
  1141. X**    - If pager_cmd is executable then compare it to /usr/ucb/more
  1142. X**        return PG_ENV if not-equal, else return PG_DFLT
  1143. X**    - Else
  1144. X**      - pager_cmd = $PAGER
  1145. X**      - If $PAGER is executable then compare it to /usr/ucb/more
  1146. X**          return PG_ENV if not-equal, else return PG_DFLT
  1147. X**      - Else
  1148. X**          pager_cmd = /usr/ucb/more
  1149. X**          return  PG_DFLT
  1150. X**        End-if
  1151. X**      End-if
  1152. X***^^**********************************************************************/
  1153. X#ifdef __ANSI_C__
  1154. X   static pager_t  pg_pathname( char *pager_cmd )
  1155. X#endif
  1156. X{
  1157. X   char      *pg_name = pager_cmd, *getenv();
  1158. X   pager_t   pg_type;
  1159. X
  1160. X   if ( Pager_Type != PG_NONE )   pg_type = Pager_Type;
  1161. X
  1162. X      /* see if the given pager is okay */
  1163. X   if ( !pg_name  ||  !*pg_name  ||  access(pg_name, X_OK) ) {
  1164. X      pg_name = getenv("PAGER");
  1165. X   }
  1166. X   else {
  1167. X      pg_type = ( strcmp(pager_cmd, DEFAULT_PAGER) ) ? PG_ENV : PG_DFLT;
  1168. X      return   pg_type;
  1169. X   }
  1170. X
  1171. X      /* see if $PAGER is ok */
  1172. X   if ( !access(pg_name, X_OK) ) {
  1173. X      pg_type = ( strcmp(pg_name, DEFAULT_PAGER) ) ? PG_ENV : PG_DFLT;
  1174. X      strcpy( pager_cmd, pg_name );
  1175. X   }
  1176. X   else {
  1177. X      pg_type = PG_DFLT;
  1178. X      strcpy( pager_cmd, DEFAULT_PAGER );
  1179. X   }
  1180. X
  1181. X   return   pg_type;
  1182. X}/* pg_pathname */
  1183. X
  1184. X
  1185. X#endif  /* USE_PAGER */
  1186. END_OF_FILE
  1187. if test 12598 -ne `wc -c <'pgopen.c'`; then
  1188.     echo shar: \"'pgopen.c'\" unpacked with wrong size!
  1189. fi
  1190. # end of 'pgopen.c'
  1191. fi
  1192. if test -f 'stest.c' -a "${1}" != "-c" ; then 
  1193.   echo shar: Will not clobber existing file \"'stest.c'\"
  1194. else
  1195. echo shar: Extracting \"'stest.c'\" \(9296 characters\)
  1196. sed "s/^X//" >'stest.c' <<'END_OF_FILE'
  1197. X/*************************************************************************
  1198. X** ^FILE: stest.c - test program for parseargs()
  1199. X**
  1200. X** ^DESCRIPTION:
  1201. X**    This file is the test program for the parseargs(3) function libarary.
  1202. X**    It is used to test parseargs for all command-line styles (which presently
  1203. X**    includes: UNIX, VMS, AmigaDOS, MS-DOS, and OS/2).
  1204. X**
  1205. X** ^HISTORY:
  1206. X**    --/--/--    Brad Appleton    <brad@ssd.csd.harris.com>    
  1207. X**    - Added structured block comments
  1208. X**    - Added an extra test for both old-style and new-style argument arrays
  1209. X**    - Added a test for triggers (ARGNOVAL arguments)
  1210. X**    - Added a test for arguments with optional values (using parsecntl())
  1211. X**    - Added arg-vector arguments
  1212. X**
  1213. X**    --/--/--    Peter da Silva    <peter@ferranti.com>    
  1214. X**
  1215. X**    --/--/--    Eric P. Allman    <eric@Berkeley.EDU>     Created
  1216. X***^^**********************************************************************/
  1217. X
  1218. X#include <useful.h>
  1219. X#include <parseargs.h>
  1220. X
  1221. X#ifdef vms
  1222. X# include <ssdef.h>
  1223. X#endif
  1224. X
  1225. XVERSIONID("$Header: stest.c,v 2.0 89/12/24 00:56:29 eric Exp $");
  1226. X
  1227. Xstatic char Mode[4] = "OFF";
  1228. X
  1229. X/***************************************************************************
  1230. X** ^FUNCTION: argMine - example ARGNOVAL argument translation routine
  1231. X**
  1232. X** ^SYNOPSIS:
  1233. X*/
  1234. X#ifndef __ANSI_C__
  1235. X   BOOL argMine( ad, vp, copyf )
  1236. X/*
  1237. X** ^PARAMETERS:
  1238. X*/
  1239. X   ARGDESC *ad;
  1240. X/*    -- the argument descriptor for this parameter.
  1241. X*/
  1242. X   char *vp;
  1243. X/*    -- a pointer to the string input value.
  1244. X*/
  1245. X   BOOL copyf;
  1246. X/*    -- if TRUE, the value will be destroyed later, and so should be
  1247. X**       copied if it will be retained (as for a string).
  1248. X*/
  1249. X#endif  /* !__ANSI_C__ */
  1250. X
  1251. X/* ^DESCRIPTION:
  1252. X**    This routine is provided as a (very) simple example of how to use
  1253. X**    the ARGNOVAL flag to set up "trigger" arguments. Depending upon the
  1254. X**    implementation of the "trigger" function (this routine), the position
  1255. X**    of the corresponding argument on the command line may (or may not) be
  1256. X**    important.
  1257. X**
  1258. X** ^REQUIREMENTS:
  1259. X**    ad should have ARGNOVAL set and this function as its ad_type.
  1260. X**
  1261. X** ^SIDE-EFFECTS:
  1262. X**    The static global variable Mode is (re)written.
  1263. X**
  1264. X** ^RETURN-VALUE:
  1265. X**    TRUE.
  1266. X**
  1267. X** ^ALGORITHM:
  1268. X**    Trivial.
  1269. X***^^**********************************************************************/
  1270. X/*ARGSUSED*/
  1271. X#ifdef __ANSI_C__
  1272. X   BOOL argMine( ARGDESC *ad, char *vp, BOOL copyf )
  1273. X#endif
  1274. X{
  1275. X   strcpy(Mode, "ON");
  1276. X   return TRUE;
  1277. X}
  1278. X
  1279. X/*************************************************************************/
  1280. X   /* declare variables to hold values from the command-line */
  1281. X#define DEF_STR "Default String"
  1282. X
  1283. Xtypedef ARGVEC_T(char *)  strvec_t;
  1284. X
  1285. Xstatic int    RepCount;
  1286. Xstatic char    *Name;
  1287. Xstatic char    *Str     = DEF_STR;
  1288. Xstatic char    *DirName = ".";
  1289. Xstatic BOOL    XRated   = FALSE;
  1290. Xstatic BOOL    XFlag    = FALSE;
  1291. Xstatic BOOL    YFlag    = TRUE;
  1292. Xstatic BOOL    ZFlag    = FALSE;
  1293. Xstatic char    TabChar  = ':';
  1294. Xstatic ARGVEC_T(int) Integers = ARGVEC_EMPTY(int);
  1295. Xstatic strvec_t Groups = ARGVEC_EMPTY(char *);
  1296. Xstatic ArgList  *Argv  = (ArgList *)NULL;
  1297. X
  1298. X/*************************************************************************/
  1299. X   /* declare a new style argument-descriptor array */
  1300. Xstatic
  1301. XCMD_OBJECT
  1302. X   Cmd
  1303. X
  1304. XCMD_NAME
  1305. X   "stest -- test program for parseargs"
  1306. X
  1307. XCMD_DESCRIPTION
  1308. X   "This program is used to test parseargs for each desired command-line \
  1309. Xstyle and for both old and new style argument-array declarations.  The actual \
  1310. Xname of the command will be <os>_test.  parseargs will be called twice (with \
  1311. Xthe same command-line description) in order to test both the old and the new \
  1312. Xsyntax for declaring argument arrays."
  1313. X
  1314. XCMD_ARGUMENTS
  1315. X   'n', ARGREQ|ARGPOS, argStr,  __ &Name,  "name (name to look for)",
  1316. X   's', ARGVALOPT, argStr,  __ &Str,       "STRing (optional string to use)",
  1317. X   'g', ARGVEC,    argStr,  __ &Groups,    "newsGROUPS (newsgroups to test)",
  1318. X   'c', ARGOPT,    argInt,  __ &RepCount,  "REP=count (repeat count per group)",
  1319. X   'd', ARGOPT,    argStr,   __ &DirName,  "DIRname (work directory)",
  1320. X   'i', ARGVEC,    argInt,   __ &Integers, "INTegerS (vector of numbers)",
  1321. X   '#', ARGHIDDEN, argBool,  __ &XRated,   "XratedMODE (naughty! naughty!)",
  1322. X
  1323. X   'x', ARGOPT, argSBool, __ &XFlag, "Xflag (set X flag)",
  1324. X   'y', ARGOPT, argUBool, __ &YFlag, "Yflag (unset Y flag)",
  1325. X   'z', ARGOPT, argTBool, __ &ZFlag, "Zflag (toggle Z flag)",
  1326. X
  1327. X   't', ARGOPT,   argChar, __ &TabChar, "TAB=char (field delimiter)",
  1328. X   'r', ARGNOVAL, argMine, __ NULL,     "raw (trigger raw-mode \
  1329. Xbefore processing any more arguments on the command-line)",
  1330. X
  1331. X   ' ', ARGLIST, listStr, __ &Argv, "file (list of files)",
  1332. X
  1333. X   END_ARGUMENTS
  1334. XCMD_END
  1335. X
  1336. X
  1337. X/*************************************************************************/
  1338. X   /* declare an old style argument-descriptor array */
  1339. Xstatic ARGDESC    Args[] =
  1340. X{
  1341. X   STARTOFARGS,
  1342. X
  1343. X   'n', ARGREQ|ARGPOS, argStr,  __ &Name,  "name (name to look for)",
  1344. X   's', ARGVALOPT, argStr,  __ &Str,       "STRing (optional string to use)",
  1345. X   'g', ARGVEC,    argStr,  __ &Groups,    "newsGROUPS (newsgroups to test)",
  1346. X   'c', ARGOPT,    argInt,  __ &RepCount,  "REP=count (repeat count per group)",
  1347. X   'd', ARGOPT,    argStr,   __ &DirName,  "DIRname (work directory)",
  1348. X   'i', ARGVEC,    argInt,   __ &Integers, "INTegerS (vector of numbers)",
  1349. X   '#', ARGHIDDEN, argBool,  __ &XRated,   "XratedMODE (naughty! naughty!)",
  1350. X
  1351. X   'x', ARGOPT, argSBool, __ &XFlag, "Xflag (set X flag)",
  1352. X   'y', ARGOPT, argUBool, __ &YFlag, "Yflag (unset Y flag)",
  1353. X   'z', ARGOPT, argTBool, __ &ZFlag, "Zflag (toggle Z flag)",
  1354. X
  1355. X   't', ARGOPT,   argChar, __ &TabChar, "TAB=char (field delimiter)",
  1356. X   'r', ARGNOVAL, argMine, __ NULL,     "raw (trigger raw-mode \
  1357. Xbefore processing any more arguments on the command-line)",
  1358. X
  1359. X   ' ', ARGLIST, listStr, __ &Argv, "file (list of files)",
  1360. X
  1361. X   ENDOFARGS
  1362. X};
  1363. X
  1364. X
  1365. X/***************************************************************************
  1366. X** ^FUNCTION: reset_args - reset argument values for another pass
  1367. X**
  1368. X** ^SYNOPSIS:
  1369. X*/
  1370. X#ifndef __ANSI_C__
  1371. X   static VOID reset_args()
  1372. X#endif
  1373. X/*  
  1374. X** ^PARAMETERS:
  1375. X**    None.
  1376. X**
  1377. X** ^DESCRIPTION:
  1378. X**    Reset_args resets all the argument values to their corresponding
  1379. X**    default values so that we can (re)test the parseargs library.
  1380. X**
  1381. X** ^REQUIREMENTS:
  1382. X**    None.
  1383. X**
  1384. X** ^SIDE-EFFECTS:
  1385. X**    All the static-global argument variables are rewritten.
  1386. X**
  1387. X** ^RETURN-VALUE:
  1388. X**    None.
  1389. X**
  1390. X** ^ALGORITHM:
  1391. X**    Trivial.
  1392. X***^^**********************************************************************/
  1393. X#ifdef __ANSI_C__
  1394. X   static void reset_args( void )
  1395. X#endif
  1396. X{
  1397. X   RepCount = 0;
  1398. X   Name     = CHARNULL;
  1399. X   Str      = DEF_STR;
  1400. X   DirName  = ".";
  1401. X   XRated   = FALSE;
  1402. X   XFlag    = FALSE;
  1403. X   YFlag    = TRUE;
  1404. X   ZFlag    = FALSE;
  1405. X   TabChar  = ':';
  1406. X
  1407. X   vecFree(Integers, int);
  1408. X   vecDeepFree(Groups, char *);
  1409. X   listFree( Argv );
  1410. X   Argv = ARGLISTNULL;
  1411. X}
  1412. X
  1413. X
  1414. X/***************************************************************************
  1415. X** ^FUNCTION: print_args - print current argument values
  1416. X**
  1417. X** ^SYNOPSIS:
  1418. X*/
  1419. X#ifndef __ANSI_C__
  1420. X   static void print_args( argd )
  1421. X/*
  1422. X** ^PARAMETERS:
  1423. X*/
  1424. X   ARGDESC *argd;
  1425. X/*    -- the command whose arg-values are to be printed
  1426. X*/
  1427. X#endif  /* !__ANSI_C__ */
  1428. X
  1429. X/* ^DESCRIPTION:
  1430. X**    Print the current values of all the command-line settings
  1431. X**
  1432. X** ^REQUIREMENTS:
  1433. X**    The command-line should have already been parsed by one of the
  1434. X**    Xparseargs functions.
  1435. X**
  1436. X** ^SIDE-EFFECTS:
  1437. X**    Prints on stdout.
  1438. X**
  1439. X** ^RETURN-VALUE:
  1440. X**    None.
  1441. X**
  1442. X** ^ALGORITHM:
  1443. X**    Trivial.
  1444. X***^^**********************************************************************/
  1445. X#ifdef __ANSI_C__
  1446. X   static void print_args( const ARGDESC *argd )
  1447. X#endif
  1448. X{
  1449. X   int  i;
  1450. X   argMask_t flags;
  1451. X   ArgList *ls;
  1452. X
  1453. X   printf( "Name = \"%s\", DirName = \"%s\", RepCount = %d,\n",
  1454. X           Name, DirName, RepCount );
  1455. X
  1456. X   printf( "XFlag = %d, YFlag = %d, ZFlag = %d, TabChar='%c'(%03o);\n",
  1457. X           XFlag, YFlag, ZFlag, TabChar, TabChar );
  1458. X
  1459. X   printf( "XRated=%d, Raw-Mode = \"%s\"\n", XRated, Mode );
  1460. X
  1461. X      /* to call parsecntl() to see if the optional value was supplied */
  1462. X   i = parsecntl( (ARGDESC *)argd, pc_ARGFLAGS, pc_READ, "string", &flags);
  1463. X
  1464. X   if ( BTEST(flags, ARGGIVEN) && !BTEST(flags, ARGVALGIVEN) ) {
  1465. X      printf("String=!No Value Given on CmdLine!\n" );
  1466. X   }
  1467. X   else {
  1468. X      printf("String=\"%s\"\n", Str);
  1469. X   }
  1470. X
  1471. X   if (Groups.count) {
  1472. X      printf("Newsgroups:");
  1473. X      for (i = 0 ; i < Groups.count ; i++ ) {
  1474. X         printf(" %s", Groups.array[i]);
  1475. X      }
  1476. X      putchar('\n');
  1477. X   }
  1478. X
  1479. X   if (Integers.count) {
  1480. X      printf("Integers:");
  1481. X      for (i = 0 ; i < Integers.count ; i++ ) {
  1482. X         printf(" %d", Integers.array[i]);
  1483. X      }
  1484. X      putchar('\n');
  1485. X   }
  1486. X
  1487. X   if (Argv)  printf("Remaining args: ");
  1488. X   for ( ls = Argv ; ls ; L_ADVANCE(ls) ) {
  1489. X      printf("%s", L_STRING(ls));
  1490. X      if ( L_NEXT(ls) ) {
  1491. X         putchar(' ');
  1492. X      }
  1493. X      else {
  1494. X         putchar('\n');
  1495. X      }
  1496. X   }/*for*/
  1497. X}
  1498. X
  1499. X
  1500. X/*ARGSUSED*/
  1501. XMAIN(argc, argv)
  1502. X{
  1503. X   parseargs(argv, Cmd);   /* parse the command-line */
  1504. X   print_args(Cmd);        /* print what we found */
  1505. X
  1506. X   putchar('\n');
  1507. X   reset_args();           /* reset args for another pass */
  1508. X
  1509. X   parseargs(argv, Args);  /* parse same command-line using old-style argd */
  1510. X   print_args(Args);       /* print what we found (should be same as before) */
  1511. X
  1512. X#ifdef vms
  1513. X   exit(SS$_NORMAL);
  1514. X#else
  1515. X   exit(0);  /* wave bye-bye */
  1516. X#endif
  1517. X}
  1518. END_OF_FILE
  1519. if test 9296 -ne `wc -c <'stest.c'`; then
  1520.     echo shar: \"'stest.c'\" unpacked with wrong size!
  1521. fi
  1522. # end of 'stest.c'
  1523. fi
  1524. if test -f 'unix_man.c' -a "${1}" != "-c" ; then 
  1525.   echo shar: Will not clobber existing file \"'unix_man.c'\"
  1526. else
  1527. echo shar: Extracting \"'unix_man.c'\" \(8905 characters\)
  1528. sed "s/^X//" >'unix_man.c' <<'END_OF_FILE'
  1529. X/*************************************************************************
  1530. X** ^FILE: unix_man.c - print manual templates for user command
  1531. X**
  1532. X** ^DESCRIPTION:
  1533. X**    This file is the portion of parseargs(1) that prints a Unix
  1534. X**    manual template of a given command on the standard output.
  1535. X**    The template is formatted for {n|t}roff using the -man macros.
  1536. X**
  1537. X** ^HISTORY:
  1538. X**    27/08/91     Earl Chew     <cechew@bruce.cs.monash.edu.au>
  1539. X**    - Use ProgNameLen when accessing ProgName
  1540. X**    - Use get_argpfx() to access names
  1541. X**
  1542. X**    01/02/91     Brad Appleton     <brad@ssd.csd.harris.com>     Created
  1543. X***^^**********************************************************************/
  1544. X
  1545. X#include <stdio.h>
  1546. X#include <ctype.h>
  1547. X#include <useful.h>
  1548. X#include "strfuncs.h"
  1549. X
  1550. X#define PARSEARGS_PRIVATE   /* include private definitions */
  1551. X#include "parseargs.h"
  1552. X
  1553. XEXTERN  VOID  syserr  ARGS((const char *, ...));
  1554. XEXTERN  VOID  usrerr  ARGS((const char *, ...));
  1555. X
  1556. X#define MAXCOLS  65
  1557. X#define VAL(str)           ((str) ? str : "")
  1558. X#define COMMENT            printf(".\\\"-----------------------------------\n")
  1559. X#define TH(title,len,section)  printf(".TH %.*s %d\n", len, title, section )
  1560. X#define SH(title)          printf(".SH %s\n", title )
  1561. X#define TP(cols,title)     printf(".TP %d\n%s\n", cols, title )
  1562. X#define PP                 printf(".PP\n" )
  1563. X
  1564. X
  1565. X/***************************************************************************
  1566. X** ^FUNCTION: fmtarg - format command-argument syntax
  1567. X**
  1568. X** ^SYNOPSIS:
  1569. X*/
  1570. X#ifndef __ANSI_C__
  1571. X   static int fmtarg( ad, buf )
  1572. X/*
  1573. X** ^PARAMETERS:
  1574. X*/
  1575. X   ARGDESC *ad;
  1576. X/*    -- pointer to the argument to format
  1577. X*/
  1578. X   char *buf;
  1579. X/*    -- character buffer to hold the formatted result
  1580. X*/
  1581. X#endif  /* !__ANSI_C__ */
  1582. X
  1583. X/* ^DESCRIPTION:
  1584. X**    Fmtarg will determine the proper command-line syntax for the
  1585. X**    given argument and write the result to the given buffer.
  1586. X**
  1587. X** ^REQUIREMENTS:
  1588. X**    buf must be large enough to hold the formatted result (100 characters
  1589. X**    should do the trick).
  1590. X**
  1591. X** ^SIDE-EFFECTS:
  1592. X**    buf is overwritten.
  1593. X**
  1594. X** ^RETURN-VALUE:
  1595. X**    The number of printable characters in the argument-syntax-string
  1596. X**
  1597. X** ^ALGORITHM:
  1598. X**    Print argument usage based on whether or not the argument is
  1599. X**    positional, hidden, multi-valued (list or vector), etc ....
  1600. X**    Optional arguments and values are enclosed in square braces.
  1601. X***^^**********************************************************************/
  1602. X#ifdef __ANSI_C__
  1603. X   static int fmtarg( const ARGDESC *ad , char *buf )
  1604. X#endif
  1605. X{
  1606. X      /* buf must already be large enough */
  1607. X   char *pos;
  1608. X   argName_t   name;
  1609. X
  1610. X   (VOID) get_argname( arg_sname(ad), name );
  1611. X
  1612. X   if (ARG_isPOSITIONAL(ad)) {
  1613. X       if ( ARG_isMULTIVAL(ad) ) {
  1614. X          sprintf( buf, "\\fI%s\\fP\\ ...", name );
  1615. X          return   (strlen(name) + 4);
  1616. X       }/*if list*/
  1617. X
  1618. X       sprintf( buf, "\\fI%s\\fP", name );
  1619. X       return  strlen(name);
  1620. X   }/*if parm*/
  1621. X
  1622. X#ifdef SVR4
  1623. X   sprintf(buf, "\\f4\\-%c\\fP", arg_cname(ad));
  1624. X#else
  1625. X   sprintf(buf, "\\fB\\-%c\\fP", arg_cname(ad));
  1626. X#endif
  1627. X   pos = buf + strlen(buf);
  1628. X
  1629. X   if ( ARG_isVALTAKEN(ad)  &&  !ARG_isBOOLEAN(ad)  &&  !ARG_isPSEUDOARG(ad) ) {
  1630. X       if ( ARG_isMULTIVAL(ad) ) {
  1631. X          if ( ARG_isVALOPTIONAL(ad) ) {
  1632. X             sprintf(pos, "\\ \\s-1[\\s+1\\fI%s\\fP\\ ...\\s-1]\\s+1", name);
  1633. X             return  (strlen(name) + 9);
  1634. X          }/*if optarg*/
  1635. X
  1636. X          sprintf( pos, "\\ \\fI%s\\ ...\\fP", name );
  1637. X          return  (strlen(name) + 7);
  1638. X       }/*if list*/
  1639. X
  1640. X       if ( ARG_isVALOPTIONAL(ad) ) {
  1641. X          sprintf( pos, "\\ \\s-1[\\s+1\\fI%s\\fP\\s-1]\\s+1", name );
  1642. X          return  (strlen(name) + 5);
  1643. X       }/*if optarg*/
  1644. X
  1645. X       sprintf( pos, "\\ \\fI%s\\fP", name );
  1646. X       return  (strlen(name) + 3);
  1647. X   }/*if*/
  1648. X
  1649. X   return  2;
  1650. X}
  1651. X
  1652. X
  1653. X/***************************************************************************
  1654. X** ^FUNCTION: manpage - print the manual template
  1655. X**
  1656. X** ^SYNOPSIS:
  1657. X*/
  1658. X#ifndef __ANSI_C__
  1659. X   VOID manpage ( argd )
  1660. X/*
  1661. X** ^PARAMETERS:
  1662. X*/
  1663. X   ARGDESC *argd;
  1664. X/*    -- the command-argdesc-array
  1665. X*/
  1666. X#endif  /* !__ANSI_C__ */
  1667. X
  1668. X/* ^DESCRIPTION:
  1669. X**    Manpage print on standard output, a Unix manual template for the
  1670. X**    given command. The NAME, SYNOPSIS, and OPTIONS sections are filled
  1671. X**    in and the DESCRIPTION section is partially filled in with any
  1672. X**    known command-description. The FILES, SEE ALSO, DIAGNOSTICS, CAVEATS,
  1673. X**    BUGS, AUTHOR, and HISTORY section titles are provided but the body
  1674. X**    of each section must be composed by the documentor.
  1675. X**
  1676. X** ^REQUIREMENTS:
  1677. X**    Argd should be a valid command-line descriptor array.
  1678. X**
  1679. X** ^SIDE-EFFECTS:
  1680. X**    Prints on standard-output.
  1681. X**
  1682. X** ^RETURN-VALUE:
  1683. X**    None.
  1684. X**
  1685. X** ^ALGORITHM:
  1686. X**    - print .TH setting followed by NAME section.
  1687. X**    - cycle through each argument and print is syntax for the SYNOPSIS.
  1688. X**    - print the description (if it exists).
  1689. X**    - cycle through each argument again and print its syntax and description
  1690. X**      for the OPTIONS section.
  1691. X**    - print just the headings for the remaining sections.
  1692. X***^^**********************************************************************/
  1693. X#ifdef __ANSI_C__
  1694. X   void manpage( const ARGDESC *argd )
  1695. X#endif
  1696. X{
  1697. X   register CONST ARGDESC *ad, *args, *cmd;
  1698. X   argName_t  name;
  1699. X   CONST char *program, *purpose, *description;
  1700. X   int   len, maxlen, positionals, namelen, programlen, purposelen;
  1701. X
  1702. X      /* allow null argument descriptor */
  1703. X   if ( !argd )  return;
  1704. X
  1705. X   if ( !CMD_isINIT(argd) )   init_args( (ARGDESC *)argd );
  1706. X   cmd = argd;
  1707. X
  1708. X   name[0] = 0;
  1709. X   namelen = 0;
  1710. X   if ( cmd_name(cmd) ) {
  1711. X      (VOID) strcpy( name, cmd_name(cmd) );
  1712. X      if ( !BTEST(cmd_state(cmd), ps_USERNAME|ps_FREENAME) ) {
  1713. X         namelen = get_argpfx( name );
  1714. X         name[namelen] = 0;
  1715. X      }
  1716. X      else {
  1717. X         namelen = strlen( cmd_name(cmd) );
  1718. X      }
  1719. X   }
  1720. X
  1721. X   program = 0;
  1722. X   programlen = 0;
  1723. X   if ( cmd_name(cmd) ) {
  1724. X      program = cmd_name(cmd);
  1725. X      programlen = namelen;
  1726. X   }
  1727. X   else if ( cmd_argv0(cmd) ) {
  1728. X      program = cmd_argv0(cmd);
  1729. X      programlen = strlen(program);
  1730. X   }
  1731. X
  1732. X   purpose = cmd_purpose(cmd);
  1733. X   if ( !BTEST(cmd_state(cmd), ps_USERPURPOSE|ps_FREEPURPOSE) && purpose ) {
  1734. X      purpose = get_argdesc(purpose, &purposelen);
  1735. X   }
  1736. X   else {
  1737. X     purposelen = strlen(VAL(purpose));
  1738. X   }
  1739. X   description = cmd_description(cmd);
  1740. X
  1741. X   printf(".\\\"---------- TO PRINT, USE: {n,t}roff -man file ----------\n");
  1742. X   printf(".if n .po 1\n");
  1743. X   printf(".if n .ll 78\n");
  1744. X
  1745. X   COMMENT;
  1746. X#ifdef SVR4
  1747. X   TH( name, namelen, 1 );
  1748. X#else
  1749. X   TH( strupr(name), namelen, 1 );
  1750. X#endif
  1751. X
  1752. X   COMMENT;
  1753. X   SH( "NAME" );
  1754. X   printf( "%s \\- %.*s\n", VAL(program), purposelen, VAL(purpose) );
  1755. X
  1756. X   COMMENT;
  1757. X   SH( "SYNOPSIS" );
  1758. X
  1759. X   len = strlen( program ) + 1;
  1760. X#ifdef SVR4
  1761. X   sprintf( name, "\\f4%.*s\\fP", programlen, program );
  1762. X#else
  1763. X   sprintf( name, "\\fB%.*s\\fP", programlen, program );
  1764. X#endif
  1765. X   TP( len, name );
  1766. X
  1767. X   maxlen = 0;
  1768. X   for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
  1769. X     for ( args = argd ; args ; args = cmd_defargs(args) ) {
  1770. X        for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
  1771. X           argName_t  buf;
  1772. X
  1773. X              /* don't display hidden arguments */
  1774. X           if ( ARG_isHIDDEN(ad) )  continue;
  1775. X           if ( !positionals  &&  ARG_isPOSITIONAL(ad) )  continue;
  1776. X           if ( positionals  &&  !ARG_isPOSITIONAL(ad) )  continue;
  1777. X
  1778. X           len = fmtarg( ad, buf );
  1779. X           if ( len > maxlen )   maxlen = len;
  1780. X
  1781. X           if ( ARG_isREQUIRED(ad) ) {
  1782. X               printf( "%s\n", buf );
  1783. X           }
  1784. X           else {
  1785. X               printf( "[%s]\n", buf );
  1786. X           }
  1787. X        }/*for each ad */
  1788. X     }/* for each argd */
  1789. X   }/* for each parm-type */
  1790. X
  1791. X   COMMENT;
  1792. X   SH( "DESCRIPTION" );
  1793. X   PP;
  1794. X   indent_para(stdout, MAXCOLS, 0, "", 0, VAL(description), 0);
  1795. X
  1796. X   COMMENT;
  1797. X   SH( "OPTIONS" );
  1798. X
  1799. X   for ( positionals = 0 ; positionals < 2 ; positionals++ ) {
  1800. X      for ( args = argd ; args ; args = cmd_defargs(args) ) {
  1801. X         for ( ad = ARG_FIRST(args) ; !ARG_isEND(ad) ; ARG_ADVANCE(ad) ) {
  1802. X            argName_t  buf;
  1803. X            char  *desc;
  1804. X            int  desclen;
  1805. X
  1806. X               /* don't display hidden arguments */
  1807. X            if ( ARG_isHIDDEN(ad) )  continue;
  1808. X            if ( !positionals  &&  ARG_isPOSITIONAL(ad) )  continue;
  1809. X            if ( positionals  &&  !ARG_isPOSITIONAL(ad) )  continue;
  1810. X
  1811. X            (VOID) fmtarg( ad, buf );
  1812. X            TP( maxlen + 2, buf );
  1813. X            desc = get_argdesc(arg_description(ad), &desclen);
  1814. X            indent_para(stdout, MAXCOLS, 0, "", 0, desc, desclen);
  1815. X         }/*for each ad */
  1816. X      }/* for each argd */
  1817. X   }/* for each parm-type */
  1818. X
  1819. X   COMMENT;
  1820. X   SH( "FILES" );
  1821. X   PP;
  1822. X
  1823. X   COMMENT;
  1824. X   SH( "ENVIRONMENT" );
  1825. X   PP;
  1826. X
  1827. X   COMMENT;
  1828. X   SH( "SEE ALSO" );
  1829. X   PP;
  1830. X
  1831. X   COMMENT;
  1832. X   SH( "DIAGNOSTICS" );
  1833. X   PP;
  1834. X
  1835. X   COMMENT;
  1836. X   SH( "CAVEATS" );
  1837. X   PP;
  1838. X
  1839. X   COMMENT;
  1840. X   SH( "BUGS" );
  1841. X   PP;
  1842. X
  1843. X   COMMENT;
  1844. X   SH( "AUTHOR" );
  1845. X   PP;
  1846. X
  1847. X   COMMENT;
  1848. X   SH( "HISTORY" );
  1849. X   PP;
  1850. X}
  1851. END_OF_FILE
  1852. if test 8905 -ne `wc -c <'unix_man.c'`; then
  1853.     echo shar: \"'unix_man.c'\" unpacked with wrong size!
  1854. fi
  1855. # end of 'unix_man.c'
  1856. fi
  1857. if test -f 'useful.h' -a "${1}" != "-c" ; then 
  1858.   echo shar: Will not clobber existing file \"'useful.h'\"
  1859. else
  1860. echo shar: Extracting \"'useful.h'\" \(8507 characters\)
  1861. sed "s/^X//" >'useful.h' <<'END_OF_FILE'
  1862. X/*************************************************************************
  1863. X** ^FILE: useful.h - various definitions of general interest
  1864. X**
  1865. X** ^DESCRIPTION:
  1866. X**    This file #defines several macros that are either of very general
  1867. X**    use, or that assist in writing portable programs between various
  1868. X**    systems and/or compilers.
  1869. X**
  1870. X** ^HISTORY:
  1871. X**    --/--/--    Brad Appleton    <brad@ssd.csd.harris.com>    
  1872. X**    - Added OS specific #defines for unix, SYSV, BSD, etc ...
  1873. X**    - Added structured block comments
  1874. X**    - Added varargs/stdarg macros
  1875. X**    - Added BSET, BCLEAR, BTEST macros for handling bitmasks
  1876. X**    - #defined EXTERN to be extern "C" for C++
  1877. X**    - Added #defines for STDIN, STDOUT, and STDERR file descriptors
  1878. X**
  1879. X**    --/--/--    Peter da Silva    <peter@ferranti.com>    
  1880. X**
  1881. X**    --/--/--    Eric P. Allman    <eric@Berkeley.EDU>     Created
  1882. X***^^**********************************************************************/
  1883. X
  1884. X/* $Header: useful.h,v 2.0 89/12/24 00:56:33 eric Exp $ */
  1885. X
  1886. X#ifndef _USEFUL_H_
  1887. X#define _USEFUL_H_
  1888. X
  1889. X#if (defined(_unix) || defined(__unix) || defined(_unix_) || defined(__unix__))
  1890. X# ifndef unix
  1891. X#   define unix
  1892. X# endif
  1893. X#endif /* _unix */
  1894. X
  1895. X#if (defined(_UNIX) || defined(__UNIX) || defined(_UNIX_) || defined(__UNIX__))
  1896. X# ifndef unix
  1897. X#   define unix
  1898. X# endif
  1899. X#endif /* _UNIX */
  1900. X
  1901. X   /* give a stab at the dual Unix universe dilemma (UCB vs AT&T) */
  1902. X#ifdef unix
  1903. X# if ( defined(_BSD) && !defined(BSD) )
  1904. X#  define BSD
  1905. X# endif
  1906. X# if ( defined(_SYSV) && !defined(SYSV) )
  1907. X#  define SYSV
  1908. X# endif
  1909. X
  1910. X# ifndef BSD
  1911. X#  ifdef sun
  1912. X#   define BSD
  1913. X#  endif
  1914. X#  if ( defined(apollo) || defined(aegis) )
  1915. X#   define BSD
  1916. X#  endif
  1917. X#  if ( defined(_CX_UX) && defined(ucb_universe) )
  1918. X#   define BSD
  1919. X#  endif
  1920. X#  if ( defined(VAX_BSD) || defined(ULTRIX) || defined(ultrix) )
  1921. X#   define BSD
  1922. X#  endif
  1923. X#  if ( defined(DYNIX) || defined(dynix) )
  1924. X#   define BSD
  1925. X#  endif
  1926. X#  if ( defined(UTX) || defined(utx) )
  1927. X#   define BSD
  1928. X#  endif
  1929. X# endif /* !BSD */
  1930. X
  1931. X# ifndef SYSV
  1932. X#  ifdef mips
  1933. X#   define SYSV
  1934. X#  endif
  1935. X#  ifdef DGUX
  1936. X#   define SYSV
  1937. X#  endif
  1938. X#  if ( defined(_CX_UX) && defined(att_universe) )
  1939. X#   define SYSV
  1940. X#  endif
  1941. X#  if ( defined(hpux) || defined(HPUX) )
  1942. X#   define SYSV
  1943. X#  endif
  1944. X#  if ( defined(irix) || defined(IRIX) )
  1945. X#   define SYSV
  1946. X#  endif
  1947. X#  if ( defined(aix) || defined(AIX) )
  1948. X#   define SYSV
  1949. X#  endif
  1950. X# endif /* !SYSV */
  1951. X#endif /* unix */
  1952. X
  1953. X#ifndef MSDOS
  1954. X# if (defined(_MSDOS_)||defined(__MSDOS__)||defined(_MSDOS)||defined(__MSDOS))
  1955. X#  define MSDOS
  1956. X# endif
  1957. X#endif
  1958. X
  1959. X#ifndef OS2
  1960. X# if ( defined(_OS2_) || defined(__OS2__) || defined(_OS2) || defined(__OS2) )
  1961. X#  define OS2
  1962. X# endif
  1963. X#endif
  1964. X
  1965. X#ifndef AmigaDOS
  1966. X# if ( defined(AMIGA) || defined(MANX) || defined(AZTEC) )
  1967. X#   define AmigaDOS
  1968. X# endif
  1969. X#endif /* AmigaDOS */
  1970. X
  1971. X
  1972. X#ifdef __STDC__
  1973. X# include <stddef.h>
  1974. X# include <stdlib.h>
  1975. X#endif
  1976. X
  1977. X#if ( !defined(__STDC__) && defined(vms) )
  1978. X# include <stdlib.h>
  1979. X#endif
  1980. X
  1981. X#ifndef FILE
  1982. X# include <stdio.h>
  1983. X#endif
  1984. X
  1985. X#ifndef STDIN
  1986. X# define STDIN   0
  1987. X# define STDOUT  1
  1988. X# define STDERR  2
  1989. X#endif
  1990. X
  1991. X   /* macros to portably convert character case */
  1992. X#define TOUPPER(c)  ( islower(c) ) ? toupper(c) : (c)
  1993. X#define TOLOWER(c)  ( isupper(c) ) ? tolower(c) : (c)
  1994. X
  1995. X   /* give a stab at the multiple-language dilemma */
  1996. X#ifdef __STDC__
  1997. X#  define ARGS(x)        x
  1998. X#  define NOARGS        ( void )
  1999. X#  define __ANSI_C__
  2000. X#else
  2001. X#  if defined(c_plusplus) || defined(__cplusplus)
  2002. X#    define ARGS(x)        x
  2003. X#    define NOARGS        ()
  2004. X#    define __ANSI_C__
  2005. X#  else
  2006. X#    define ARGS(x)        ()
  2007. X#    define NOARGS        ()
  2008. X#  endif
  2009. X#endif
  2010. X
  2011. X   /* give a stab at the variable arguments dilemma  --BDA */
  2012. X#ifdef __STDC__
  2013. X#  ifndef va_arg
  2014. X#    include <stdarg.h>
  2015. X#  endif
  2016. X#  define  VA_START(ap,last)  va_start(ap, last)
  2017. X#  define  VA_ARG(ap,type)    va_arg(ap, type)
  2018. X#  define  VA_END(ap)         va_end(ap)
  2019. X#else
  2020. X#  ifndef va_arg
  2021. X#    include  <varargs.h>
  2022. X#  endif
  2023. X#  define  VA_START(ap,last)  va_start(ap)
  2024. X#  define  VA_ARG(ap,type)    va_arg(ap, type)
  2025. X#  define  VA_END(ap)         va_end(ap)
  2026. X#endif
  2027. X
  2028. X#ifndef VOID
  2029. X#  if ( defined(__ANSI_C__)  ||  !defined(NOVOID) )
  2030. X#    define VOID        void
  2031. X#  else
  2032. X#    define VOID        int
  2033. X#  endif
  2034. X#endif
  2035. X
  2036. X#ifndef TRUE
  2037. X#  define TRUE        1
  2038. X#  define FALSE        0
  2039. X#endif
  2040. X
  2041. X#ifndef STATIC
  2042. X#  ifndef NODEBUG
  2043. X#    define STATIC
  2044. X#  else
  2045. X#    define STATIC        static
  2046. X#  endif
  2047. X#endif
  2048. X
  2049. X#ifndef EXTERN
  2050. X#  if defined(c_plusplus) || defined(__cplusplus)
  2051. X#    define EXTERN        extern "C"
  2052. X#  else
  2053. X#    define EXTERN        extern
  2054. X#  endif
  2055. X#endif
  2056. X
  2057. X#ifndef CONST
  2058. X#  ifdef __ANSI_C__
  2059. X#    define CONST        const
  2060. X#  else
  2061. X#    define CONST
  2062. X#  endif
  2063. X#endif
  2064. X
  2065. X#ifndef NULL
  2066. X#  define NULL        0
  2067. X#endif
  2068. X
  2069. X#ifndef CHARNULL
  2070. X#  define CHARNULL    ((char *) NULL)
  2071. X#endif
  2072. X
  2073. X#ifndef FILENULL
  2074. X#  define FILENULL    ((FILE *) NULL)
  2075. X#endif
  2076. X
  2077. X#if ( defined(__ANSI_C__)  ||  defined(vms) )
  2078. X   typedef   void *ARBPTR;
  2079. X#else
  2080. X   typedef   char *ARBPTR;
  2081. X#endif
  2082. X
  2083. X#define __        (ARBPTR)
  2084. X#define ARBNULL        (__ NULL)
  2085. X
  2086. X#ifndef BOOL
  2087. X   typedef   char   BOOL;
  2088. X#endif
  2089. X
  2090. X#ifdef lint
  2091. X#  define VERSIONID(v)
  2092. X#else
  2093. X#  define VERSIONID(v)    static char _Version[] = v
  2094. X#endif
  2095. X
  2096. X   /* keep BITSET for compatibilty
  2097. X   ** but use BSET, BCLEAR, etc... instead   --BDA
  2098. X   */
  2099. X#define BITSET(bstr,mask)    ( ((bstr) & (mask)) != 0 )
  2100. X
  2101. X#define BTEST(bstr,mask)    ( ((bstr) & (mask)) != 0 )
  2102. X#define BSET(bstr,mask)     (bstr) |= (mask)
  2103. X#define BCLEAR(bstr,mask)   (bstr) &= ~(mask)
  2104. X
  2105. X#ifndef __STRING_H
  2106. X# define __STRING_H
  2107. X   EXTERN  char  *strcat    ARGS(( char *, const char * ));
  2108. X   EXTERN  char  *strncat   ARGS(( char *, const char *, int ));
  2109. X   EXTERN  int    strcmp    ARGS(( const char *, const char * ));
  2110. X   EXTERN  int    strncmp   ARGS(( const char *, const char *, int ));
  2111. X   EXTERN  char  *strcpy    ARGS(( char *, const char * ));
  2112. X   EXTERN  char  *strncpy   ARGS(( char *, const char *, int ));
  2113. X   EXTERN  int    strlen    ARGS(( const char * ));
  2114. X   
  2115. X# ifndef BSD
  2116. X#  define index(s,c)   strchr(s,c)
  2117. X#  define rindex(s,c)  strrchr(s,c)
  2118. X   EXTERN  char  *strchr    ARGS(( const char *, int ));
  2119. X   EXTERN  char  *strrchr   ARGS(( const char *, int ));
  2120. X   EXTERN  char  *strpbrk   ARGS(( const char *, const char * ));
  2121. X   EXTERN  int    strspn    ARGS(( const char *, const char * ));
  2122. X   EXTERN  int    strcspn   ARGS(( const char *, const char * ));
  2123. X   EXTERN  char  *strtok    ARGS(( char *, const char * ));
  2124. X   
  2125. X# else
  2126. X#  define strchr(s,c)   index(s,c)
  2127. X#  define strrchr(s,c)  rindex(s,c)
  2128. X   EXTERN  char  *index     ARGS(( const char *, int ));
  2129. X   EXTERN  char  *rindex    ARGS(( const char *, int ));
  2130. X# endif /* !BSD */
  2131. X   
  2132. X# ifndef BSD
  2133. X#  define bcmp(b1,b2,n)   memcmp(b1,b2,n)
  2134. X#  define bcopy(b1,b2,n)  memcpy(b2,b1,n)
  2135. X#  define bzero(b,n)      memset(b,'\0',n)
  2136. X#  ifndef __MEMORY_H
  2137. X#    define __MEMORY_H
  2138. X   EXTERN  ARBPTR  memccpy   ARGS(( ARBPTR, const ARBPTR, int, int ));
  2139. X   EXTERN  ARBPTR  memchr    ARGS(( ARBPTR, int, int ));
  2140. X   EXTERN  int     memcmp    ARGS(( const ARBPTR, const ARBPTR, int ));
  2141. X   EXTERN  ARBPTR  memcpy    ARGS(( ARBPTR, const ARBPTR, int ));
  2142. X   EXTERN  ARBPTR  memmove   ARGS(( ARBPTR, const ARBPTR, int ));
  2143. X   EXTERN  ARBPTR  memset    ARGS(( ARBPTR, int, int ));
  2144. X#  endif  /* __MEMORY_H */
  2145. X   
  2146. X# else
  2147. X#  define memcmp(b1,b2,n)  bcmp(b1,b2,n)
  2148. X#  define memcpy(b1,b2,n)  bcopy(b2,b1,n)
  2149. X#  ifndef __BSTRING_H
  2150. X#    define __BSTRING_H
  2151. X   EXTERN  VOID   bcopy     ARGS(( const ARBPTR, ARBPTR, int ));
  2152. X   EXTERN  int    bcmp      ARGS(( const ARBPTR, const ARBPTR, int ));
  2153. X   EXTERN  VOID   bzero     ARGS(( ARBPTR, int ));
  2154. X   EXTERN  int    ffs       ARGS(( int ));
  2155. X#  endif  /* __BSTRING_H */
  2156. X# endif /* !BSD */
  2157. X#endif /* __STRING_H */
  2158. X
  2159. X#if ( !defined(__ANSI_C__)  &&  !defined(_SIZE_T_DEFINED) )
  2160. X# if (defined(sun) && defined(BSD))
  2161. X#  include <sys/types.h>
  2162. X#  if (!defined (__sys_stdtypes_h) && !defined(_TYPES_))
  2163. X    /* size_t is also defined in <sys/stdtypes.h> in SunOS 4.1
  2164. X    ** and int <types.h> in SunOS 4.0.3
  2165. X    */
  2166. X    typedef int size_t;
  2167. X#  endif
  2168. X#  define _SIZE_T_DEFINED 1
  2169. X# endif /* sun */
  2170. X# if (defined(vms) && defined(__STDDEF_LOADED))
  2171. X#  define _SIZE_T_DEFINED 1
  2172. X# endif /* vms */
  2173. X# ifndef _SIZE_T_DEFINED
  2174. X   typedef unsigned int size_t;
  2175. X#  define _SIZE_T_DEFINED 1
  2176. X# endif  /* !_SIZE_T_DEFINED */
  2177. X#endif
  2178. X
  2179. X#if ( !defined(__malloc_h) && !defined(__MALLOC_H) && !defined(vms) )
  2180. X# include <malloc.h>
  2181. X#else
  2182. X  EXTERN  ARBPTR  malloc   ARGS(( size_t ));
  2183. X  EXTERN  ARBPTR  realloc  ARGS(( ARBPTR, size_t ));
  2184. X  EXTERN  VOID    free     ARGS(( ARBPTR ));
  2185. X#endif /*__malloc_h*/
  2186. X
  2187. XEXTERN  ARBPTR  ckalloc  ARGS(( size_t ));
  2188. XEXTERN  VOID    exit     ARGS(( int ));
  2189. X
  2190. X#define MAXINPUTLINE    200        /* maximum string input line */
  2191. X#define MAXWORDLEN    100        /* maximum word (token) length */
  2192. X
  2193. X#endif /* _USEFUL_H_ */
  2194. END_OF_FILE
  2195. if test 8507 -ne `wc -c <'useful.h'`; then
  2196.     echo shar: \"'useful.h'\" unpacked with wrong size!
  2197. fi
  2198. # end of 'useful.h'
  2199. fi
  2200. echo shar: End of archive 4 \(of 10\).
  2201. cp /dev/null ark4isdone
  2202. MISSING=""
  2203. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  2204.     if test ! -f ark${I}isdone ; then
  2205.     MISSING="${MISSING} ${I}"
  2206.     fi
  2207. done
  2208. if test "${MISSING}" = "" ; then
  2209.     echo You have unpacked all 10 archives.
  2210.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2211. else
  2212.     echo You still need to unpack the following archives:
  2213.     echo "        " ${MISSING}
  2214. fi
  2215. ##  End of shell archive.
  2216. exit 0
  2217.  
  2218. exit 0 # Just in case...
  2219.