xref: /onnv-gate/usr/src/grub/grub-0.97/netboot/misc.c (revision 8044:b3af80bbf173)
1*8044SWilliam.Kucharski@Sun.COM /*
2*8044SWilliam.Kucharski@Sun.COM  *  GRUB  --  GRand Unified Bootloader
3*8044SWilliam.Kucharski@Sun.COM  *  Copyright (C) 2000,2001,2002  Free Software Foundation, Inc.
4*8044SWilliam.Kucharski@Sun.COM  *
5*8044SWilliam.Kucharski@Sun.COM  *  This program is free software; you can redistribute it and/or modify
6*8044SWilliam.Kucharski@Sun.COM  *  it under the terms of the GNU General Public License as published by
7*8044SWilliam.Kucharski@Sun.COM  *  the Free Software Foundation; either version 2 of the License, or
8*8044SWilliam.Kucharski@Sun.COM  *  (at your option) any later version.
9*8044SWilliam.Kucharski@Sun.COM  *
10*8044SWilliam.Kucharski@Sun.COM  *  This program is distributed in the hope that it will be useful,
11*8044SWilliam.Kucharski@Sun.COM  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12*8044SWilliam.Kucharski@Sun.COM  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*8044SWilliam.Kucharski@Sun.COM  *  GNU General Public License for more details.
14*8044SWilliam.Kucharski@Sun.COM  *
15*8044SWilliam.Kucharski@Sun.COM  *  You should have received a copy of the GNU General Public License
16*8044SWilliam.Kucharski@Sun.COM  *  along with this program; if not, write to the Free Software
17*8044SWilliam.Kucharski@Sun.COM  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18*8044SWilliam.Kucharski@Sun.COM  */
19*8044SWilliam.Kucharski@Sun.COM 
20*8044SWilliam.Kucharski@Sun.COM /* Based on "src/misc.c" in etherboot-5.0.5.  */
21*8044SWilliam.Kucharski@Sun.COM 
22*8044SWilliam.Kucharski@Sun.COM #include "grub.h"
23*8044SWilliam.Kucharski@Sun.COM #include "timer.h"
24*8044SWilliam.Kucharski@Sun.COM 
25*8044SWilliam.Kucharski@Sun.COM #include "nic.h"
26*8044SWilliam.Kucharski@Sun.COM 
27*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
28*8044SWilliam.Kucharski@Sun.COM RANDOM - compute a random number between 0 and 2147483647L or 2147483562?
29*8044SWilliam.Kucharski@Sun.COM **************************************************************************/
random(void)30*8044SWilliam.Kucharski@Sun.COM int32_t random(void)
31*8044SWilliam.Kucharski@Sun.COM {
32*8044SWilliam.Kucharski@Sun.COM 	static int32_t seed = 0;
33*8044SWilliam.Kucharski@Sun.COM 	int32_t q;
34*8044SWilliam.Kucharski@Sun.COM 	if (!seed) /* Initialize linear congruential generator */
35*8044SWilliam.Kucharski@Sun.COM 		seed = currticks() + *(int32_t *)&arptable[ARP_CLIENT].node
36*8044SWilliam.Kucharski@Sun.COM 		       + ((int16_t *)arptable[ARP_CLIENT].node)[2];
37*8044SWilliam.Kucharski@Sun.COM 	/* simplified version of the LCG given in Bruce Schneier's
38*8044SWilliam.Kucharski@Sun.COM 	   "Applied Cryptography" */
39*8044SWilliam.Kucharski@Sun.COM 	q = seed/53668;
40*8044SWilliam.Kucharski@Sun.COM 	if ((seed = 40014*(seed-53668*q) - 12211*q) < 0) seed += 2147483563L;
41*8044SWilliam.Kucharski@Sun.COM 	return seed;
42*8044SWilliam.Kucharski@Sun.COM }
43*8044SWilliam.Kucharski@Sun.COM 
44*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
45*8044SWilliam.Kucharski@Sun.COM POLL INTERRUPTIONS
46*8044SWilliam.Kucharski@Sun.COM **************************************************************************/
poll_interruptions(void)47*8044SWilliam.Kucharski@Sun.COM void poll_interruptions(void)
48*8044SWilliam.Kucharski@Sun.COM {
49*8044SWilliam.Kucharski@Sun.COM 	if (checkkey() != -1 && ASCII_CHAR(getkey()) == K_INTR) {
50*8044SWilliam.Kucharski@Sun.COM 		user_abort++;
51*8044SWilliam.Kucharski@Sun.COM 	}
52*8044SWilliam.Kucharski@Sun.COM }
53*8044SWilliam.Kucharski@Sun.COM 
54*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
55*8044SWilliam.Kucharski@Sun.COM SLEEP
56*8044SWilliam.Kucharski@Sun.COM **************************************************************************/
sleep(int secs)57*8044SWilliam.Kucharski@Sun.COM void sleep(int secs)
58*8044SWilliam.Kucharski@Sun.COM {
59*8044SWilliam.Kucharski@Sun.COM 	unsigned long tmo;
60*8044SWilliam.Kucharski@Sun.COM 
61*8044SWilliam.Kucharski@Sun.COM 	for (tmo = currticks()+secs*TICKS_PER_SEC; currticks() < tmo; ) {
62*8044SWilliam.Kucharski@Sun.COM 		poll_interruptions();
63*8044SWilliam.Kucharski@Sun.COM 	}
64*8044SWilliam.Kucharski@Sun.COM }
65*8044SWilliam.Kucharski@Sun.COM 
66*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
67*8044SWilliam.Kucharski@Sun.COM INTERRUPTIBLE SLEEP
68*8044SWilliam.Kucharski@Sun.COM **************************************************************************/
interruptible_sleep(int secs)69*8044SWilliam.Kucharski@Sun.COM void interruptible_sleep(int secs)
70*8044SWilliam.Kucharski@Sun.COM {
71*8044SWilliam.Kucharski@Sun.COM 	printf("<sleep>\n");
72*8044SWilliam.Kucharski@Sun.COM 	return sleep(secs);
73*8044SWilliam.Kucharski@Sun.COM }
74*8044SWilliam.Kucharski@Sun.COM 
75*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
76*8044SWilliam.Kucharski@Sun.COM TWIDDLE
77*8044SWilliam.Kucharski@Sun.COM **************************************************************************/
twiddle(void)78*8044SWilliam.Kucharski@Sun.COM void twiddle(void)
79*8044SWilliam.Kucharski@Sun.COM {
80*8044SWilliam.Kucharski@Sun.COM #ifdef BAR_PROGRESS
81*8044SWilliam.Kucharski@Sun.COM 	static int count=0;
82*8044SWilliam.Kucharski@Sun.COM 	static const char tiddles[]="-\\|/";
83*8044SWilliam.Kucharski@Sun.COM 	static unsigned long lastticks = 0;
84*8044SWilliam.Kucharski@Sun.COM 	unsigned long ticks;
85*8044SWilliam.Kucharski@Sun.COM #endif
86*8044SWilliam.Kucharski@Sun.COM #ifdef FREEBSD_PXEEMU
87*8044SWilliam.Kucharski@Sun.COM 	extern char pxeemu_nbp_active;
88*8044SWilliam.Kucharski@Sun.COM 	if(pxeemu_nbp_active != 0)
89*8044SWilliam.Kucharski@Sun.COM 		return;
90*8044SWilliam.Kucharski@Sun.COM #endif
91*8044SWilliam.Kucharski@Sun.COM #ifdef	BAR_PROGRESS
92*8044SWilliam.Kucharski@Sun.COM 	/* Limit the maximum rate at which characters are printed */
93*8044SWilliam.Kucharski@Sun.COM 	ticks = currticks();
94*8044SWilliam.Kucharski@Sun.COM 	if ((lastticks + (TICKS_PER_SEC/18)) > ticks)
95*8044SWilliam.Kucharski@Sun.COM 		return;
96*8044SWilliam.Kucharski@Sun.COM 	lastticks = ticks;
97*8044SWilliam.Kucharski@Sun.COM 
98*8044SWilliam.Kucharski@Sun.COM 	putchar(tiddles[(count++)&3]);
99*8044SWilliam.Kucharski@Sun.COM 	putchar('\b');
100*8044SWilliam.Kucharski@Sun.COM #else
101*8044SWilliam.Kucharski@Sun.COM 	//putchar('.');
102*8044SWilliam.Kucharski@Sun.COM #endif	/* BAR_PROGRESS */
103*8044SWilliam.Kucharski@Sun.COM }
104*8044SWilliam.Kucharski@Sun.COM 
105*8044SWilliam.Kucharski@Sun.COM 
106*8044SWilliam.Kucharski@Sun.COM /* Because Etherboot uses its own formats for the printf family,
107*8044SWilliam.Kucharski@Sun.COM    define separate definitions from GRUB.  */
108*8044SWilliam.Kucharski@Sun.COM /**************************************************************************
109*8044SWilliam.Kucharski@Sun.COM PRINTF and friends
110*8044SWilliam.Kucharski@Sun.COM 
111*8044SWilliam.Kucharski@Sun.COM 	Formats:
112*8044SWilliam.Kucharski@Sun.COM 		%[#]x	- 4 bytes long (8 hex digits, lower case)
113*8044SWilliam.Kucharski@Sun.COM 		%[#]X	- 4 bytes long (8 hex digits, upper case)
114*8044SWilliam.Kucharski@Sun.COM 		%[#]hx	- 2 bytes int (4 hex digits, lower case)
115*8044SWilliam.Kucharski@Sun.COM 		%[#]hX	- 2 bytes int (4 hex digits, upper case)
116*8044SWilliam.Kucharski@Sun.COM 		%[#]hhx	- 1 byte int (2 hex digits, lower case)
117*8044SWilliam.Kucharski@Sun.COM 		%[#]hhX	- 1 byte int (2 hex digits, upper case)
118*8044SWilliam.Kucharski@Sun.COM 			- optional # prefixes 0x or 0X
119*8044SWilliam.Kucharski@Sun.COM 		%d	- decimal int
120*8044SWilliam.Kucharski@Sun.COM 		%c	- char
121*8044SWilliam.Kucharski@Sun.COM 		%s	- string
122*8044SWilliam.Kucharski@Sun.COM 		%@	- Internet address in ddd.ddd.ddd.ddd notation
123*8044SWilliam.Kucharski@Sun.COM 		%!	- Ethernet address in xx:xx:xx:xx:xx:xx notation
124*8044SWilliam.Kucharski@Sun.COM 	Note: width specification not supported
125*8044SWilliam.Kucharski@Sun.COM **************************************************************************/
126*8044SWilliam.Kucharski@Sun.COM static int
etherboot_vsprintf(char * buf,const char * fmt,const int * dp)127*8044SWilliam.Kucharski@Sun.COM etherboot_vsprintf (char *buf, const char *fmt, const int *dp)
128*8044SWilliam.Kucharski@Sun.COM {
129*8044SWilliam.Kucharski@Sun.COM   char *p, *s;
130*8044SWilliam.Kucharski@Sun.COM 
131*8044SWilliam.Kucharski@Sun.COM   s = buf;
132*8044SWilliam.Kucharski@Sun.COM   for ( ; *fmt != '\0'; ++fmt)
133*8044SWilliam.Kucharski@Sun.COM     {
134*8044SWilliam.Kucharski@Sun.COM       if (*fmt != '%')
135*8044SWilliam.Kucharski@Sun.COM 	{
136*8044SWilliam.Kucharski@Sun.COM 	  buf ? *s++ = *fmt : grub_putchar (*fmt);
137*8044SWilliam.Kucharski@Sun.COM 	  continue;
138*8044SWilliam.Kucharski@Sun.COM 	}
139*8044SWilliam.Kucharski@Sun.COM 
140*8044SWilliam.Kucharski@Sun.COM       if (*++fmt == 's')
141*8044SWilliam.Kucharski@Sun.COM 	{
142*8044SWilliam.Kucharski@Sun.COM 	  for (p = (char *) *dp++; *p != '\0'; p++)
143*8044SWilliam.Kucharski@Sun.COM 	    buf ? *s++ = *p : grub_putchar (*p);
144*8044SWilliam.Kucharski@Sun.COM 	}
145*8044SWilliam.Kucharski@Sun.COM       else
146*8044SWilliam.Kucharski@Sun.COM 	{
147*8044SWilliam.Kucharski@Sun.COM 	  /* Length of item is bounded */
148*8044SWilliam.Kucharski@Sun.COM 	  char tmp[20], *q = tmp;
149*8044SWilliam.Kucharski@Sun.COM 	  int alt = 0;
150*8044SWilliam.Kucharski@Sun.COM 	  int shift = 28;
151*8044SWilliam.Kucharski@Sun.COM 
152*8044SWilliam.Kucharski@Sun.COM 	  if (*fmt == '#')
153*8044SWilliam.Kucharski@Sun.COM 	    {
154*8044SWilliam.Kucharski@Sun.COM 	      alt = 1;
155*8044SWilliam.Kucharski@Sun.COM 	      fmt++;
156*8044SWilliam.Kucharski@Sun.COM 	    }
157*8044SWilliam.Kucharski@Sun.COM 
158*8044SWilliam.Kucharski@Sun.COM 	  if (*fmt == 'h')
159*8044SWilliam.Kucharski@Sun.COM 	    {
160*8044SWilliam.Kucharski@Sun.COM 	      shift = 12;
161*8044SWilliam.Kucharski@Sun.COM 	      fmt++;
162*8044SWilliam.Kucharski@Sun.COM 	    }
163*8044SWilliam.Kucharski@Sun.COM 
164*8044SWilliam.Kucharski@Sun.COM 	  if (*fmt == 'h')
165*8044SWilliam.Kucharski@Sun.COM 	    {
166*8044SWilliam.Kucharski@Sun.COM 	      shift = 4;
167*8044SWilliam.Kucharski@Sun.COM 	      fmt++;
168*8044SWilliam.Kucharski@Sun.COM 	    }
169*8044SWilliam.Kucharski@Sun.COM 
170*8044SWilliam.Kucharski@Sun.COM 	  /*
171*8044SWilliam.Kucharski@Sun.COM 	   * Before each format q points to tmp buffer
172*8044SWilliam.Kucharski@Sun.COM 	   * After each format q points past end of item
173*8044SWilliam.Kucharski@Sun.COM 	   */
174*8044SWilliam.Kucharski@Sun.COM 	  if ((*fmt | 0x20) == 'x')
175*8044SWilliam.Kucharski@Sun.COM 	    {
176*8044SWilliam.Kucharski@Sun.COM 	      /* With x86 gcc, sizeof(long) == sizeof(int) */
177*8044SWilliam.Kucharski@Sun.COM 	      const long *lp = (const long *) dp;
178*8044SWilliam.Kucharski@Sun.COM 	      long h = *lp++;
179*8044SWilliam.Kucharski@Sun.COM 	      int ncase = (*fmt & 0x20);
180*8044SWilliam.Kucharski@Sun.COM 
181*8044SWilliam.Kucharski@Sun.COM 	      dp = (const int *) lp;
182*8044SWilliam.Kucharski@Sun.COM 	      if (alt)
183*8044SWilliam.Kucharski@Sun.COM 		{
184*8044SWilliam.Kucharski@Sun.COM 		  *q++ = '0';
185*8044SWilliam.Kucharski@Sun.COM 		  *q++ = 'X' | ncase;
186*8044SWilliam.Kucharski@Sun.COM 		}
187*8044SWilliam.Kucharski@Sun.COM 	      for (; shift >= 0; shift -= 4)
188*8044SWilliam.Kucharski@Sun.COM 		*q++ = "0123456789ABCDEF"[(h >> shift) & 0xF] | ncase;
189*8044SWilliam.Kucharski@Sun.COM 	    }
190*8044SWilliam.Kucharski@Sun.COM 	  else if (*fmt == 'd')
191*8044SWilliam.Kucharski@Sun.COM 	    {
192*8044SWilliam.Kucharski@Sun.COM 	      int i = *dp++;
193*8044SWilliam.Kucharski@Sun.COM 	      char *r;
194*8044SWilliam.Kucharski@Sun.COM 
195*8044SWilliam.Kucharski@Sun.COM 	      if (i < 0)
196*8044SWilliam.Kucharski@Sun.COM 		{
197*8044SWilliam.Kucharski@Sun.COM 		  *q++ = '-';
198*8044SWilliam.Kucharski@Sun.COM 		  i = -i;
199*8044SWilliam.Kucharski@Sun.COM 		}
200*8044SWilliam.Kucharski@Sun.COM 
201*8044SWilliam.Kucharski@Sun.COM 	      p = q;		/* save beginning of digits */
202*8044SWilliam.Kucharski@Sun.COM 	      do
203*8044SWilliam.Kucharski@Sun.COM 		{
204*8044SWilliam.Kucharski@Sun.COM 		  *q++ = '0' + (i % 10);
205*8044SWilliam.Kucharski@Sun.COM 		  i /= 10;
206*8044SWilliam.Kucharski@Sun.COM 		}
207*8044SWilliam.Kucharski@Sun.COM 	      while (i);
208*8044SWilliam.Kucharski@Sun.COM 
209*8044SWilliam.Kucharski@Sun.COM 	      /* reverse digits, stop in middle */
210*8044SWilliam.Kucharski@Sun.COM 	      r = q;		/* don't alter q */
211*8044SWilliam.Kucharski@Sun.COM 	      while (--r > p)
212*8044SWilliam.Kucharski@Sun.COM 		{
213*8044SWilliam.Kucharski@Sun.COM 		  i = *r;
214*8044SWilliam.Kucharski@Sun.COM 		  *r = *p;
215*8044SWilliam.Kucharski@Sun.COM 		  *p++ = i;
216*8044SWilliam.Kucharski@Sun.COM 		}
217*8044SWilliam.Kucharski@Sun.COM 	    }
218*8044SWilliam.Kucharski@Sun.COM 	  else if (*fmt == '@')
219*8044SWilliam.Kucharski@Sun.COM 	    {
220*8044SWilliam.Kucharski@Sun.COM 	      unsigned char *r;
221*8044SWilliam.Kucharski@Sun.COM 	      union
222*8044SWilliam.Kucharski@Sun.COM 	      {
223*8044SWilliam.Kucharski@Sun.COM 		long		l;
224*8044SWilliam.Kucharski@Sun.COM 		unsigned char	c[4];
225*8044SWilliam.Kucharski@Sun.COM 	      }
226*8044SWilliam.Kucharski@Sun.COM 	      u;
227*8044SWilliam.Kucharski@Sun.COM 	      const long *lp = (const long *) dp;
228*8044SWilliam.Kucharski@Sun.COM 
229*8044SWilliam.Kucharski@Sun.COM 	      u.l = *lp++;
230*8044SWilliam.Kucharski@Sun.COM 	      dp = (const int *) lp;
231*8044SWilliam.Kucharski@Sun.COM 
232*8044SWilliam.Kucharski@Sun.COM 	      for (r = &u.c[0]; r < &u.c[4]; ++r)
233*8044SWilliam.Kucharski@Sun.COM 		q += etherboot_sprintf (q, "%d.", *r);
234*8044SWilliam.Kucharski@Sun.COM 
235*8044SWilliam.Kucharski@Sun.COM 	      --q;
236*8044SWilliam.Kucharski@Sun.COM 	    }
237*8044SWilliam.Kucharski@Sun.COM 	  else if (*fmt == '!')
238*8044SWilliam.Kucharski@Sun.COM 	    {
239*8044SWilliam.Kucharski@Sun.COM 	      char *r;
240*8044SWilliam.Kucharski@Sun.COM 	      p = (char *) *dp++;
241*8044SWilliam.Kucharski@Sun.COM 
242*8044SWilliam.Kucharski@Sun.COM 	      for (r = p + ETH_ALEN; p < r; ++p)
243*8044SWilliam.Kucharski@Sun.COM 		q += etherboot_sprintf (q, "%hhX:", *p);
244*8044SWilliam.Kucharski@Sun.COM 
245*8044SWilliam.Kucharski@Sun.COM 	      --q;
246*8044SWilliam.Kucharski@Sun.COM 	    }
247*8044SWilliam.Kucharski@Sun.COM 	  else if (*fmt == 'c')
248*8044SWilliam.Kucharski@Sun.COM 	    *q++ = *dp++;
249*8044SWilliam.Kucharski@Sun.COM 	  else
250*8044SWilliam.Kucharski@Sun.COM 	    *q++ = *fmt;
251*8044SWilliam.Kucharski@Sun.COM 
252*8044SWilliam.Kucharski@Sun.COM 	  /* now output the saved string */
253*8044SWilliam.Kucharski@Sun.COM 	  for (p = tmp; p < q; ++p)
254*8044SWilliam.Kucharski@Sun.COM 	    buf ? *s++ = *p : grub_putchar (*p);
255*8044SWilliam.Kucharski@Sun.COM 	}
256*8044SWilliam.Kucharski@Sun.COM     }
257*8044SWilliam.Kucharski@Sun.COM 
258*8044SWilliam.Kucharski@Sun.COM   if (buf)
259*8044SWilliam.Kucharski@Sun.COM     *s = '\0';
260*8044SWilliam.Kucharski@Sun.COM 
261*8044SWilliam.Kucharski@Sun.COM   return (s - buf);
262*8044SWilliam.Kucharski@Sun.COM }
263*8044SWilliam.Kucharski@Sun.COM 
264*8044SWilliam.Kucharski@Sun.COM int
etherboot_sprintf(char * buf,const char * fmt,...)265*8044SWilliam.Kucharski@Sun.COM etherboot_sprintf (char *buf, const char *fmt, ...)
266*8044SWilliam.Kucharski@Sun.COM {
267*8044SWilliam.Kucharski@Sun.COM   return etherboot_vsprintf (buf, fmt, ((const int *) &fmt) + 1);
268*8044SWilliam.Kucharski@Sun.COM }
269*8044SWilliam.Kucharski@Sun.COM 
270*8044SWilliam.Kucharski@Sun.COM void
etherboot_printf(const char * fmt,...)271*8044SWilliam.Kucharski@Sun.COM etherboot_printf (const char *fmt, ...)
272*8044SWilliam.Kucharski@Sun.COM {
273*8044SWilliam.Kucharski@Sun.COM   (void) etherboot_vsprintf (0, fmt, ((const int *) &fmt) + 1);
274*8044SWilliam.Kucharski@Sun.COM }
275*8044SWilliam.Kucharski@Sun.COM 
276*8044SWilliam.Kucharski@Sun.COM int
inet_aton(char * p,in_addr * addr)277*8044SWilliam.Kucharski@Sun.COM inet_aton (char *p, in_addr *addr)
278*8044SWilliam.Kucharski@Sun.COM {
279*8044SWilliam.Kucharski@Sun.COM   unsigned long ip = 0;
280*8044SWilliam.Kucharski@Sun.COM   int val;
281*8044SWilliam.Kucharski@Sun.COM   int i;
282*8044SWilliam.Kucharski@Sun.COM 
283*8044SWilliam.Kucharski@Sun.COM   for (i = 0; i < 4; i++)
284*8044SWilliam.Kucharski@Sun.COM     {
285*8044SWilliam.Kucharski@Sun.COM       val = getdec (&p);
286*8044SWilliam.Kucharski@Sun.COM 
287*8044SWilliam.Kucharski@Sun.COM       if (val < 0 || val > 255)
288*8044SWilliam.Kucharski@Sun.COM 	return 0;
289*8044SWilliam.Kucharski@Sun.COM 
290*8044SWilliam.Kucharski@Sun.COM       if (i != 3 && *p++ != '.')
291*8044SWilliam.Kucharski@Sun.COM 	return 0;
292*8044SWilliam.Kucharski@Sun.COM 
293*8044SWilliam.Kucharski@Sun.COM       ip = (ip << 8) | val;
294*8044SWilliam.Kucharski@Sun.COM     }
295*8044SWilliam.Kucharski@Sun.COM 
296*8044SWilliam.Kucharski@Sun.COM   addr->s_addr = htonl (ip);
297*8044SWilliam.Kucharski@Sun.COM 
298*8044SWilliam.Kucharski@Sun.COM   return 1;
299*8044SWilliam.Kucharski@Sun.COM }
300*8044SWilliam.Kucharski@Sun.COM 
301*8044SWilliam.Kucharski@Sun.COM int
getdec(char ** ptr)302*8044SWilliam.Kucharski@Sun.COM getdec (char **ptr)
303*8044SWilliam.Kucharski@Sun.COM {
304*8044SWilliam.Kucharski@Sun.COM   char *p = *ptr;
305*8044SWilliam.Kucharski@Sun.COM   int ret = 0;
306*8044SWilliam.Kucharski@Sun.COM 
307*8044SWilliam.Kucharski@Sun.COM   if (*p < '0' || *p > '9')
308*8044SWilliam.Kucharski@Sun.COM     return -1;
309*8044SWilliam.Kucharski@Sun.COM 
310*8044SWilliam.Kucharski@Sun.COM   while (*p >= '0' && *p <= '9')
311*8044SWilliam.Kucharski@Sun.COM     {
312*8044SWilliam.Kucharski@Sun.COM       ret = ret * 10 + (*p - '0');
313*8044SWilliam.Kucharski@Sun.COM       p++;
314*8044SWilliam.Kucharski@Sun.COM     }
315*8044SWilliam.Kucharski@Sun.COM 
316*8044SWilliam.Kucharski@Sun.COM   *ptr = p;
317*8044SWilliam.Kucharski@Sun.COM 
318*8044SWilliam.Kucharski@Sun.COM   return ret;
319*8044SWilliam.Kucharski@Sun.COM }
320*8044SWilliam.Kucharski@Sun.COM 
321*8044SWilliam.Kucharski@Sun.COM 
322