10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * Copyright 1987, 1988 by MIT Student Information Processing Board 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * For copyright info, see copyright.h. 50Sstevel@tonic-gate */ 60Sstevel@tonic-gate 7*8093SMark.Phalan@Sun.COM /* 8*8093SMark.Phalan@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 9*8093SMark.Phalan@Sun.COM * Use is subject to license terms. 10*8093SMark.Phalan@Sun.COM */ 11*8093SMark.Phalan@Sun.COM 120Sstevel@tonic-gate #include "ss_internal.h" 130Sstevel@tonic-gate #include "copyright.h" 142881Smp153739 #include <errno.h> 150Sstevel@tonic-gate 160Sstevel@tonic-gate enum parse_mode { WHITESPACE, TOKEN, QUOTED_STRING }; 170Sstevel@tonic-gate 18*8093SMark.Phalan@Sun.COM 19*8093SMark.Phalan@Sun.COM /* 20*8093SMark.Phalan@Sun.COM * Solaris Kerberos: 21*8093SMark.Phalan@Sun.COM * ss_parse has been modified slightly from the original in two ways. 22*8093SMark.Phalan@Sun.COM * 1) A new parameter "quiet" has been added which is used to silence 23*8093SMark.Phalan@Sun.COM * error or warning messages. 24*8093SMark.Phalan@Sun.COM * 2) ss_parse now returns an error status instead of argv - this is to 25*8093SMark.Phalan@Sun.COM * allow an error to be distinguished from no tokens when parsing an empty 26*8093SMark.Phalan@Sun.COM * string. 27*8093SMark.Phalan@Sun.COM * Both of these changes allow ss_parse to be used during tab-completion. 28*8093SMark.Phalan@Sun.COM */ 29*8093SMark.Phalan@Sun.COM 300Sstevel@tonic-gate /* 310Sstevel@tonic-gate * parse(line_ptr, argc_ptr) 320Sstevel@tonic-gate * 330Sstevel@tonic-gate * Function: 340Sstevel@tonic-gate * Parses line, dividing at whitespace, into tokens, returns 350Sstevel@tonic-gate * the "argc" and "argv" values. 360Sstevel@tonic-gate * Arguments: 370Sstevel@tonic-gate * line_ptr (char *) 380Sstevel@tonic-gate * Pointer to text string to be parsed. 390Sstevel@tonic-gate * argc_ptr (int *) 400Sstevel@tonic-gate * Where to put the "argc" (number of tokens) value. 41*8093SMark.Phalan@Sun.COM * argv_ptr (char ***) 42*8093SMark.Phalan@Sun.COM * Where to put the series of pointers to parsed tokens. 430Sstevel@tonic-gate * Returns: 44*8093SMark.Phalan@Sun.COM * error (0 - success, non-zero on failure) 450Sstevel@tonic-gate */ 460Sstevel@tonic-gate 470Sstevel@tonic-gate #define NEW_ARGV(old,n) (char **)realloc((char *)old,\ 480Sstevel@tonic-gate (unsigned)(n+2)*sizeof(char*)) 490Sstevel@tonic-gate 50*8093SMark.Phalan@Sun.COM int ss_parse (sci_idx, line_ptr, argc_ptr, argv_ptr, quiet) 510Sstevel@tonic-gate int sci_idx; 520Sstevel@tonic-gate register char *line_ptr; 530Sstevel@tonic-gate int *argc_ptr; 54*8093SMark.Phalan@Sun.COM char ***argv_ptr; 55*8093SMark.Phalan@Sun.COM int quiet; 560Sstevel@tonic-gate { 570Sstevel@tonic-gate register char **argv, *cp; 580Sstevel@tonic-gate register int argc; 590Sstevel@tonic-gate register enum parse_mode parse_mode; 600Sstevel@tonic-gate 610Sstevel@tonic-gate argv = (char **) malloc (sizeof(char *)); 620Sstevel@tonic-gate if (argv == (char **)NULL) { 63*8093SMark.Phalan@Sun.COM if (!quiet) 64*8093SMark.Phalan@Sun.COM ss_error(sci_idx, errno, "Can't allocate storage"); 650Sstevel@tonic-gate *argc_ptr = 0; 66*8093SMark.Phalan@Sun.COM *argv_ptr = argv; 67*8093SMark.Phalan@Sun.COM return(ENOMEM); 680Sstevel@tonic-gate } 690Sstevel@tonic-gate *argv = (char *)NULL; 700Sstevel@tonic-gate 710Sstevel@tonic-gate argc = 0; 720Sstevel@tonic-gate 730Sstevel@tonic-gate parse_mode = WHITESPACE; /* flushing whitespace */ 740Sstevel@tonic-gate cp = line_ptr; /* cp is for output */ 750Sstevel@tonic-gate while (1) { 760Sstevel@tonic-gate #ifdef DEBUG 770Sstevel@tonic-gate { 782881Smp153739 printf ("character `%c', mode %d\n", *line_ptr, parse_mode); 790Sstevel@tonic-gate } 800Sstevel@tonic-gate #endif 810Sstevel@tonic-gate while (parse_mode == WHITESPACE) { 820Sstevel@tonic-gate if (*line_ptr == '\0') 830Sstevel@tonic-gate goto end_of_line; 840Sstevel@tonic-gate if (*line_ptr == ' ' || *line_ptr == '\t') { 850Sstevel@tonic-gate line_ptr++; 860Sstevel@tonic-gate continue; 870Sstevel@tonic-gate } 880Sstevel@tonic-gate if (*line_ptr == '"') { 890Sstevel@tonic-gate /* go to quoted-string mode */ 900Sstevel@tonic-gate parse_mode = QUOTED_STRING; 910Sstevel@tonic-gate cp = line_ptr++; 920Sstevel@tonic-gate argv = NEW_ARGV (argv, argc); 930Sstevel@tonic-gate argv[argc++] = cp; 940Sstevel@tonic-gate argv[argc] = NULL; 950Sstevel@tonic-gate } 960Sstevel@tonic-gate else { 970Sstevel@tonic-gate /* random-token mode */ 980Sstevel@tonic-gate parse_mode = TOKEN; 990Sstevel@tonic-gate cp = line_ptr; 1000Sstevel@tonic-gate argv = NEW_ARGV (argv, argc); 1010Sstevel@tonic-gate argv[argc++] = line_ptr; 1020Sstevel@tonic-gate argv[argc] = NULL; 1030Sstevel@tonic-gate } 1040Sstevel@tonic-gate } 1050Sstevel@tonic-gate while (parse_mode == TOKEN) { 1060Sstevel@tonic-gate if (*line_ptr == '\0') { 1070Sstevel@tonic-gate *cp++ = '\0'; 1080Sstevel@tonic-gate goto end_of_line; 1090Sstevel@tonic-gate } 1100Sstevel@tonic-gate else if (*line_ptr == ' ' || *line_ptr == '\t') { 1110Sstevel@tonic-gate *cp++ = '\0'; 1120Sstevel@tonic-gate line_ptr++; 1130Sstevel@tonic-gate parse_mode = WHITESPACE; 1140Sstevel@tonic-gate } 1150Sstevel@tonic-gate else if (*line_ptr == '"') { 1160Sstevel@tonic-gate line_ptr++; 1170Sstevel@tonic-gate parse_mode = QUOTED_STRING; 1180Sstevel@tonic-gate } 1190Sstevel@tonic-gate else { 1200Sstevel@tonic-gate *cp++ = *line_ptr++; 1210Sstevel@tonic-gate } 1220Sstevel@tonic-gate } 1230Sstevel@tonic-gate while (parse_mode == QUOTED_STRING) { 1240Sstevel@tonic-gate if (*line_ptr == '\0') { 125*8093SMark.Phalan@Sun.COM if (!quiet) 126*8093SMark.Phalan@Sun.COM ss_error (sci_idx, 0, 127*8093SMark.Phalan@Sun.COM "Unbalanced quotes in command line"); 1280Sstevel@tonic-gate free (argv); 1290Sstevel@tonic-gate *argc_ptr = 0; 130*8093SMark.Phalan@Sun.COM *argv_ptr = NULL; 131*8093SMark.Phalan@Sun.COM return (-1); 1320Sstevel@tonic-gate } 1330Sstevel@tonic-gate else if (*line_ptr == '"') { 1340Sstevel@tonic-gate if (*++line_ptr == '"') { 1350Sstevel@tonic-gate *cp++ = '"'; 1360Sstevel@tonic-gate line_ptr++; 1370Sstevel@tonic-gate } 1380Sstevel@tonic-gate else { 1390Sstevel@tonic-gate parse_mode = TOKEN; 1400Sstevel@tonic-gate } 1410Sstevel@tonic-gate } 1420Sstevel@tonic-gate else { 1430Sstevel@tonic-gate *cp++ = *line_ptr++; 1440Sstevel@tonic-gate } 1450Sstevel@tonic-gate } 1460Sstevel@tonic-gate } 1470Sstevel@tonic-gate end_of_line: 1480Sstevel@tonic-gate *argc_ptr = argc; 1490Sstevel@tonic-gate #ifdef DEBUG 1502881Smp153739 { 1512881Smp153739 int i; 1522881Smp153739 printf ("argc = %d\n", argc); 1532881Smp153739 for (i = 0; i <= argc; i++) 1542881Smp153739 printf ("\targv[%2d] = `%s'\n", i, 1552881Smp153739 argv[i] ? argv[i] : "<NULL>"); 1562881Smp153739 } 1570Sstevel@tonic-gate #endif 158*8093SMark.Phalan@Sun.COM *argv_ptr = argv; 159*8093SMark.Phalan@Sun.COM return(0); 1600Sstevel@tonic-gate } 161