17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
23*5d54f3d8Smuffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24*5d54f3d8Smuffin * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984 AT&T */
287c478bd9Sstevel@tonic-gate /* All Rights Reserved */
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/
337c478bd9Sstevel@tonic-gate #include <stdio.h>
347c478bd9Sstevel@tonic-gate #include <ctype.h>
35*5d54f3d8Smuffin #include <stdarg.h>
367c478bd9Sstevel@tonic-gate #include <errno.h>
37*5d54f3d8Smuffin #include <string.h>
38*5d54f3d8Smuffin #include <malloc.h>
397c478bd9Sstevel@tonic-gate
407c478bd9Sstevel@tonic-gate #define ON 1
417c478bd9Sstevel@tonic-gate #define OFF 0
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate #define ARGMAX 64
447c478bd9Sstevel@tonic-gate static unsigned char newap[ARGMAX * sizeof(double)];
457c478bd9Sstevel@tonic-gate static unsigned char newform[256];
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate extern int _doscan();
487c478bd9Sstevel@tonic-gate
49*5d54f3d8Smuffin static int format_arg(unsigned char *, unsigned char *, unsigned char *);
50*5d54f3d8Smuffin
517c478bd9Sstevel@tonic-gate int
scanf(char * fmt,...)52*5d54f3d8Smuffin scanf(char *fmt, ...)
537c478bd9Sstevel@tonic-gate {
547c478bd9Sstevel@tonic-gate va_list ap;
557c478bd9Sstevel@tonic-gate char *nf;
567c478bd9Sstevel@tonic-gate int ret_val;
577c478bd9Sstevel@tonic-gate
58*5d54f3d8Smuffin
59*5d54f3d8Smuffin va_start(ap, fmt);
607c478bd9Sstevel@tonic-gate if (strlen(fmt) >= sizeof(newform)) {
617c478bd9Sstevel@tonic-gate nf = malloc(strlen(fmt)+1);
62*5d54f3d8Smuffin if (format_arg((unsigned char *)strcpy(nf, fmt), ap, newap)
63*5d54f3d8Smuffin == ON) {
64*5d54f3d8Smuffin va_end(ap);
657c478bd9Sstevel@tonic-gate ret_val = _doscan(stdin, nf, newap);
667c478bd9Sstevel@tonic-gate free(nf);
677c478bd9Sstevel@tonic-gate return(ret_val);
687c478bd9Sstevel@tonic-gate }
697c478bd9Sstevel@tonic-gate free(nf);
70*5d54f3d8Smuffin } else if (format_arg((unsigned char *)strcpy(newform, fmt), ap, newap)
71*5d54f3d8Smuffin == ON) {
72*5d54f3d8Smuffin va_end(ap);
737c478bd9Sstevel@tonic-gate return(_doscan(stdin, newform, newap));
747c478bd9Sstevel@tonic-gate }
75*5d54f3d8Smuffin ret_val = _doscan(stdin, fmt, ap);
76*5d54f3d8Smuffin va_end(ap);
77*5d54f3d8Smuffin return (ret_val);
787c478bd9Sstevel@tonic-gate }
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gate int
fscanf(FILE * iop,char * fmt,...)81*5d54f3d8Smuffin fscanf(FILE *iop, char *fmt, ...)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate va_list ap;
847c478bd9Sstevel@tonic-gate char *nf;
857c478bd9Sstevel@tonic-gate int ret_val;
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate #ifdef POSIX
887c478bd9Sstevel@tonic-gate if ( !(iop->_flag & (_IOREAD|_IORW)) ) {
897c478bd9Sstevel@tonic-gate iop->_flag |= _IOERR;
907c478bd9Sstevel@tonic-gate errno = EBADF;
917c478bd9Sstevel@tonic-gate return (EOF);
927c478bd9Sstevel@tonic-gate }
93*5d54f3d8Smuffin #endif /* POSIX */
94*5d54f3d8Smuffin va_start(ap, fmt);
957c478bd9Sstevel@tonic-gate if (strlen(fmt) >= sizeof(newform)) {
967c478bd9Sstevel@tonic-gate nf = malloc(strlen(fmt)+1);
97*5d54f3d8Smuffin if (format_arg((unsigned char *)strcpy(nf, fmt), ap, newap)
98*5d54f3d8Smuffin == ON) {
99*5d54f3d8Smuffin va_end(ap);
1007c478bd9Sstevel@tonic-gate ret_val = _doscan(stdin, nf, newap);
1017c478bd9Sstevel@tonic-gate free(nf);
1027c478bd9Sstevel@tonic-gate return(ret_val);
1037c478bd9Sstevel@tonic-gate }
1047c478bd9Sstevel@tonic-gate free(nf);
105*5d54f3d8Smuffin } else if (format_arg((unsigned char *)strcpy(newform, fmt), ap, newap)
106*5d54f3d8Smuffin == ON) {
107*5d54f3d8Smuffin va_end(ap);
1087c478bd9Sstevel@tonic-gate return(_doscan(iop, newform, newap));
1097c478bd9Sstevel@tonic-gate }
110*5d54f3d8Smuffin ret_val = _doscan(iop, fmt, ap);
111*5d54f3d8Smuffin va_end(ap);
112*5d54f3d8Smuffin return (ret_val);
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate int
sscanf(char * str,char * fmt,...)116*5d54f3d8Smuffin sscanf(char *str, char *fmt, ...)
1177c478bd9Sstevel@tonic-gate {
1187c478bd9Sstevel@tonic-gate va_list ap;
1197c478bd9Sstevel@tonic-gate FILE strbuf;
1207c478bd9Sstevel@tonic-gate char *nf;
1217c478bd9Sstevel@tonic-gate int ret_val;
1227c478bd9Sstevel@tonic-gate
123*5d54f3d8Smuffin va_start(ap, fmt);
1247c478bd9Sstevel@tonic-gate strbuf._flag = _IOREAD|_IOSTRG;
1257c478bd9Sstevel@tonic-gate strbuf._ptr = strbuf._base = (unsigned char*)str;
1267c478bd9Sstevel@tonic-gate strbuf._cnt = strlen(str);
1277c478bd9Sstevel@tonic-gate strbuf._bufsiz = strbuf._cnt;
1287c478bd9Sstevel@tonic-gate if (strlen(fmt) >= sizeof(newform)) {
1297c478bd9Sstevel@tonic-gate nf = malloc(strlen(fmt)+1);
130*5d54f3d8Smuffin if (format_arg((unsigned char *)strcpy(nf, fmt), ap, newap)
131*5d54f3d8Smuffin == ON) {
132*5d54f3d8Smuffin va_end(ap);
1337c478bd9Sstevel@tonic-gate ret_val = _doscan(stdin, nf, newap);
1347c478bd9Sstevel@tonic-gate free(nf);
1357c478bd9Sstevel@tonic-gate return(ret_val);
1367c478bd9Sstevel@tonic-gate }
1377c478bd9Sstevel@tonic-gate free(nf);
138*5d54f3d8Smuffin } else if (format_arg((unsigned char *)strcpy(newform, fmt), ap, newap)
139*5d54f3d8Smuffin == ON) {
140*5d54f3d8Smuffin va_end(ap);
1417c478bd9Sstevel@tonic-gate return(_doscan(&strbuf, newform, newap));
1427c478bd9Sstevel@tonic-gate }
143*5d54f3d8Smuffin ret_val = _doscan(&strbuf, fmt, ap);
144*5d54f3d8Smuffin va_end(ap);
145*5d54f3d8Smuffin return (ret_val);
1467c478bd9Sstevel@tonic-gate }
1477c478bd9Sstevel@tonic-gate
1487c478bd9Sstevel@tonic-gate /*
1497c478bd9Sstevel@tonic-gate * This function reorganises the format string and argument list.
1507c478bd9Sstevel@tonic-gate */
1517c478bd9Sstevel@tonic-gate
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate #ifndef NL_ARGMAX
1547c478bd9Sstevel@tonic-gate #define NL_ARGMAX 9
1557c478bd9Sstevel@tonic-gate #endif
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate struct al {
1587c478bd9Sstevel@tonic-gate int a_num; /* arg # specified at this position */
1597c478bd9Sstevel@tonic-gate unsigned char *a_start; /* ptr to 'n' part of '%n$' in format str */
1607c478bd9Sstevel@tonic-gate unsigned char *a_end; /* ptr to '$'+1 part of '%n$' in format str */
1617c478bd9Sstevel@tonic-gate int *a_val; /* pointers to arguments */
1627c478bd9Sstevel@tonic-gate };
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate static int
format_arg(unsigned char * format,unsigned char * list,unsigned char * newlist)165*5d54f3d8Smuffin format_arg(unsigned char *format, unsigned char *list, unsigned char *newlist)
1667c478bd9Sstevel@tonic-gate {
1677c478bd9Sstevel@tonic-gate unsigned char *aptr, *bptr, *cptr;
168*5d54f3d8Smuffin int i, fcode, nl_fmt, num, length, j;
1697c478bd9Sstevel@tonic-gate unsigned char *fmtsav;
1707c478bd9Sstevel@tonic-gate struct al args[ARGMAX + 1];
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate #ifdef VTEST
1737c478bd9Sstevel@tonic-gate {
1747c478bd9Sstevel@tonic-gate int fd;
1757c478bd9Sstevel@tonic-gate fd = creat("/tmp/SCANF", 0666);
1767c478bd9Sstevel@tonic-gate }
1777c478bd9Sstevel@tonic-gate #endif
1787c478bd9Sstevel@tonic-gate for (i = 0; i <= ARGMAX; args[i++].a_num = 0);
1797c478bd9Sstevel@tonic-gate nl_fmt = 0;
1807c478bd9Sstevel@tonic-gate i = j = 1;
1817c478bd9Sstevel@tonic-gate while (*format) {
1827c478bd9Sstevel@tonic-gate while ((fcode = *format++) != '\0' && fcode != '%') ;
1837c478bd9Sstevel@tonic-gate if (!fcode || i > ARGMAX)
1847c478bd9Sstevel@tonic-gate break;
1857c478bd9Sstevel@tonic-gate charswitch:
1867c478bd9Sstevel@tonic-gate switch (fcode = *format++) {
1877c478bd9Sstevel@tonic-gate case 'l':
1887c478bd9Sstevel@tonic-gate case 'h':
1897c478bd9Sstevel@tonic-gate goto charswitch;
1907c478bd9Sstevel@tonic-gate case '0': case '1': case '2':
1917c478bd9Sstevel@tonic-gate case '3': case '4': case '5':
1927c478bd9Sstevel@tonic-gate case '6': case '7': case '8':
1937c478bd9Sstevel@tonic-gate case '9':
1947c478bd9Sstevel@tonic-gate num = fcode - '0';
1957c478bd9Sstevel@tonic-gate fmtsav = format;
1967c478bd9Sstevel@tonic-gate while (isdigit(fcode = *format)) {
1977c478bd9Sstevel@tonic-gate num = num * 10 + fcode - '0';
1987c478bd9Sstevel@tonic-gate format++;
1997c478bd9Sstevel@tonic-gate }
2007c478bd9Sstevel@tonic-gate if (*format == '$') {
2017c478bd9Sstevel@tonic-gate nl_fmt++;
2027c478bd9Sstevel@tonic-gate args[i].a_start = fmtsav - 1;
2037c478bd9Sstevel@tonic-gate args[i].a_end = ++format;
2047c478bd9Sstevel@tonic-gate if (num > NL_ARGMAX)
2057c478bd9Sstevel@tonic-gate num = num;
2067c478bd9Sstevel@tonic-gate args[i].a_num = num;
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate goto charswitch;
2097c478bd9Sstevel@tonic-gate /* now have arg type only to parse */
2107c478bd9Sstevel@tonic-gate case 'd': case 'u': case 'o':
2117c478bd9Sstevel@tonic-gate case 'x': case 'e': case 'f':
2127c478bd9Sstevel@tonic-gate case 'g': case 'c': case '[':
2137c478bd9Sstevel@tonic-gate case 's':
2147c478bd9Sstevel@tonic-gate if (nl_fmt == 0)
2157c478bd9Sstevel@tonic-gate return(OFF);
2167c478bd9Sstevel@tonic-gate if (!args[i].a_num) {
2177c478bd9Sstevel@tonic-gate args[i].a_start = args[i].a_end = format - 1;
2187c478bd9Sstevel@tonic-gate args[i].a_num = j++;
2197c478bd9Sstevel@tonic-gate }
2207c478bd9Sstevel@tonic-gate i++;
2217c478bd9Sstevel@tonic-gate break;
2227c478bd9Sstevel@tonic-gate case '*':
2237c478bd9Sstevel@tonic-gate case '%':
2247c478bd9Sstevel@tonic-gate break;
2257c478bd9Sstevel@tonic-gate default:
2267c478bd9Sstevel@tonic-gate format--;
2277c478bd9Sstevel@tonic-gate break;
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate }
2307c478bd9Sstevel@tonic-gate length = i;
2317c478bd9Sstevel@tonic-gate if (nl_fmt == 0)
2327c478bd9Sstevel@tonic-gate return (OFF);
2337c478bd9Sstevel@tonic-gate for (i = 1; i < length && args[i].a_num == 0; i++);
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate /*
2367c478bd9Sstevel@tonic-gate * Reformat the format string
2377c478bd9Sstevel@tonic-gate */
2387c478bd9Sstevel@tonic-gate cptr = aptr = args[i].a_start;
2397c478bd9Sstevel@tonic-gate do {
2407c478bd9Sstevel@tonic-gate bptr = args[i++].a_end;
2417c478bd9Sstevel@tonic-gate for (; i < length && args[i].a_num == 0; i++);
2427c478bd9Sstevel@tonic-gate if (i == length)
2437c478bd9Sstevel@tonic-gate while (*cptr++);
2447c478bd9Sstevel@tonic-gate else
2457c478bd9Sstevel@tonic-gate cptr = args[i].a_start;
2467c478bd9Sstevel@tonic-gate for (; bptr != cptr; *aptr++ = *bptr++);
2477c478bd9Sstevel@tonic-gate } while (i < length);
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate /*
2507c478bd9Sstevel@tonic-gate * Create arglist
2517c478bd9Sstevel@tonic-gate * assuming that pointer to all variable type have
2527c478bd9Sstevel@tonic-gate * same size.
2537c478bd9Sstevel@tonic-gate */
2547c478bd9Sstevel@tonic-gate for (i = 1; i < length; i++)
2557c478bd9Sstevel@tonic-gate args[i].a_val = ((int **)(list += sizeof(int *)))[-1];
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate for (i = 1; i < length; i++) {
2587c478bd9Sstevel@tonic-gate int **ptr;
2597c478bd9Sstevel@tonic-gate ptr = (int **)newlist;
2607c478bd9Sstevel@tonic-gate *ptr = args[args[i].a_num].a_val;
2617c478bd9Sstevel@tonic-gate newlist += sizeof(int *);
2627c478bd9Sstevel@tonic-gate }
2637c478bd9Sstevel@tonic-gate return(ON);
2647c478bd9Sstevel@tonic-gate }
265