add placeholder for classic magicmenu pull-down-on-titlebar behaviour when using...
[AROS.git] / workbench / fs / pipe / pipename.c
blobdf7346e8ceb2e7f139af901f0dfdbd8dad98d91b
1 /****************************************************************************
2 ** File: pipename.c
3 ** Program: pipe-handler - an AmigaDOS handler for named pipes
4 ** Version: 1.1
5 ** Author: Ed Puckett qix@mit-oz
6 **
7 ** Copyright 1987 by EpAc Software. All Rights Reserved.
8 **
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"
20 #include "pipename.h"
21 #include "pipebuf.h"
22 #include "pipecreate.h"
23 #include "pipesched.h"
24 #include "pipe-handler.h"
28 /*---------------------------------------------------------------------------
29 ** pipename.c
30 ** ----------
31 ** This module contains functions related to the parsing of the pipe names.
33 ** Visible Functions
34 ** -----------------
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)
40 ** char uppercase (c)
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 ** ----------------------
48 ** isnumeral (c)
50 ** Local Functions
51 ** ---------------
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 */
99 { char *cp;
100 int ParseNum();
103 l_strcpy (namebuf, default_tapname_prefix);
105 *nmp= namebuf + (sizeof (default_tapname_prefix) - 1);
106 *sizep= DEFAULT_PIPELEN;
107 *tapnmp= NULL;
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 */
117 if (isnumeral (*cp))
118 { if ( (! ParseNum (cp, sizep)) || (*sizep <= 0) )
119 return FALSE;
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 */
129 #if CON_TAP_ONLY
130 else
131 { if ( *(strdiff ("CON:", *tapnmp)) ) /* true if not '\0' */
132 return FALSE; /* only CON: . . . allowed */
134 #endif /* CON_TAP_ONLY */
137 return TRUE;
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;
151 register char *str;
152 unsigned maxsize;
155 #ifdef AROS_FAST_BSTR
156 strncpy(str, BSTRp, maxsize);
157 str[maxsize-1] = 0;
158 #else
159 register int i;
160 register int limit;
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++);
169 *str= '\0';
170 #endif
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
178 ** be stored.
181 void CstrtoBSTR (str, BSTRp, maxsize)
183 register char *str;
184 BYTE *BSTRp;
185 unsigned maxsize;
188 #ifdef AROS_FAST_BSTR
189 strncpy(BSTRp, str, maxsize);
190 BSTRp[maxsize-1] = 0;
191 #else
192 register char *bp;
193 register int i, limit;
195 bp= BSTRp + 1;
197 limit= maxsize - 1;
199 for (i= 0; i < limit; ++i)
200 if ( (*(bp++)= *(str++)) == '\0' )
201 break;
203 BSTRp[0]= i;
204 #endif
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)
215 register char *str;
216 BYTE *BSTRp;
217 unsigned maxsize;
220 register char *bp;
221 register int i, limit;
223 bp= BSTRp + 1;
225 limit= maxsize - 1;
227 for (i= 0; i < limit; ++i)
228 if ( (*(bp++)= *(str++)) == '\0' )
229 break;
231 BSTRp[0]= i;
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)
246 register int x;
247 register int lower;
248 register int upper;
250 { return ((x >= lower) && (x <= upper));
254 char uppercase (c)
256 register char c;
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)
271 register char *str;
272 register char ch;
274 { while ((*str != '\0') && (*str != ch))
275 ++str;
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
284 ** libraries.
287 void l_strcpy (to, from)
289 register char *to;
290 register char *from;
293 #ifdef __AROS__
294 strcpy(to, from);
295 #else
296 STRCPYLOOP:
297 if (*(to++)= *(from++))
298 goto STRCPYLOOP;
299 #endif
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)
313 register char *str1;
314 register char *str2;
316 { while ( *str1 && (uppercase (*str1) == uppercase (*str2)) )
317 { ++str1;
318 ++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)
340 BYTE newflag;
342 { char *cp, *cpc;
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 */
350 --cp;
353 { ++(*cp); /* "increment" name */
355 for (cpc= cp; (! isnumeral (*cpc)); ) /* ripple carry */
356 { *(cpc--)= '0';
358 if (! isnumeral (*cpc))
359 break; /* no more digits */
361 ++(*cpc);
364 while (FindPipe (autoname) != NULL); /* repeat until name is unique */
368 return autoname;
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
379 ** the number.
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)
387 char *str;
388 ULONG *nump;
390 { int radix = 10;
391 char *digits = "0123456789ABCDEF";
392 LONG value;
395 if ((*str == '0') && (uppercase (*(str + 1)) == 'X'))
396 { radix= 16;
397 str += 2;
399 else if (*str == '0')
400 { radix= 8;
401 ++str;
404 for (*nump= 0; TRUE; ++str)
405 { value= findchar (digits, uppercase (*str)) - digits;
407 if (! inrange (value, 0, (radix - 1)))
408 break;
410 if (*nump > ((MAX_PIPELEN - value) / radix))
411 return FALSE;
413 *nump *= radix;
414 *nump += value;
418 return ( (*str == PIPE_SPEC_CHAR) || (*str == '\0') );