1 /****************************************************************************
3 ** Program: pipe-handler - an AmigaDOS handler for named pipes
5 ** Author: Ed Puckett qix@mit-oz
7 ** Copyright 1987 by EpAc Software. All Rights Reserved.
9 ** History: 05-Jan-87 Original Version (1.0)
10 ** 07-Feb-87 Added conditional compilation for autoname.
12 #include <string.h> /* For strcpy */
14 #include <libraries/dos.h>
15 #include <libraries/dosextens.h>
16 #include <libraries/filehandler.h>
17 #include <exec/exec.h>
19 #include "pipelists.h"
22 #include "pipecreate.h"
23 #include "pipesched.h"
24 #include "pipe-handler.h"
28 /*---------------------------------------------------------------------------
31 ** This module contains functions related to the parsing of the pipe names.
35 ** int ParsePipeName (Bname, nmp, sizep, tapnmp)
36 ** void BSTRtoCstr (BSTRp, str, maxsize)
37 ** void CstrtoBSTR (str, BSTRp, maxsize)
38 ** void CstrtoFIB (str, BSTRp, maxsize)
39 ** int inrange (x, lower, upper)
41 ** char *findchar (str, ch)
42 ** void l_strcpy (to, from)
43 ** char *strdiff (str1, str2)
44 ** char *get_autoname (newflag) (if AUTONAME or AUTONAME_STAR is true)
46 ** Macros (in pipename.h)
47 ** ----------------------
52 ** int ParseNum (str, nump)
55 static int ParseNum ( char *str
, ULONG
*nump
);
59 /*---------------------------------------------------------------------------
60 ** ParsePipeName() parses the string "Bname" into three parts: a pipe name,
61 ** a size specification and a tap name. (Bname must be the byte address of a
62 ** BSTR, i.e., a string whose first byte is its length.) The three parts are
63 ** separated by the character PIPE_SPEC_CHAR (defined in pipename.h).
64 ** Assuming that PIPE_SPEC_CHAR is '/', and that '[]' are metacharacters
65 ** which enclose optional parts, the syntax for Bname is [D:][p][/n][/[t]].
66 ** Here, "D" represents a device name, "p" represents a pipe name,
67 ** "n" represents a number and "t" represents a tap name.
68 ** ParsePipeName() returns nonzero iff "Bname" conforms to the syntax
69 ** and the following restrictions.
70 ** "D:" represents a device name. If it occurs, it is ignored. Notice
71 ** that tap names which contain a ":" force a device name to be specified for
72 ** the pipe. Otherwise, everything up to and including the ":" in the tap
73 ** name will be ignored.
74 ** *nmp returns pointing to a copy of "p", even if it is empty. Default
75 ** pipe names are handled by calling get_autoname(). (This is done by
76 ** OpenPipe() if *nmp returns empty.)
77 ** "n" must begin with a digit. If "n" begins with "0x", it is parsed
78 ** as a hexadecimal number. If it begins with "0" but not "0x", it is parsed
79 ** as an octal number. Otherwise, it is parsed as a decimal number. If the
80 ** size specifier ("/t" above) is not given, *sizep is set to DEFAULT_PIPELEN.
81 ** If the compile-time flag CON_TAP_ONLY is set, "t" may only be a "CON:"
82 ** file specifier, such as "CON:10/10/400/120/TapWindow". If CON_TAP_ONLY is
83 ** not set, string is accepted. If "t" is empty (but the PIPE_SPEC_CHAR was
84 ** given), then a defualt tap name is formed by appending "p" to
85 ** DEFAULT_TAPNAME_PREFIX. If the tap name specifier ("/[t]" above) is not
86 ** given, *tapnmp is set to NULL.
89 static char default_tapname_prefix
[] = DEFAULT_TAPNAME_PREFIX
;
90 static char namebuf
[sizeof (default_tapname_prefix
) + PIPENAMELEN
];
92 int ParsePipeName (Bname
, nmp
, sizep
, tapnmp
)
94 BYTE
*Bname
; /* reference to BSTR name sent to handler */
95 char **nmp
; /* reference to pipe name pointer */
96 ULONG
*sizep
; /* size longword pointer */
97 char **tapnmp
; /* reference to tap name pointer, returns NULL if none */
103 l_strcpy (namebuf
, default_tapname_prefix
);
105 *nmp
= namebuf
+ (sizeof (default_tapname_prefix
) - 1);
106 *sizep
= DEFAULT_PIPELEN
;
109 BSTRtoCstr (Bname
, *nmp
, PIPENAMELEN
);
111 if (*(cp
= findchar (*nmp
, ':')) == ':')
112 l_strcpy (*nmp
, ++cp
); /* get rid of "devname:" prefix */
114 if ( *(cp
= findchar (*nmp
, PIPE_SPEC_CHAR
)) ) /* true if not '\0' */
115 { *(cp
++)= '\0'; /* terminate pipe name */
118 { if ( (! ParseNum (cp
, sizep
)) || (*sizep
<= 0) )
121 if ( *(cp
= findchar (cp
, PIPE_SPEC_CHAR
)) == '\0' )
122 return TRUE
; /* no tap name, but successful anyway */
124 ++cp
; /* skip separator */
127 if ( *(*tapnmp
= cp
) == '\0' ) /* first character of tap name */
128 *tapnmp
= namebuf
; /* use default prefix prepended to pipe name */
131 { if ( *(strdiff ("CON:", *tapnmp
)) ) /* true if not '\0' */
132 return FALSE
; /* only CON: . . . allowed */
134 #endif /* CON_TAP_ONLY */
142 /*---------------------------------------------------------------------------
143 ** BSTRtoCstr() converts the BSTR pointed to by "BSTRp" (a byte address) to
144 ** a null-terminated string, storing the result in the locations pointed to
145 ** by "str". At most "maxsize" bytes will be stored.
148 void BSTRtoCstr (BSTRp
, str
, maxsize
)
150 register BYTE
*BSTRp
;
155 #ifdef AROS_FAST_BSTR
156 strncpy(str
, BSTRp
, maxsize
);
163 if ((limit
= *(BSTRp
++)) > ((int) maxsize
- 1)) /* leave room for '\0' */
164 limit
= (int) maxsize
- 1;
166 for (i
= 0; i
< limit
; ++i
)
167 *(str
++)= *(BSTRp
++);
175 /*---------------------------------------------------------------------------
176 ** CstrtoBSTR() converts the null-terminated string pointed to by "str" to
177 ** a BSTR located at the byte address "BSTRp". At most "maxsize" bytes will
181 void CstrtoBSTR (str
, BSTRp
, maxsize
)
188 #ifdef AROS_FAST_BSTR
189 strncpy(BSTRp
, str
, maxsize
);
190 BSTRp
[maxsize
-1] = 0;
193 register int i
, limit
;
199 for (i
= 0; i
< limit
; ++i
)
200 if ( (*(bp
++)= *(str
++)) == '\0' )
207 /*---------------------------------------------------------------------------
208 ** CstrtoFIB() converts the null-terminated string pointed to by "str" to
209 ** a FIB fib_FileName or fib_Comment located at the byte address "BSTRp".
210 ** At most "maxsize" bytes will be stored.
213 void CstrtoFIB (str
, BSTRp
, maxsize
)
221 register int i
, limit
;
227 for (i
= 0; i
< limit
; ++i
)
228 if ( (*(bp
++)= *(str
++)) == '\0' )
237 /*---------------------------------------------------------------------------
238 ** inrange() returns nonzero iff x is in the range [lower, upper].
239 ** uppercase() returns the uppercase version of the ASCII character sent.
240 ** These are not implemented as macros to avoid hard-to-find bugs like
241 ** uppercase(c++), where the side-effect occurs more than once.
244 int inrange (x
, lower
, upper
)
250 { return ((x
>= lower
) && (x
<= upper
));
258 { return (char) (inrange (c
, 'a', 'z') ? (c
+ ('A' - 'a')) : c
);
263 /*---------------------------------------------------------------------------
264 ** The null-terminated string "str" is scanned for the character "ch". If
265 ** found, a pointer to its first occurrence in "str" is returned. Otherwise,
266 ** a pointer to the terminating '\0' in "str" is returned.
269 char *findchar (str
, ch
)
274 { while ((*str
!= '\0') && (*str
!= ch
))
277 return str
; /* return position of ch, or end if not found */
282 /*---------------------------------------------------------------------------
283 ** This is just like strcpy(). Its is defined here to avoid including other
287 void l_strcpy (to
, from
)
297 if (*(to
++)= *(from
++))
304 /*---------------------------------------------------------------------------
305 ** strdiff() returns a pointer to the first difference in the two null-
306 ** terminated strings "str1" and "str2". If no differnce is found, or if
307 ** "str1" is shorter than "str2", then a pointer to '\0' is returned.
308 ** The returned pointer is to a character in "str1".
311 char *strdiff (str1
, str2
)
316 { while ( *str1
&& (uppercase (*str1
) == uppercase (*str2
)) )
321 return str1
; /* return position of first difference, or end of str1 */
326 /*---------------------------------------------------------------------------
327 ** get_autoname() returns a pointer to "autoname". If "newflag" is nonzero,
328 ** autoname is first updated so that it does not conflict with any existing
329 ** pipe name. This is done by looking for a block of ASCII digits in
330 ** "autoname", and incrementing their effective value. "autoname" MUST
331 ** contain such a block of digits.
334 #if AUTONAME || AUTONAME_STAR
336 static char autoname
[] = AUTONAME_INIT
;
338 char *get_autoname (newflag
)
343 PIPEDATA
*FindPipe();
346 if (newflag
) /* then create a new unique pipe name */
347 { cp
= findchar (autoname
, '\0');
349 while (! isnumeral (*cp
)) /* find last numeral */
353 { ++(*cp
); /* "increment" name */
355 for (cpc
= cp
; (! isnumeral (*cpc
)); ) /* ripple carry */
358 if (! isnumeral (*cpc
))
359 break; /* no more digits */
364 while (FindPipe (autoname
) != NULL
); /* repeat until name is unique */
371 #endif /* AUTONAME || AUTONAME_STAR */
375 /*---------------------------------------------------------------------------
376 ** ParseNum() parses the null-terminated string pointed to by "str" into a
377 ** number, and stores its value in *nump. ParseNum() returns nonzero iff
378 ** successful. Both '\0' and PIPE_SPEC_CHAR are acceptable terminators for
380 ** If the number begins with "0x", it is interpreted as hexadecimal.
381 ** If it begins with "0" but not "0x", it is interpreted as octal.
382 ** Otherwise, it is interpreted as decimal.
385 static int ParseNum (str
, nump
)
391 char *digits
= "0123456789ABCDEF";
395 if ((*str
== '0') && (uppercase (*(str
+ 1)) == 'X'))
399 else if (*str
== '0')
404 for (*nump
= 0; TRUE
; ++str
)
405 { value
= findchar (digits
, uppercase (*str
)) - digits
;
407 if (! inrange (value
, 0, (radix
- 1)))
410 if (*nump
> ((MAX_PIPELEN
- value
) / radix
))
418 return ( (*str
== PIPE_SPEC_CHAR
) || (*str
== '\0') );