17c478bd9Sstevel@tonic-gate /* 2*6c02b4a4Smuffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 77c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 87c478bd9Sstevel@tonic-gate 97c478bd9Sstevel@tonic-gate /* 107c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 117c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement 127c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 137c478bd9Sstevel@tonic-gate */ 147c478bd9Sstevel@tonic-gate 157c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 167c478bd9Sstevel@tonic-gate 177c478bd9Sstevel@tonic-gate #include "sh.h" 187c478bd9Sstevel@tonic-gate #include <locale.h> 197c478bd9Sstevel@tonic-gate #include <dirent.h> 20*6c02b4a4Smuffin #include <string.h> 217c478bd9Sstevel@tonic-gate /* 227c478bd9Sstevel@tonic-gate * #include <sys/ioctl.h> 237c478bd9Sstevel@tonic-gate * #include <stdlib.h> 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate #include "sh.tconst.h" 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * C Shell 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate bool errspl; /* Argument to error was spliced by seterr2 */ 327c478bd9Sstevel@tonic-gate tchar one[2] = { '1', 0 }; 337c478bd9Sstevel@tonic-gate tchar *onev[2] = { one, NOSTR }; 347c478bd9Sstevel@tonic-gate /* 357c478bd9Sstevel@tonic-gate * contains DIR * for last opendir_(), its left open if an error 367c478bd9Sstevel@tonic-gate * longjmp (reset) occurs before it gets closed via closedir. 377c478bd9Sstevel@tonic-gate * if its not null in the error handler, then closedir it. 387c478bd9Sstevel@tonic-gate */ 397c478bd9Sstevel@tonic-gate DIR *Dirp = NULL; 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate /* 427c478bd9Sstevel@tonic-gate * Print error string s with optional argument arg. 437c478bd9Sstevel@tonic-gate * This routine always resets or exits. The flag haderr 447c478bd9Sstevel@tonic-gate * is set so the routine who catches the unwind can propogate 457c478bd9Sstevel@tonic-gate * it if they want. 467c478bd9Sstevel@tonic-gate * 477c478bd9Sstevel@tonic-gate * Note that any open files at the point of error will eventually 487c478bd9Sstevel@tonic-gate * be closed in the routine process in sh.c which is the only 497c478bd9Sstevel@tonic-gate * place error unwinds are ever caught. 507c478bd9Sstevel@tonic-gate */ 517c478bd9Sstevel@tonic-gate /*VARARGS1*/ 52*6c02b4a4Smuffin void 537c478bd9Sstevel@tonic-gate error(s, a1, a2) 547c478bd9Sstevel@tonic-gate char *s; 557c478bd9Sstevel@tonic-gate { 56*6c02b4a4Smuffin tchar **v; 57*6c02b4a4Smuffin char *ep; 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate /* 607c478bd9Sstevel@tonic-gate * Must flush before we print as we wish output before the error 617c478bd9Sstevel@tonic-gate * to go on (some form of) standard output, while output after 627c478bd9Sstevel@tonic-gate * goes on (some form of) diagnostic output. 637c478bd9Sstevel@tonic-gate * If didfds then output will go to 1/2 else to FSHOUT/FSHDIAG. 647c478bd9Sstevel@tonic-gate * See flush in sh.print.c. 657c478bd9Sstevel@tonic-gate */ 667c478bd9Sstevel@tonic-gate flush(); 677c478bd9Sstevel@tonic-gate haderr = 1; /* Now to diagnostic output */ 687c478bd9Sstevel@tonic-gate timflg = 0; /* This isn't otherwise reset */ 697c478bd9Sstevel@tonic-gate if (v = pargv) 707c478bd9Sstevel@tonic-gate pargv = 0, blkfree(v); 717c478bd9Sstevel@tonic-gate if (v = gargv) 727c478bd9Sstevel@tonic-gate gargv = 0, blkfree(v); 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate /* 757c478bd9Sstevel@tonic-gate * A zero arguments causes no printing, else print 767c478bd9Sstevel@tonic-gate * an error diagnostic here. 777c478bd9Sstevel@tonic-gate */ 787c478bd9Sstevel@tonic-gate if (s) { 797c478bd9Sstevel@tonic-gate printf(s, a1, a2), printf("\n"); 807c478bd9Sstevel@tonic-gate } 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate didfds = 0; /* Forget about 0,1,2 */ 847c478bd9Sstevel@tonic-gate if ((ep = err) && errspl) { 857c478bd9Sstevel@tonic-gate errspl = 0; 867c478bd9Sstevel@tonic-gate xfree(ep); 877c478bd9Sstevel@tonic-gate } 887c478bd9Sstevel@tonic-gate errspl = 0; 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate if ( Dirp ){ 917c478bd9Sstevel@tonic-gate closedir(Dirp); 927c478bd9Sstevel@tonic-gate Dirp = NULL; 937c478bd9Sstevel@tonic-gate } 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate /* 967c478bd9Sstevel@tonic-gate * Go away if -e or we are a child shell 977c478bd9Sstevel@tonic-gate */ 987c478bd9Sstevel@tonic-gate if (exiterr || child) { 997c478bd9Sstevel@tonic-gate exit(1); 1007c478bd9Sstevel@tonic-gate } 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate /* 1037c478bd9Sstevel@tonic-gate * Reset the state of the input. 1047c478bd9Sstevel@tonic-gate * This buffered seek to end of file will also 1057c478bd9Sstevel@tonic-gate * clear the while/foreach stack. 1067c478bd9Sstevel@tonic-gate */ 1077c478bd9Sstevel@tonic-gate btoeof(); 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate setq(S_status, onev, &shvhed); 1107c478bd9Sstevel@tonic-gate if (tpgrp > 0) 1117c478bd9Sstevel@tonic-gate (void) ioctl(FSHTTY, TIOCSPGRP, (char *)&tpgrp); 1127c478bd9Sstevel@tonic-gate reset(); /* Unwind */ 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * Perror is the shells version of perror which should otherwise 1177c478bd9Sstevel@tonic-gate * never be called. 1187c478bd9Sstevel@tonic-gate */ 119*6c02b4a4Smuffin void 120*6c02b4a4Smuffin Perror(tchar *s) 1217c478bd9Sstevel@tonic-gate { 1227c478bd9Sstevel@tonic-gate char chbuf[BUFSIZ]; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate /* 1257c478bd9Sstevel@tonic-gate * Perror uses unit 2, thus if we didn't set up the fd's 1267c478bd9Sstevel@tonic-gate * we must set up unit 2 now else the diagnostic will disappear 1277c478bd9Sstevel@tonic-gate */ 1287c478bd9Sstevel@tonic-gate if (!didfds) { 129*6c02b4a4Smuffin int oerrno = errno; 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate (void) dcopy(SHDIAG, 2); 1327c478bd9Sstevel@tonic-gate errno = oerrno; 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate tstostr(chbuf, s); 1357c478bd9Sstevel@tonic-gate perror(chbuf); 1367c478bd9Sstevel@tonic-gate error(NULL); /* To exit or unwind */ 1377c478bd9Sstevel@tonic-gate } 1387c478bd9Sstevel@tonic-gate 139*6c02b4a4Smuffin void 140*6c02b4a4Smuffin bferr(char *cp) 1417c478bd9Sstevel@tonic-gate { 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate flush(); 1447c478bd9Sstevel@tonic-gate haderr = 1; 1457c478bd9Sstevel@tonic-gate if( bname) printf("%t: ", bname); 1467c478bd9Sstevel@tonic-gate error("%s", gettext(cp)); 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate 1497c478bd9Sstevel@tonic-gate /* 1507c478bd9Sstevel@tonic-gate * The parser and scanner set up errors for later by calling seterr, 1517c478bd9Sstevel@tonic-gate * which sets the variable err as a side effect; later to be tested, 1527c478bd9Sstevel@tonic-gate * e.g. in process. 1537c478bd9Sstevel@tonic-gate */ 154*6c02b4a4Smuffin void 155*6c02b4a4Smuffin seterr(char *s) 1567c478bd9Sstevel@tonic-gate { 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate if (err == 0) 1597c478bd9Sstevel@tonic-gate err = s, errspl = 0; 1607c478bd9Sstevel@tonic-gate } 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate /* Set err to a splice of cp and dp, to be freed later in error() */ 163*6c02b4a4Smuffin void 164*6c02b4a4Smuffin seterr2(tchar *cp, char *dp) 1657c478bd9Sstevel@tonic-gate { 1667c478bd9Sstevel@tonic-gate char chbuf[BUFSIZ]; 1677c478bd9Sstevel@tonic-gate char *gdp; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate if (err) 1707c478bd9Sstevel@tonic-gate return; 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* Concatinate cp and dp in the allocated space. */ 1737c478bd9Sstevel@tonic-gate tstostr(chbuf, cp); 1747c478bd9Sstevel@tonic-gate gdp = gettext(dp); 1757c478bd9Sstevel@tonic-gate err = (char *)xalloc(strlen(chbuf)+strlen(gdp)+1); 1767c478bd9Sstevel@tonic-gate strcpy(err, chbuf); 1777c478bd9Sstevel@tonic-gate strcat(err, gdp); 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate errspl++;/* Remember to xfree(err). */ 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* Set err to a splice of cp with a string form of character d */ 183*6c02b4a4Smuffin void 184*6c02b4a4Smuffin seterrc(char *cp, tchar d) 1857c478bd9Sstevel@tonic-gate { 1867c478bd9Sstevel@tonic-gate char chbuf[MB_LEN_MAX+1]; 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* don't overwrite an existing error message */ 1897c478bd9Sstevel@tonic-gate if (err) 1907c478bd9Sstevel@tonic-gate return; 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate #ifdef MBCHAR 1937c478bd9Sstevel@tonic-gate { 1947c478bd9Sstevel@tonic-gate wchar_t wcd=(wchar_t)(d&TRIM); 1957c478bd9Sstevel@tonic-gate int i; 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate i = wctomb(chbuf, wcd); /* chbuf holds d in multibyte representation. */ 1987c478bd9Sstevel@tonic-gate chbuf[(i>0)?i:0] = (char) 0; 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate #else 2017c478bd9Sstevel@tonic-gate chbuf[0]=(char)(d&TRIM); chbuf[1]=(char)0; 2027c478bd9Sstevel@tonic-gate #endif 2037c478bd9Sstevel@tonic-gate 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate /* Concatinate cp and d in the allocated space. */ 2067c478bd9Sstevel@tonic-gate err = (char *)xalloc(strlen(cp)+strlen(chbuf)+1); 2077c478bd9Sstevel@tonic-gate strcpy(err, cp); 2087c478bd9Sstevel@tonic-gate strcat(err, chbuf); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate errspl++; /* Remember to xfree(err). */ 2117c478bd9Sstevel@tonic-gate } 212