ash.c 294 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * ash shell port for busybox
  4. *
  5. * This code is derived from software contributed to Berkeley by
  6. * Kenneth Almquist.
  7. *
  8. * Original BSD copyright notice is retained at the end of this file.
  9. *
  10. * Copyright (c) 1989, 1991, 1993, 1994
  11. * The Regents of the University of California. All rights reserved.
  12. *
  13. * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
  14. * was re-ported from NetBSD and debianized.
  15. *
  16. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  17. */
  18. /*
  19. * The following should be set to reflect the type of system you have:
  20. * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
  21. * define SYSV if you are running under System V.
  22. * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
  23. * define DEBUG=2 to compile in and turn on debugging.
  24. *
  25. * When debugging is on (DEBUG is 1 and "set -o debug" was executed),
  26. * debugging info will be written to ./trace and a quit signal
  27. * will generate a core dump.
  28. */
  29. #define DEBUG 0
  30. /* Tweak debug output verbosity here */
  31. #define DEBUG_TIME 0
  32. #define DEBUG_PID 1
  33. #define DEBUG_SIG 1
  34. #define PROFILE 0
  35. #define JOBS ENABLE_ASH_JOB_CONTROL
  36. #include <paths.h>
  37. #include <setjmp.h>
  38. #include <fnmatch.h>
  39. #include <sys/times.h>
  40. #include <sys/utsname.h> /* for setting $HOSTNAME */
  41. #include "busybox.h" /* for applet_names */
  42. #include "unicode.h"
  43. #include "shell_common.h"
  44. #if ENABLE_SH_MATH_SUPPORT
  45. # include "math.h"
  46. #endif
  47. #if ENABLE_ASH_RANDOM_SUPPORT
  48. # include "random.h"
  49. #else
  50. # define CLEAR_RANDOM_T(rnd) ((void)0)
  51. #endif
  52. #include "NUM_APPLETS.h"
  53. #if NUM_APPLETS == 1
  54. /* STANDALONE does not make sense, and won't compile */
  55. # undef CONFIG_FEATURE_SH_STANDALONE
  56. # undef ENABLE_FEATURE_SH_STANDALONE
  57. # undef IF_FEATURE_SH_STANDALONE
  58. # undef IF_NOT_FEATURE_SH_STANDALONE
  59. # define ENABLE_FEATURE_SH_STANDALONE 0
  60. # define IF_FEATURE_SH_STANDALONE(...)
  61. # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
  62. #endif
  63. #ifndef PIPE_BUF
  64. # define PIPE_BUF 4096 /* amount of buffering in a pipe */
  65. #endif
  66. #if !BB_MMU
  67. # error "Do not even bother, ash will not run on NOMMU machine"
  68. #endif
  69. //config:config ASH
  70. //config: bool "ash"
  71. //config: default y
  72. //config: depends on !NOMMU
  73. //config: help
  74. //config: Tha 'ash' shell adds about 60k in the default configuration and is
  75. //config: the most complete and most pedantically correct shell included with
  76. //config: busybox. This shell is actually a derivative of the Debian 'dash'
  77. //config: shell (by Herbert Xu), which was created by porting the 'ash' shell
  78. //config: (written by Kenneth Almquist) from NetBSD.
  79. //config:
  80. //config:config ASH_BASH_COMPAT
  81. //config: bool "bash-compatible extensions"
  82. //config: default y
  83. //config: depends on ASH
  84. //config: help
  85. //config: Enable bash-compatible extensions.
  86. //config:
  87. //config:config ASH_IDLE_TIMEOUT
  88. //config: bool "Idle timeout variable"
  89. //config: default n
  90. //config: depends on ASH
  91. //config: help
  92. //config: Enables bash-like auto-logout after $TMOUT seconds of idle time.
  93. //config:
  94. //config:config ASH_JOB_CONTROL
  95. //config: bool "Job control"
  96. //config: default y
  97. //config: depends on ASH
  98. //config: help
  99. //config: Enable job control in the ash shell.
  100. //config:
  101. //config:config ASH_ALIAS
  102. //config: bool "Alias support"
  103. //config: default y
  104. //config: depends on ASH
  105. //config: help
  106. //config: Enable alias support in the ash shell.
  107. //config:
  108. //config:config ASH_GETOPTS
  109. //config: bool "Builtin getopt to parse positional parameters"
  110. //config: default y
  111. //config: depends on ASH
  112. //config: help
  113. //config: Enable support for getopts builtin in ash.
  114. //config:
  115. //config:config ASH_BUILTIN_ECHO
  116. //config: bool "Builtin version of 'echo'"
  117. //config: default y
  118. //config: depends on ASH
  119. //config: help
  120. //config: Enable support for echo builtin in ash.
  121. //config:
  122. //config:config ASH_BUILTIN_PRINTF
  123. //config: bool "Builtin version of 'printf'"
  124. //config: default y
  125. //config: depends on ASH
  126. //config: help
  127. //config: Enable support for printf builtin in ash.
  128. //config:
  129. //config:config ASH_BUILTIN_TEST
  130. //config: bool "Builtin version of 'test'"
  131. //config: default y
  132. //config: depends on ASH
  133. //config: help
  134. //config: Enable support for test builtin in ash.
  135. //config:
  136. //config:config ASH_HELP
  137. //config: bool "help builtin"
  138. //config: default y
  139. //config: depends on ASH
  140. //config: help
  141. //config: Enable help builtin in ash.
  142. //config:
  143. //config:config ASH_CMDCMD
  144. //config: bool "'command' command to override shell builtins"
  145. //config: default y
  146. //config: depends on ASH
  147. //config: help
  148. //config: Enable support for the ash 'command' builtin, which allows
  149. //config: you to run the specified command with the specified arguments,
  150. //config: even when there is an ash builtin command with the same name.
  151. //config:
  152. //config:config ASH_MAIL
  153. //config: bool "Check for new mail on interactive shells"
  154. //config: default n
  155. //config: depends on ASH
  156. //config: help
  157. //config: Enable "check for new mail" function in the ash shell.
  158. //config:
  159. //config:config ASH_OPTIMIZE_FOR_SIZE
  160. //config: bool "Optimize for size instead of speed"
  161. //config: default y
  162. //config: depends on ASH
  163. //config: help
  164. //config: Compile ash for reduced size at the price of speed.
  165. //config:
  166. //config:config ASH_RANDOM_SUPPORT
  167. //config: bool "Pseudorandom generator and $RANDOM variable"
  168. //config: default y
  169. //config: depends on ASH
  170. //config: help
  171. //config: Enable pseudorandom generator and dynamic variable "$RANDOM".
  172. //config: Each read of "$RANDOM" will generate a new pseudorandom value.
  173. //config: You can reset the generator by using a specified start value.
  174. //config: After "unset RANDOM" the generator will switch off and this
  175. //config: variable will no longer have special treatment.
  176. //config:
  177. //config:config ASH_EXPAND_PRMT
  178. //config: bool "Expand prompt string"
  179. //config: default y
  180. //config: depends on ASH
  181. //config: help
  182. //config: "PS#" may contain volatile content, such as backquote commands.
  183. //config: This option recreates the prompt string from the environment
  184. //config: variable each time it is displayed.
  185. //config:
  186. //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
  187. //applet:IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, sh))
  188. //applet:IF_FEATURE_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, bash))
  189. //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
  190. //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
  191. /* ============ Hash table sizes. Configurable. */
  192. #define VTABSIZE 39
  193. #define ATABSIZE 39
  194. #define CMDTABLESIZE 31 /* should be prime */
  195. /* ============ Shell options */
  196. static const char *const optletters_optnames[] = {
  197. "e" "errexit",
  198. "f" "noglob",
  199. "I" "ignoreeof",
  200. "i" "interactive",
  201. "m" "monitor",
  202. "n" "noexec",
  203. "s" "stdin",
  204. "x" "xtrace",
  205. "v" "verbose",
  206. "C" "noclobber",
  207. "a" "allexport",
  208. "b" "notify",
  209. "u" "nounset",
  210. "\0" "vi"
  211. #if ENABLE_ASH_BASH_COMPAT
  212. ,"\0" "pipefail"
  213. #endif
  214. #if DEBUG
  215. ,"\0" "nolog"
  216. ,"\0" "debug"
  217. #endif
  218. };
  219. #define optletters(n) optletters_optnames[n][0]
  220. #define optnames(n) (optletters_optnames[n] + 1)
  221. enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
  222. /* ============ Misc data */
  223. #define msg_illnum "Illegal number: %s"
  224. /*
  225. * We enclose jmp_buf in a structure so that we can declare pointers to
  226. * jump locations. The global variable handler contains the location to
  227. * jump to when an exception occurs, and the global variable exception_type
  228. * contains a code identifying the exception. To implement nested
  229. * exception handlers, the user should save the value of handler on entry
  230. * to an inner scope, set handler to point to a jmploc structure for the
  231. * inner scope, and restore handler on exit from the scope.
  232. */
  233. struct jmploc {
  234. jmp_buf loc;
  235. };
  236. struct globals_misc {
  237. /* pid of main shell */
  238. int rootpid;
  239. /* shell level: 0 for the main shell, 1 for its children, and so on */
  240. int shlvl;
  241. #define rootshell (!shlvl)
  242. char *minusc; /* argument to -c option */
  243. char *curdir; // = nullstr; /* current working directory */
  244. char *physdir; // = nullstr; /* physical working directory */
  245. char *arg0; /* value of $0 */
  246. struct jmploc *exception_handler;
  247. volatile int suppress_int; /* counter */
  248. volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
  249. /* last pending signal */
  250. volatile /*sig_atomic_t*/ smallint pending_sig;
  251. smallint exception_type; /* kind of exception (0..5) */
  252. /* exceptions */
  253. #define EXINT 0 /* SIGINT received */
  254. #define EXERROR 1 /* a generic error */
  255. #define EXSHELLPROC 2 /* execute a shell procedure */
  256. #define EXEXEC 3 /* command execution failed */
  257. #define EXEXIT 4 /* exit the shell */
  258. #define EXSIG 5 /* trapped signal in wait(1) */
  259. smallint isloginsh;
  260. char nullstr[1]; /* zero length string */
  261. char optlist[NOPTS];
  262. #define eflag optlist[0]
  263. #define fflag optlist[1]
  264. #define Iflag optlist[2]
  265. #define iflag optlist[3]
  266. #define mflag optlist[4]
  267. #define nflag optlist[5]
  268. #define sflag optlist[6]
  269. #define xflag optlist[7]
  270. #define vflag optlist[8]
  271. #define Cflag optlist[9]
  272. #define aflag optlist[10]
  273. #define bflag optlist[11]
  274. #define uflag optlist[12]
  275. #define viflag optlist[13]
  276. #if ENABLE_ASH_BASH_COMPAT
  277. # define pipefail optlist[14]
  278. #else
  279. # define pipefail 0
  280. #endif
  281. #if DEBUG
  282. # define nolog optlist[14 + ENABLE_ASH_BASH_COMPAT]
  283. # define debug optlist[15 + ENABLE_ASH_BASH_COMPAT]
  284. #endif
  285. /* trap handler commands */
  286. /*
  287. * Sigmode records the current value of the signal handlers for the various
  288. * modes. A value of zero means that the current handler is not known.
  289. * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
  290. */
  291. char sigmode[NSIG - 1];
  292. #define S_DFL 1 /* default signal handling (SIG_DFL) */
  293. #define S_CATCH 2 /* signal is caught */
  294. #define S_IGN 3 /* signal is ignored (SIG_IGN) */
  295. #define S_HARD_IGN 4 /* signal is ignored permenantly */
  296. /* indicates specified signal received */
  297. uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
  298. uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
  299. char *trap[NSIG];
  300. char **trap_ptr; /* used only by "trap hack" */
  301. /* Rarely referenced stuff */
  302. #if ENABLE_ASH_RANDOM_SUPPORT
  303. random_t random_gen;
  304. #endif
  305. pid_t backgndpid; /* pid of last background process */
  306. smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */
  307. };
  308. extern struct globals_misc *const ash_ptr_to_globals_misc;
  309. #define G_misc (*ash_ptr_to_globals_misc)
  310. #define rootpid (G_misc.rootpid )
  311. #define shlvl (G_misc.shlvl )
  312. #define minusc (G_misc.minusc )
  313. #define curdir (G_misc.curdir )
  314. #define physdir (G_misc.physdir )
  315. #define arg0 (G_misc.arg0 )
  316. #define exception_handler (G_misc.exception_handler)
  317. #define exception_type (G_misc.exception_type )
  318. #define suppress_int (G_misc.suppress_int )
  319. #define pending_int (G_misc.pending_int )
  320. #define pending_sig (G_misc.pending_sig )
  321. #define isloginsh (G_misc.isloginsh )
  322. #define nullstr (G_misc.nullstr )
  323. #define optlist (G_misc.optlist )
  324. #define sigmode (G_misc.sigmode )
  325. #define gotsig (G_misc.gotsig )
  326. #define may_have_traps (G_misc.may_have_traps )
  327. #define trap (G_misc.trap )
  328. #define trap_ptr (G_misc.trap_ptr )
  329. #define random_gen (G_misc.random_gen )
  330. #define backgndpid (G_misc.backgndpid )
  331. #define job_warning (G_misc.job_warning)
  332. #define INIT_G_misc() do { \
  333. (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
  334. barrier(); \
  335. curdir = nullstr; \
  336. physdir = nullstr; \
  337. trap_ptr = trap; \
  338. } while (0)
  339. /* ============ DEBUG */
  340. #if DEBUG
  341. static void trace_printf(const char *fmt, ...);
  342. static void trace_vprintf(const char *fmt, va_list va);
  343. # define TRACE(param) trace_printf param
  344. # define TRACEV(param) trace_vprintf param
  345. # define close(fd) do { \
  346. int dfd = (fd); \
  347. if (close(dfd) < 0) \
  348. bb_error_msg("bug on %d: closing %d(0x%x)", \
  349. __LINE__, dfd, dfd); \
  350. } while (0)
  351. #else
  352. # define TRACE(param)
  353. # define TRACEV(param)
  354. #endif
  355. /* ============ Utility functions */
  356. #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
  357. #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
  358. #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
  359. static int isdigit_str9(const char *str)
  360. {
  361. int maxlen = 9 + 1; /* max 9 digits: 999999999 */
  362. while (--maxlen && isdigit(*str))
  363. str++;
  364. return (*str == '\0');
  365. }
  366. static const char *var_end(const char *var)
  367. {
  368. while (*var)
  369. if (*var++ == '=')
  370. break;
  371. return var;
  372. }
  373. /* ============ Interrupts / exceptions */
  374. static void exitshell(void) NORETURN;
  375. /*
  376. * These macros allow the user to suspend the handling of interrupt signals
  377. * over a period of time. This is similar to SIGHOLD or to sigblock, but
  378. * much more efficient and portable. (But hacking the kernel is so much
  379. * more fun than worrying about efficiency and portability. :-))
  380. */
  381. #define INT_OFF do { \
  382. suppress_int++; \
  383. xbarrier(); \
  384. } while (0)
  385. /*
  386. * Called to raise an exception. Since C doesn't include exceptions, we
  387. * just do a longjmp to the exception handler. The type of exception is
  388. * stored in the global variable "exception_type".
  389. */
  390. static void raise_exception(int) NORETURN;
  391. static void
  392. raise_exception(int e)
  393. {
  394. #if DEBUG
  395. if (exception_handler == NULL)
  396. abort();
  397. #endif
  398. INT_OFF;
  399. exception_type = e;
  400. longjmp(exception_handler->loc, 1);
  401. }
  402. #if DEBUG
  403. #define raise_exception(e) do { \
  404. TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
  405. raise_exception(e); \
  406. } while (0)
  407. #endif
  408. /*
  409. * Called from trap.c when a SIGINT is received. (If the user specifies
  410. * that SIGINT is to be trapped or ignored using the trap builtin, then
  411. * this routine is not called.) Suppressint is nonzero when interrupts
  412. * are held using the INT_OFF macro. (The test for iflag is just
  413. * defensive programming.)
  414. */
  415. static void raise_interrupt(void) NORETURN;
  416. static void
  417. raise_interrupt(void)
  418. {
  419. int ex_type;
  420. pending_int = 0;
  421. /* Signal is not automatically unmasked after it is raised,
  422. * do it ourself - unmask all signals */
  423. sigprocmask_allsigs(SIG_UNBLOCK);
  424. /* pending_sig = 0; - now done in signal_handler() */
  425. ex_type = EXSIG;
  426. if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
  427. if (!(rootshell && iflag)) {
  428. /* Kill ourself with SIGINT */
  429. signal(SIGINT, SIG_DFL);
  430. raise(SIGINT);
  431. }
  432. ex_type = EXINT;
  433. }
  434. raise_exception(ex_type);
  435. /* NOTREACHED */
  436. }
  437. #if DEBUG
  438. #define raise_interrupt() do { \
  439. TRACE(("raising interrupt on line %d\n", __LINE__)); \
  440. raise_interrupt(); \
  441. } while (0)
  442. #endif
  443. static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
  444. int_on(void)
  445. {
  446. xbarrier();
  447. if (--suppress_int == 0 && pending_int) {
  448. raise_interrupt();
  449. }
  450. }
  451. #define INT_ON int_on()
  452. static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
  453. force_int_on(void)
  454. {
  455. xbarrier();
  456. suppress_int = 0;
  457. if (pending_int)
  458. raise_interrupt();
  459. }
  460. #define FORCE_INT_ON force_int_on()
  461. #define SAVE_INT(v) ((v) = suppress_int)
  462. #define RESTORE_INT(v) do { \
  463. xbarrier(); \
  464. suppress_int = (v); \
  465. if (suppress_int == 0 && pending_int) \
  466. raise_interrupt(); \
  467. } while (0)
  468. /* ============ Stdout/stderr output */
  469. static void
  470. outstr(const char *p, FILE *file)
  471. {
  472. INT_OFF;
  473. fputs(p, file);
  474. INT_ON;
  475. }
  476. static void
  477. flush_stdout_stderr(void)
  478. {
  479. INT_OFF;
  480. fflush_all();
  481. INT_ON;
  482. }
  483. static void
  484. outcslow(int c, FILE *dest)
  485. {
  486. INT_OFF;
  487. putc(c, dest);
  488. fflush(dest);
  489. INT_ON;
  490. }
  491. static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
  492. static int
  493. out1fmt(const char *fmt, ...)
  494. {
  495. va_list ap;
  496. int r;
  497. INT_OFF;
  498. va_start(ap, fmt);
  499. r = vprintf(fmt, ap);
  500. va_end(ap);
  501. INT_ON;
  502. return r;
  503. }
  504. static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
  505. static int
  506. fmtstr(char *outbuf, size_t length, const char *fmt, ...)
  507. {
  508. va_list ap;
  509. int ret;
  510. va_start(ap, fmt);
  511. INT_OFF;
  512. ret = vsnprintf(outbuf, length, fmt, ap);
  513. va_end(ap);
  514. INT_ON;
  515. return ret;
  516. }
  517. static void
  518. out1str(const char *p)
  519. {
  520. outstr(p, stdout);
  521. }
  522. static void
  523. out2str(const char *p)
  524. {
  525. outstr(p, stderr);
  526. flush_stdout_stderr();
  527. }
  528. /* ============ Parser structures */
  529. /* control characters in argument strings */
  530. #define CTL_FIRST CTLESC
  531. #define CTLESC ((unsigned char)'\201') /* escape next character */
  532. #define CTLVAR ((unsigned char)'\202') /* variable defn */
  533. #define CTLENDVAR ((unsigned char)'\203')
  534. #define CTLBACKQ ((unsigned char)'\204')
  535. #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
  536. /* CTLBACKQ | CTLQUOTE == '\205' */
  537. #define CTLARI ((unsigned char)'\206') /* arithmetic expression */
  538. #define CTLENDARI ((unsigned char)'\207')
  539. #define CTLQUOTEMARK ((unsigned char)'\210')
  540. #define CTL_LAST CTLQUOTEMARK
  541. /* variable substitution byte (follows CTLVAR) */
  542. #define VSTYPE 0x0f /* type of variable substitution */
  543. #define VSNUL 0x10 /* colon--treat the empty string as unset */
  544. #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
  545. /* values of VSTYPE field */
  546. #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
  547. #define VSMINUS 0x2 /* ${var-text} */
  548. #define VSPLUS 0x3 /* ${var+text} */
  549. #define VSQUESTION 0x4 /* ${var?message} */
  550. #define VSASSIGN 0x5 /* ${var=text} */
  551. #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
  552. #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
  553. #define VSTRIMLEFT 0x8 /* ${var#pattern} */
  554. #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
  555. #define VSLENGTH 0xa /* ${#var} */
  556. #if ENABLE_ASH_BASH_COMPAT
  557. #define VSSUBSTR 0xc /* ${var:position:length} */
  558. #define VSREPLACE 0xd /* ${var/pattern/replacement} */
  559. #define VSREPLACEALL 0xe /* ${var//pattern/replacement} */
  560. #endif
  561. static const char dolatstr[] ALIGN1 = {
  562. CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
  563. };
  564. #define NCMD 0
  565. #define NPIPE 1
  566. #define NREDIR 2
  567. #define NBACKGND 3
  568. #define NSUBSHELL 4
  569. #define NAND 5
  570. #define NOR 6
  571. #define NSEMI 7
  572. #define NIF 8
  573. #define NWHILE 9
  574. #define NUNTIL 10
  575. #define NFOR 11
  576. #define NCASE 12
  577. #define NCLIST 13
  578. #define NDEFUN 14
  579. #define NARG 15
  580. #define NTO 16
  581. #if ENABLE_ASH_BASH_COMPAT
  582. #define NTO2 17
  583. #endif
  584. #define NCLOBBER 18
  585. #define NFROM 19
  586. #define NFROMTO 20
  587. #define NAPPEND 21
  588. #define NTOFD 22
  589. #define NFROMFD 23
  590. #define NHERE 24
  591. #define NXHERE 25
  592. #define NNOT 26
  593. #define N_NUMBER 27
  594. union node;
  595. struct ncmd {
  596. smallint type; /* Nxxxx */
  597. union node *assign;
  598. union node *args;
  599. union node *redirect;
  600. };
  601. struct npipe {
  602. smallint type;
  603. smallint pipe_backgnd;
  604. struct nodelist *cmdlist;
  605. };
  606. struct nredir {
  607. smallint type;
  608. union node *n;
  609. union node *redirect;
  610. };
  611. struct nbinary {
  612. smallint type;
  613. union node *ch1;
  614. union node *ch2;
  615. };
  616. struct nif {
  617. smallint type;
  618. union node *test;
  619. union node *ifpart;
  620. union node *elsepart;
  621. };
  622. struct nfor {
  623. smallint type;
  624. union node *args;
  625. union node *body;
  626. char *var;
  627. };
  628. struct ncase {
  629. smallint type;
  630. union node *expr;
  631. union node *cases;
  632. };
  633. struct nclist {
  634. smallint type;
  635. union node *next;
  636. union node *pattern;
  637. union node *body;
  638. };
  639. struct narg {
  640. smallint type;
  641. union node *next;
  642. char *text;
  643. struct nodelist *backquote;
  644. };
  645. /* nfile and ndup layout must match!
  646. * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
  647. * that it is actually NTO2 (>&file), and change its type.
  648. */
  649. struct nfile {
  650. smallint type;
  651. union node *next;
  652. int fd;
  653. int _unused_dupfd;
  654. union node *fname;
  655. char *expfname;
  656. };
  657. struct ndup {
  658. smallint type;
  659. union node *next;
  660. int fd;
  661. int dupfd;
  662. union node *vname;
  663. char *_unused_expfname;
  664. };
  665. struct nhere {
  666. smallint type;
  667. union node *next;
  668. int fd;
  669. union node *doc;
  670. };
  671. struct nnot {
  672. smallint type;
  673. union node *com;
  674. };
  675. union node {
  676. smallint type;
  677. struct ncmd ncmd;
  678. struct npipe npipe;
  679. struct nredir nredir;
  680. struct nbinary nbinary;
  681. struct nif nif;
  682. struct nfor nfor;
  683. struct ncase ncase;
  684. struct nclist nclist;
  685. struct narg narg;
  686. struct nfile nfile;
  687. struct ndup ndup;
  688. struct nhere nhere;
  689. struct nnot nnot;
  690. };
  691. /*
  692. * NODE_EOF is returned by parsecmd when it encounters an end of file.
  693. * It must be distinct from NULL.
  694. */
  695. #define NODE_EOF ((union node *) -1L)
  696. struct nodelist {
  697. struct nodelist *next;
  698. union node *n;
  699. };
  700. struct funcnode {
  701. int count;
  702. union node n;
  703. };
  704. /*
  705. * Free a parse tree.
  706. */
  707. static void
  708. freefunc(struct funcnode *f)
  709. {
  710. if (f && --f->count < 0)
  711. free(f);
  712. }
  713. /* ============ Debugging output */
  714. #if DEBUG
  715. static FILE *tracefile;
  716. static void
  717. trace_printf(const char *fmt, ...)
  718. {
  719. va_list va;
  720. if (debug != 1)
  721. return;
  722. if (DEBUG_TIME)
  723. fprintf(tracefile, "%u ", (int) time(NULL));
  724. if (DEBUG_PID)
  725. fprintf(tracefile, "[%u] ", (int) getpid());
  726. if (DEBUG_SIG)
  727. fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
  728. va_start(va, fmt);
  729. vfprintf(tracefile, fmt, va);
  730. va_end(va);
  731. }
  732. static void
  733. trace_vprintf(const char *fmt, va_list va)
  734. {
  735. if (debug != 1)
  736. return;
  737. if (DEBUG_TIME)
  738. fprintf(tracefile, "%u ", (int) time(NULL));
  739. if (DEBUG_PID)
  740. fprintf(tracefile, "[%u] ", (int) getpid());
  741. if (DEBUG_SIG)
  742. fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
  743. vfprintf(tracefile, fmt, va);
  744. }
  745. static void
  746. trace_puts(const char *s)
  747. {
  748. if (debug != 1)
  749. return;
  750. fputs(s, tracefile);
  751. }
  752. static void
  753. trace_puts_quoted(char *s)
  754. {
  755. char *p;
  756. char c;
  757. if (debug != 1)
  758. return;
  759. putc('"', tracefile);
  760. for (p = s; *p; p++) {
  761. switch ((unsigned char)*p) {
  762. case '\n': c = 'n'; goto backslash;
  763. case '\t': c = 't'; goto backslash;
  764. case '\r': c = 'r'; goto backslash;
  765. case '\"': c = '\"'; goto backslash;
  766. case '\\': c = '\\'; goto backslash;
  767. case CTLESC: c = 'e'; goto backslash;
  768. case CTLVAR: c = 'v'; goto backslash;
  769. case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
  770. case CTLBACKQ: c = 'q'; goto backslash;
  771. case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
  772. backslash:
  773. putc('\\', tracefile);
  774. putc(c, tracefile);
  775. break;
  776. default:
  777. if (*p >= ' ' && *p <= '~')
  778. putc(*p, tracefile);
  779. else {
  780. putc('\\', tracefile);
  781. putc((*p >> 6) & 03, tracefile);
  782. putc((*p >> 3) & 07, tracefile);
  783. putc(*p & 07, tracefile);
  784. }
  785. break;
  786. }
  787. }
  788. putc('"', tracefile);
  789. }
  790. static void
  791. trace_puts_args(char **ap)
  792. {
  793. if (debug != 1)
  794. return;
  795. if (!*ap)
  796. return;
  797. while (1) {
  798. trace_puts_quoted(*ap);
  799. if (!*++ap) {
  800. putc('\n', tracefile);
  801. break;
  802. }
  803. putc(' ', tracefile);
  804. }
  805. }
  806. static void
  807. opentrace(void)
  808. {
  809. char s[100];
  810. #ifdef O_APPEND
  811. int flags;
  812. #endif
  813. if (debug != 1) {
  814. if (tracefile)
  815. fflush(tracefile);
  816. /* leave open because libedit might be using it */
  817. return;
  818. }
  819. strcpy(s, "./trace");
  820. if (tracefile) {
  821. if (!freopen(s, "a", tracefile)) {
  822. fprintf(stderr, "Can't re-open %s\n", s);
  823. debug = 0;
  824. return;
  825. }
  826. } else {
  827. tracefile = fopen(s, "a");
  828. if (tracefile == NULL) {
  829. fprintf(stderr, "Can't open %s\n", s);
  830. debug = 0;
  831. return;
  832. }
  833. }
  834. #ifdef O_APPEND
  835. flags = fcntl(fileno(tracefile), F_GETFL);
  836. if (flags >= 0)
  837. fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
  838. #endif
  839. setlinebuf(tracefile);
  840. fputs("\nTracing started.\n", tracefile);
  841. }
  842. static void
  843. indent(int amount, char *pfx, FILE *fp)
  844. {
  845. int i;
  846. for (i = 0; i < amount; i++) {
  847. if (pfx && i == amount - 1)
  848. fputs(pfx, fp);
  849. putc('\t', fp);
  850. }
  851. }
  852. /* little circular references here... */
  853. static void shtree(union node *n, int ind, char *pfx, FILE *fp);
  854. static void
  855. sharg(union node *arg, FILE *fp)
  856. {
  857. char *p;
  858. struct nodelist *bqlist;
  859. unsigned char subtype;
  860. if (arg->type != NARG) {
  861. out1fmt("<node type %d>\n", arg->type);
  862. abort();
  863. }
  864. bqlist = arg->narg.backquote;
  865. for (p = arg->narg.text; *p; p++) {
  866. switch ((unsigned char)*p) {
  867. case CTLESC:
  868. p++;
  869. putc(*p, fp);
  870. break;
  871. case CTLVAR:
  872. putc('$', fp);
  873. putc('{', fp);
  874. subtype = *++p;
  875. if (subtype == VSLENGTH)
  876. putc('#', fp);
  877. while (*p != '=') {
  878. putc(*p, fp);
  879. p++;
  880. }
  881. if (subtype & VSNUL)
  882. putc(':', fp);
  883. switch (subtype & VSTYPE) {
  884. case VSNORMAL:
  885. putc('}', fp);
  886. break;
  887. case VSMINUS:
  888. putc('-', fp);
  889. break;
  890. case VSPLUS:
  891. putc('+', fp);
  892. break;
  893. case VSQUESTION:
  894. putc('?', fp);
  895. break;
  896. case VSASSIGN:
  897. putc('=', fp);
  898. break;
  899. case VSTRIMLEFT:
  900. putc('#', fp);
  901. break;
  902. case VSTRIMLEFTMAX:
  903. putc('#', fp);
  904. putc('#', fp);
  905. break;
  906. case VSTRIMRIGHT:
  907. putc('%', fp);
  908. break;
  909. case VSTRIMRIGHTMAX:
  910. putc('%', fp);
  911. putc('%', fp);
  912. break;
  913. case VSLENGTH:
  914. break;
  915. default:
  916. out1fmt("<subtype %d>", subtype);
  917. }
  918. break;
  919. case CTLENDVAR:
  920. putc('}', fp);
  921. break;
  922. case CTLBACKQ:
  923. case CTLBACKQ|CTLQUOTE:
  924. putc('$', fp);
  925. putc('(', fp);
  926. shtree(bqlist->n, -1, NULL, fp);
  927. putc(')', fp);
  928. break;
  929. default:
  930. putc(*p, fp);
  931. break;
  932. }
  933. }
  934. }
  935. static void
  936. shcmd(union node *cmd, FILE *fp)
  937. {
  938. union node *np;
  939. int first;
  940. const char *s;
  941. int dftfd;
  942. first = 1;
  943. for (np = cmd->ncmd.args; np; np = np->narg.next) {
  944. if (!first)
  945. putc(' ', fp);
  946. sharg(np, fp);
  947. first = 0;
  948. }
  949. for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
  950. if (!first)
  951. putc(' ', fp);
  952. dftfd = 0;
  953. switch (np->nfile.type) {
  954. case NTO: s = ">>"+1; dftfd = 1; break;
  955. case NCLOBBER: s = ">|"; dftfd = 1; break;
  956. case NAPPEND: s = ">>"; dftfd = 1; break;
  957. #if ENABLE_ASH_BASH_COMPAT
  958. case NTO2:
  959. #endif
  960. case NTOFD: s = ">&"; dftfd = 1; break;
  961. case NFROM: s = "<"; break;
  962. case NFROMFD: s = "<&"; break;
  963. case NFROMTO: s = "<>"; break;
  964. default: s = "*error*"; break;
  965. }
  966. if (np->nfile.fd != dftfd)
  967. fprintf(fp, "%d", np->nfile.fd);
  968. fputs(s, fp);
  969. if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
  970. fprintf(fp, "%d", np->ndup.dupfd);
  971. } else {
  972. sharg(np->nfile.fname, fp);
  973. }
  974. first = 0;
  975. }
  976. }
  977. static void
  978. shtree(union node *n, int ind, char *pfx, FILE *fp)
  979. {
  980. struct nodelist *lp;
  981. const char *s;
  982. if (n == NULL)
  983. return;
  984. indent(ind, pfx, fp);
  985. if (n == NODE_EOF) {
  986. fputs("<EOF>", fp);
  987. return;
  988. }
  989. switch (n->type) {
  990. case NSEMI:
  991. s = "; ";
  992. goto binop;
  993. case NAND:
  994. s = " && ";
  995. goto binop;
  996. case NOR:
  997. s = " || ";
  998. binop:
  999. shtree(n->nbinary.ch1, ind, NULL, fp);
  1000. /* if (ind < 0) */
  1001. fputs(s, fp);
  1002. shtree(n->nbinary.ch2, ind, NULL, fp);
  1003. break;
  1004. case NCMD:
  1005. shcmd(n, fp);
  1006. if (ind >= 0)
  1007. putc('\n', fp);
  1008. break;
  1009. case NPIPE:
  1010. for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
  1011. shtree(lp->n, 0, NULL, fp);
  1012. if (lp->next)
  1013. fputs(" | ", fp);
  1014. }
  1015. if (n->npipe.pipe_backgnd)
  1016. fputs(" &", fp);
  1017. if (ind >= 0)
  1018. putc('\n', fp);
  1019. break;
  1020. default:
  1021. fprintf(fp, "<node type %d>", n->type);
  1022. if (ind >= 0)
  1023. putc('\n', fp);
  1024. break;
  1025. }
  1026. }
  1027. static void
  1028. showtree(union node *n)
  1029. {
  1030. trace_puts("showtree called\n");
  1031. shtree(n, 1, NULL, stderr);
  1032. }
  1033. #endif /* DEBUG */
  1034. /* ============ Parser data */
  1035. /*
  1036. * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
  1037. */
  1038. struct strlist {
  1039. struct strlist *next;
  1040. char *text;
  1041. };
  1042. struct alias;
  1043. struct strpush {
  1044. struct strpush *prev; /* preceding string on stack */
  1045. char *prev_string;
  1046. int prev_left_in_line;
  1047. #if ENABLE_ASH_ALIAS
  1048. struct alias *ap; /* if push was associated with an alias */
  1049. #endif
  1050. char *string; /* remember the string since it may change */
  1051. };
  1052. struct parsefile {
  1053. struct parsefile *prev; /* preceding file on stack */
  1054. int linno; /* current line */
  1055. int pf_fd; /* file descriptor (or -1 if string) */
  1056. int left_in_line; /* number of chars left in this line */
  1057. int left_in_buffer; /* number of chars left in this buffer past the line */
  1058. char *next_to_pgetc; /* next char in buffer */
  1059. char *buf; /* input buffer */
  1060. struct strpush *strpush; /* for pushing strings at this level */
  1061. struct strpush basestrpush; /* so pushing one is fast */
  1062. };
  1063. static struct parsefile basepf; /* top level input file */
  1064. static struct parsefile *g_parsefile = &basepf; /* current input file */
  1065. static int startlinno; /* line # where last token started */
  1066. static char *commandname; /* currently executing command */
  1067. static struct strlist *cmdenviron; /* environment for builtin command */
  1068. static uint8_t exitstatus; /* exit status of last command */
  1069. /* ============ Message printing */
  1070. static void
  1071. ash_vmsg(const char *msg, va_list ap)
  1072. {
  1073. fprintf(stderr, "%s: ", arg0);
  1074. if (commandname) {
  1075. if (strcmp(arg0, commandname))
  1076. fprintf(stderr, "%s: ", commandname);
  1077. if (!iflag || g_parsefile->pf_fd > 0)
  1078. fprintf(stderr, "line %d: ", startlinno);
  1079. }
  1080. vfprintf(stderr, msg, ap);
  1081. outcslow('\n', stderr);
  1082. }
  1083. /*
  1084. * Exverror is called to raise the error exception. If the second argument
  1085. * is not NULL then error prints an error message using printf style
  1086. * formatting. It then raises the error exception.
  1087. */
  1088. static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
  1089. static void
  1090. ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
  1091. {
  1092. #if DEBUG
  1093. if (msg) {
  1094. TRACE(("ash_vmsg_and_raise(%d, \"", cond));
  1095. TRACEV((msg, ap));
  1096. TRACE(("\") pid=%d\n", getpid()));
  1097. } else
  1098. TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
  1099. if (msg)
  1100. #endif
  1101. ash_vmsg(msg, ap);
  1102. flush_stdout_stderr();
  1103. raise_exception(cond);
  1104. /* NOTREACHED */
  1105. }
  1106. static void ash_msg_and_raise_error(const char *, ...) NORETURN;
  1107. static void
  1108. ash_msg_and_raise_error(const char *msg, ...)
  1109. {
  1110. va_list ap;
  1111. va_start(ap, msg);
  1112. ash_vmsg_and_raise(EXERROR, msg, ap);
  1113. /* NOTREACHED */
  1114. va_end(ap);
  1115. }
  1116. static void raise_error_syntax(const char *) NORETURN;
  1117. static void
  1118. raise_error_syntax(const char *msg)
  1119. {
  1120. ash_msg_and_raise_error("syntax error: %s", msg);
  1121. /* NOTREACHED */
  1122. }
  1123. static void ash_msg_and_raise(int, const char *, ...) NORETURN;
  1124. static void
  1125. ash_msg_and_raise(int cond, const char *msg, ...)
  1126. {
  1127. va_list ap;
  1128. va_start(ap, msg);
  1129. ash_vmsg_and_raise(cond, msg, ap);
  1130. /* NOTREACHED */
  1131. va_end(ap);
  1132. }
  1133. /*
  1134. * error/warning routines for external builtins
  1135. */
  1136. static void
  1137. ash_msg(const char *fmt, ...)
  1138. {
  1139. va_list ap;
  1140. va_start(ap, fmt);
  1141. ash_vmsg(fmt, ap);
  1142. va_end(ap);
  1143. }
  1144. /*
  1145. * Return a string describing an error. The returned string may be a
  1146. * pointer to a static buffer that will be overwritten on the next call.
  1147. * Action describes the operation that got the error.
  1148. */
  1149. static const char *
  1150. errmsg(int e, const char *em)
  1151. {
  1152. if (e == ENOENT || e == ENOTDIR) {
  1153. return em;
  1154. }
  1155. return strerror(e);
  1156. }
  1157. /* ============ Memory allocation */
  1158. #if 0
  1159. /* I consider these wrappers nearly useless:
  1160. * ok, they return you to nearest exception handler, but
  1161. * how much memory do you leak in the process, making
  1162. * memory starvation worse?
  1163. */
  1164. static void *
  1165. ckrealloc(void * p, size_t nbytes)
  1166. {
  1167. p = realloc(p, nbytes);
  1168. if (!p)
  1169. ash_msg_and_raise_error(bb_msg_memory_exhausted);
  1170. return p;
  1171. }
  1172. static void *
  1173. ckmalloc(size_t nbytes)
  1174. {
  1175. return ckrealloc(NULL, nbytes);
  1176. }
  1177. static void *
  1178. ckzalloc(size_t nbytes)
  1179. {
  1180. return memset(ckmalloc(nbytes), 0, nbytes);
  1181. }
  1182. static char *
  1183. ckstrdup(const char *s)
  1184. {
  1185. char *p = strdup(s);
  1186. if (!p)
  1187. ash_msg_and_raise_error(bb_msg_memory_exhausted);
  1188. return p;
  1189. }
  1190. #else
  1191. /* Using bbox equivalents. They exit if out of memory */
  1192. # define ckrealloc xrealloc
  1193. # define ckmalloc xmalloc
  1194. # define ckzalloc xzalloc
  1195. # define ckstrdup xstrdup
  1196. #endif
  1197. /*
  1198. * It appears that grabstackstr() will barf with such alignments
  1199. * because stalloc() will return a string allocated in a new stackblock.
  1200. */
  1201. #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
  1202. enum {
  1203. /* Most machines require the value returned from malloc to be aligned
  1204. * in some way. The following macro will get this right
  1205. * on many machines. */
  1206. SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
  1207. /* Minimum size of a block */
  1208. MINSIZE = SHELL_ALIGN(504),
  1209. };
  1210. struct stack_block {
  1211. struct stack_block *prev;
  1212. char space[MINSIZE];
  1213. };
  1214. struct stackmark {
  1215. struct stack_block *stackp;
  1216. char *stacknxt;
  1217. size_t stacknleft;
  1218. struct stackmark *marknext;
  1219. };
  1220. struct globals_memstack {
  1221. struct stack_block *g_stackp; // = &stackbase;
  1222. struct stackmark *markp;
  1223. char *g_stacknxt; // = stackbase.space;
  1224. char *sstrend; // = stackbase.space + MINSIZE;
  1225. size_t g_stacknleft; // = MINSIZE;
  1226. int herefd; // = -1;
  1227. struct stack_block stackbase;
  1228. };
  1229. extern struct globals_memstack *const ash_ptr_to_globals_memstack;
  1230. #define G_memstack (*ash_ptr_to_globals_memstack)
  1231. #define g_stackp (G_memstack.g_stackp )
  1232. #define markp (G_memstack.markp )
  1233. #define g_stacknxt (G_memstack.g_stacknxt )
  1234. #define sstrend (G_memstack.sstrend )
  1235. #define g_stacknleft (G_memstack.g_stacknleft)
  1236. #define herefd (G_memstack.herefd )
  1237. #define stackbase (G_memstack.stackbase )
  1238. #define INIT_G_memstack() do { \
  1239. (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
  1240. barrier(); \
  1241. g_stackp = &stackbase; \
  1242. g_stacknxt = stackbase.space; \
  1243. g_stacknleft = MINSIZE; \
  1244. sstrend = stackbase.space + MINSIZE; \
  1245. herefd = -1; \
  1246. } while (0)
  1247. #define stackblock() ((void *)g_stacknxt)
  1248. #define stackblocksize() g_stacknleft
  1249. /*
  1250. * Parse trees for commands are allocated in lifo order, so we use a stack
  1251. * to make this more efficient, and also to avoid all sorts of exception
  1252. * handling code to handle interrupts in the middle of a parse.
  1253. *
  1254. * The size 504 was chosen because the Ultrix malloc handles that size
  1255. * well.
  1256. */
  1257. static void *
  1258. stalloc(size_t nbytes)
  1259. {
  1260. char *p;
  1261. size_t aligned;
  1262. aligned = SHELL_ALIGN(nbytes);
  1263. if (aligned > g_stacknleft) {
  1264. size_t len;
  1265. size_t blocksize;
  1266. struct stack_block *sp;
  1267. blocksize = aligned;
  1268. if (blocksize < MINSIZE)
  1269. blocksize = MINSIZE;
  1270. len = sizeof(struct stack_block) - MINSIZE + blocksize;
  1271. if (len < blocksize)
  1272. ash_msg_and_raise_error(bb_msg_memory_exhausted);
  1273. INT_OFF;
  1274. sp = ckmalloc(len);
  1275. sp->prev = g_stackp;
  1276. g_stacknxt = sp->space;
  1277. g_stacknleft = blocksize;
  1278. sstrend = g_stacknxt + blocksize;
  1279. g_stackp = sp;
  1280. INT_ON;
  1281. }
  1282. p = g_stacknxt;
  1283. g_stacknxt += aligned;
  1284. g_stacknleft -= aligned;
  1285. return p;
  1286. }
  1287. static void *
  1288. stzalloc(size_t nbytes)
  1289. {
  1290. return memset(stalloc(nbytes), 0, nbytes);
  1291. }
  1292. static void
  1293. stunalloc(void *p)
  1294. {
  1295. #if DEBUG
  1296. if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
  1297. write(STDERR_FILENO, "stunalloc\n", 10);
  1298. abort();
  1299. }
  1300. #endif
  1301. g_stacknleft += g_stacknxt - (char *)p;
  1302. g_stacknxt = p;
  1303. }
  1304. /*
  1305. * Like strdup but works with the ash stack.
  1306. */
  1307. static char *
  1308. ststrdup(const char *p)
  1309. {
  1310. size_t len = strlen(p) + 1;
  1311. return memcpy(stalloc(len), p, len);
  1312. }
  1313. static void
  1314. setstackmark(struct stackmark *mark)
  1315. {
  1316. mark->stackp = g_stackp;
  1317. mark->stacknxt = g_stacknxt;
  1318. mark->stacknleft = g_stacknleft;
  1319. mark->marknext = markp;
  1320. markp = mark;
  1321. }
  1322. static void
  1323. popstackmark(struct stackmark *mark)
  1324. {
  1325. struct stack_block *sp;
  1326. if (!mark->stackp)
  1327. return;
  1328. INT_OFF;
  1329. markp = mark->marknext;
  1330. while (g_stackp != mark->stackp) {
  1331. sp = g_stackp;
  1332. g_stackp = sp->prev;
  1333. free(sp);
  1334. }
  1335. g_stacknxt = mark->stacknxt;
  1336. g_stacknleft = mark->stacknleft;
  1337. sstrend = mark->stacknxt + mark->stacknleft;
  1338. INT_ON;
  1339. }
  1340. /*
  1341. * When the parser reads in a string, it wants to stick the string on the
  1342. * stack and only adjust the stack pointer when it knows how big the
  1343. * string is. Stackblock (defined in stack.h) returns a pointer to a block
  1344. * of space on top of the stack and stackblocklen returns the length of
  1345. * this block. Growstackblock will grow this space by at least one byte,
  1346. * possibly moving it (like realloc). Grabstackblock actually allocates the
  1347. * part of the block that has been used.
  1348. */
  1349. static void
  1350. growstackblock(void)
  1351. {
  1352. size_t newlen;
  1353. newlen = g_stacknleft * 2;
  1354. if (newlen < g_stacknleft)
  1355. ash_msg_and_raise_error(bb_msg_memory_exhausted);
  1356. if (newlen < 128)
  1357. newlen += 128;
  1358. if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
  1359. struct stack_block *oldstackp;
  1360. struct stackmark *xmark;
  1361. struct stack_block *sp;
  1362. struct stack_block *prevstackp;
  1363. size_t grosslen;
  1364. INT_OFF;
  1365. oldstackp = g_stackp;
  1366. sp = g_stackp;
  1367. prevstackp = sp->prev;
  1368. grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
  1369. sp = ckrealloc(sp, grosslen);
  1370. sp->prev = prevstackp;
  1371. g_stackp = sp;
  1372. g_stacknxt = sp->space;
  1373. g_stacknleft = newlen;
  1374. sstrend = sp->space + newlen;
  1375. /*
  1376. * Stack marks pointing to the start of the old block
  1377. * must be relocated to point to the new block
  1378. */
  1379. xmark = markp;
  1380. while (xmark != NULL && xmark->stackp == oldstackp) {
  1381. xmark->stackp = g_stackp;
  1382. xmark->stacknxt = g_stacknxt;
  1383. xmark->stacknleft = g_stacknleft;
  1384. xmark = xmark->marknext;
  1385. }
  1386. INT_ON;
  1387. } else {
  1388. char *oldspace = g_stacknxt;
  1389. size_t oldlen = g_stacknleft;
  1390. char *p = stalloc(newlen);
  1391. /* free the space we just allocated */
  1392. g_stacknxt = memcpy(p, oldspace, oldlen);
  1393. g_stacknleft += newlen;
  1394. }
  1395. }
  1396. static void
  1397. grabstackblock(size_t len)
  1398. {
  1399. len = SHELL_ALIGN(len);
  1400. g_stacknxt += len;
  1401. g_stacknleft -= len;
  1402. }
  1403. /*
  1404. * The following routines are somewhat easier to use than the above.
  1405. * The user declares a variable of type STACKSTR, which may be declared
  1406. * to be a register. The macro STARTSTACKSTR initializes things. Then
  1407. * the user uses the macro STPUTC to add characters to the string. In
  1408. * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
  1409. * grown as necessary. When the user is done, she can just leave the
  1410. * string there and refer to it using stackblock(). Or she can allocate
  1411. * the space for it using grabstackstr(). If it is necessary to allow
  1412. * someone else to use the stack temporarily and then continue to grow
  1413. * the string, the user should use grabstack to allocate the space, and
  1414. * then call ungrabstr(p) to return to the previous mode of operation.
  1415. *
  1416. * USTPUTC is like STPUTC except that it doesn't check for overflow.
  1417. * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
  1418. * is space for at least one character.
  1419. */
  1420. static void *
  1421. growstackstr(void)
  1422. {
  1423. size_t len = stackblocksize();
  1424. if (herefd >= 0 && len >= 1024) {
  1425. full_write(herefd, stackblock(), len);
  1426. return stackblock();
  1427. }
  1428. growstackblock();
  1429. return (char *)stackblock() + len;
  1430. }
  1431. /*
  1432. * Called from CHECKSTRSPACE.
  1433. */
  1434. static char *
  1435. makestrspace(size_t newlen, char *p)
  1436. {
  1437. size_t len = p - g_stacknxt;
  1438. size_t size = stackblocksize();
  1439. for (;;) {
  1440. size_t nleft;
  1441. size = stackblocksize();
  1442. nleft = size - len;
  1443. if (nleft >= newlen)
  1444. break;
  1445. growstackblock();
  1446. }
  1447. return (char *)stackblock() + len;
  1448. }
  1449. static char *
  1450. stack_nputstr(const char *s, size_t n, char *p)
  1451. {
  1452. p = makestrspace(n, p);
  1453. p = (char *)memcpy(p, s, n) + n;
  1454. return p;
  1455. }
  1456. static char *
  1457. stack_putstr(const char *s, char *p)
  1458. {
  1459. return stack_nputstr(s, strlen(s), p);
  1460. }
  1461. static char *
  1462. _STPUTC(int c, char *p)
  1463. {
  1464. if (p == sstrend)
  1465. p = growstackstr();
  1466. *p++ = c;
  1467. return p;
  1468. }
  1469. #define STARTSTACKSTR(p) ((p) = stackblock())
  1470. #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
  1471. #define CHECKSTRSPACE(n, p) do { \
  1472. char *q = (p); \
  1473. size_t l = (n); \
  1474. size_t m = sstrend - q; \
  1475. if (l > m) \
  1476. (p) = makestrspace(l, q); \
  1477. } while (0)
  1478. #define USTPUTC(c, p) (*(p)++ = (c))
  1479. #define STACKSTRNUL(p) do { \
  1480. if ((p) == sstrend) \
  1481. (p) = growstackstr(); \
  1482. *(p) = '\0'; \
  1483. } while (0)
  1484. #define STUNPUTC(p) (--(p))
  1485. #define STTOPC(p) ((p)[-1])
  1486. #define STADJUST(amount, p) ((p) += (amount))
  1487. #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
  1488. #define ungrabstackstr(s, p) stunalloc(s)
  1489. #define stackstrend() ((void *)sstrend)
  1490. /* ============ String helpers */
  1491. /*
  1492. * prefix -- see if pfx is a prefix of string.
  1493. */
  1494. static char *
  1495. prefix(const char *string, const char *pfx)
  1496. {
  1497. while (*pfx) {
  1498. if (*pfx++ != *string++)
  1499. return NULL;
  1500. }
  1501. return (char *) string;
  1502. }
  1503. /*
  1504. * Check for a valid number. This should be elsewhere.
  1505. */
  1506. static int
  1507. is_number(const char *p)
  1508. {
  1509. do {
  1510. if (!isdigit(*p))
  1511. return 0;
  1512. } while (*++p != '\0');
  1513. return 1;
  1514. }
  1515. /*
  1516. * Convert a string of digits to an integer, printing an error message on
  1517. * failure.
  1518. */
  1519. static int
  1520. number(const char *s)
  1521. {
  1522. if (!is_number(s))
  1523. ash_msg_and_raise_error(msg_illnum, s);
  1524. return atoi(s);
  1525. }
  1526. /*
  1527. * Produce a possibly single quoted string suitable as input to the shell.
  1528. * The return string is allocated on the stack.
  1529. */
  1530. static char *
  1531. single_quote(const char *s)
  1532. {
  1533. char *p;
  1534. STARTSTACKSTR(p);
  1535. do {
  1536. char *q;
  1537. size_t len;
  1538. len = strchrnul(s, '\'') - s;
  1539. q = p = makestrspace(len + 3, p);
  1540. *q++ = '\'';
  1541. q = (char *)memcpy(q, s, len) + len;
  1542. *q++ = '\'';
  1543. s += len;
  1544. STADJUST(q - p, p);
  1545. if (*s != '\'')
  1546. break;
  1547. len = 0;
  1548. do len++; while (*++s == '\'');
  1549. q = p = makestrspace(len + 3, p);
  1550. *q++ = '"';
  1551. q = (char *)memcpy(q, s - len, len) + len;
  1552. *q++ = '"';
  1553. STADJUST(q - p, p);
  1554. } while (*s);
  1555. USTPUTC('\0', p);
  1556. return stackblock();
  1557. }
  1558. /* ============ nextopt */
  1559. static char **argptr; /* argument list for builtin commands */
  1560. static char *optionarg; /* set by nextopt (like getopt) */
  1561. static char *optptr; /* used by nextopt */
  1562. /*
  1563. * XXX - should get rid of. Have all builtins use getopt(3).
  1564. * The library getopt must have the BSD extension static variable
  1565. * "optreset", otherwise it can't be used within the shell safely.
  1566. *
  1567. * Standard option processing (a la getopt) for builtin routines.
  1568. * The only argument that is passed to nextopt is the option string;
  1569. * the other arguments are unnecessary. It returns the character,
  1570. * or '\0' on end of input.
  1571. */
  1572. static int
  1573. nextopt(const char *optstring)
  1574. {
  1575. char *p;
  1576. const char *q;
  1577. char c;
  1578. p = optptr;
  1579. if (p == NULL || *p == '\0') {
  1580. /* We ate entire "-param", take next one */
  1581. p = *argptr;
  1582. if (p == NULL)
  1583. return '\0';
  1584. if (*p != '-')
  1585. return '\0';
  1586. if (*++p == '\0') /* just "-" ? */
  1587. return '\0';
  1588. argptr++;
  1589. if (LONE_DASH(p)) /* "--" ? */
  1590. return '\0';
  1591. /* p => next "-param" */
  1592. }
  1593. /* p => some option char in the middle of a "-param" */
  1594. c = *p++;
  1595. for (q = optstring; *q != c;) {
  1596. if (*q == '\0')
  1597. ash_msg_and_raise_error("illegal option -%c", c);
  1598. if (*++q == ':')
  1599. q++;
  1600. }
  1601. if (*++q == ':') {
  1602. if (*p == '\0') {
  1603. p = *argptr++;
  1604. if (p == NULL)
  1605. ash_msg_and_raise_error("no arg for -%c option", c);
  1606. }
  1607. optionarg = p;
  1608. p = NULL;
  1609. }
  1610. optptr = p;
  1611. return c;
  1612. }
  1613. /* ============ Shell variables */
  1614. /*
  1615. * The parsefile structure pointed to by the global variable parsefile
  1616. * contains information about the current file being read.
  1617. */
  1618. struct shparam {
  1619. int nparam; /* # of positional parameters (without $0) */
  1620. #if ENABLE_ASH_GETOPTS
  1621. int optind; /* next parameter to be processed by getopts */
  1622. int optoff; /* used by getopts */
  1623. #endif
  1624. unsigned char malloced; /* if parameter list dynamically allocated */
  1625. char **p; /* parameter list */
  1626. };
  1627. /*
  1628. * Free the list of positional parameters.
  1629. */
  1630. static void
  1631. freeparam(volatile struct shparam *param)
  1632. {
  1633. if (param->malloced) {
  1634. char **ap, **ap1;
  1635. ap = ap1 = param->p;
  1636. while (*ap)
  1637. free(*ap++);
  1638. free(ap1);
  1639. }
  1640. }
  1641. #if ENABLE_ASH_GETOPTS
  1642. static void FAST_FUNC getoptsreset(const char *value);
  1643. #endif
  1644. struct var {
  1645. struct var *next; /* next entry in hash list */
  1646. int flags; /* flags are defined above */
  1647. const char *var_text; /* name=value */
  1648. void (*var_func)(const char *) FAST_FUNC; /* function to be called when */
  1649. /* the variable gets set/unset */
  1650. };
  1651. struct localvar {
  1652. struct localvar *next; /* next local variable in list */
  1653. struct var *vp; /* the variable that was made local */
  1654. int flags; /* saved flags */
  1655. const char *text; /* saved text */
  1656. };
  1657. /* flags */
  1658. #define VEXPORT 0x01 /* variable is exported */
  1659. #define VREADONLY 0x02 /* variable cannot be modified */
  1660. #define VSTRFIXED 0x04 /* variable struct is statically allocated */
  1661. #define VTEXTFIXED 0x08 /* text is statically allocated */
  1662. #define VSTACK 0x10 /* text is allocated on the stack */
  1663. #define VUNSET 0x20 /* the variable is not set */
  1664. #define VNOFUNC 0x40 /* don't call the callback function */
  1665. #define VNOSET 0x80 /* do not set variable - just readonly test */
  1666. #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
  1667. #if ENABLE_ASH_RANDOM_SUPPORT
  1668. # define VDYNAMIC 0x200 /* dynamic variable */
  1669. #else
  1670. # define VDYNAMIC 0
  1671. #endif
  1672. /* Need to be before varinit_data[] */
  1673. #if ENABLE_LOCALE_SUPPORT
  1674. static void FAST_FUNC
  1675. change_lc_all(const char *value)
  1676. {
  1677. if (value && *value != '\0')
  1678. setlocale(LC_ALL, value);
  1679. }
  1680. static void FAST_FUNC
  1681. change_lc_ctype(const char *value)
  1682. {
  1683. if (value && *value != '\0')
  1684. setlocale(LC_CTYPE, value);
  1685. }
  1686. #endif
  1687. #if ENABLE_ASH_MAIL
  1688. static void chkmail(void);
  1689. static void changemail(const char *var_value) FAST_FUNC;
  1690. #else
  1691. # define chkmail() ((void)0)
  1692. #endif
  1693. static void changepath(const char *) FAST_FUNC;
  1694. #if ENABLE_ASH_RANDOM_SUPPORT
  1695. static void change_random(const char *) FAST_FUNC;
  1696. #endif
  1697. static const struct {
  1698. int flags;
  1699. const char *var_text;
  1700. void (*var_func)(const char *) FAST_FUNC;
  1701. } varinit_data[] = {
  1702. /*
  1703. * Note: VEXPORT would not work correctly here for NOFORK applets:
  1704. * some environment strings may be constant.
  1705. */
  1706. { VSTRFIXED|VTEXTFIXED , defifsvar , NULL },
  1707. #if ENABLE_ASH_MAIL
  1708. { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL" , changemail },
  1709. { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH" , changemail },
  1710. #endif
  1711. { VSTRFIXED|VTEXTFIXED , bb_PATH_root_path, changepath },
  1712. { VSTRFIXED|VTEXTFIXED , "PS1=$ " , NULL },
  1713. { VSTRFIXED|VTEXTFIXED , "PS2=> " , NULL },
  1714. { VSTRFIXED|VTEXTFIXED , "PS4=+ " , NULL },
  1715. #if ENABLE_ASH_GETOPTS
  1716. { VSTRFIXED|VTEXTFIXED , "OPTIND=1" , getoptsreset },
  1717. #endif
  1718. #if ENABLE_ASH_RANDOM_SUPPORT
  1719. { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
  1720. #endif
  1721. #if ENABLE_LOCALE_SUPPORT
  1722. { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL" , change_lc_all },
  1723. { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE" , change_lc_ctype },
  1724. #endif
  1725. #if ENABLE_FEATURE_EDITING_SAVEHISTORY
  1726. { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE" , NULL },
  1727. #endif
  1728. };
  1729. struct redirtab;
  1730. struct globals_var {
  1731. struct shparam shellparam; /* $@ current positional parameters */
  1732. struct redirtab *redirlist;
  1733. int g_nullredirs;
  1734. int preverrout_fd; /* save fd2 before print debug if xflag is set. */
  1735. struct var *vartab[VTABSIZE];
  1736. struct var varinit[ARRAY_SIZE(varinit_data)];
  1737. };
  1738. extern struct globals_var *const ash_ptr_to_globals_var;
  1739. #define G_var (*ash_ptr_to_globals_var)
  1740. #define shellparam (G_var.shellparam )
  1741. //#define redirlist (G_var.redirlist )
  1742. #define g_nullredirs (G_var.g_nullredirs )
  1743. #define preverrout_fd (G_var.preverrout_fd)
  1744. #define vartab (G_var.vartab )
  1745. #define varinit (G_var.varinit )
  1746. #define INIT_G_var() do { \
  1747. unsigned i; \
  1748. (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
  1749. barrier(); \
  1750. for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
  1751. varinit[i].flags = varinit_data[i].flags; \
  1752. varinit[i].var_text = varinit_data[i].var_text; \
  1753. varinit[i].var_func = varinit_data[i].var_func; \
  1754. } \
  1755. } while (0)
  1756. #define vifs varinit[0]
  1757. #if ENABLE_ASH_MAIL
  1758. # define vmail (&vifs)[1]
  1759. # define vmpath (&vmail)[1]
  1760. # define vpath (&vmpath)[1]
  1761. #else
  1762. # define vpath (&vifs)[1]
  1763. #endif
  1764. #define vps1 (&vpath)[1]
  1765. #define vps2 (&vps1)[1]
  1766. #define vps4 (&vps2)[1]
  1767. #if ENABLE_ASH_GETOPTS
  1768. # define voptind (&vps4)[1]
  1769. # if ENABLE_ASH_RANDOM_SUPPORT
  1770. # define vrandom (&voptind)[1]
  1771. # endif
  1772. #else
  1773. # if ENABLE_ASH_RANDOM_SUPPORT
  1774. # define vrandom (&vps4)[1]
  1775. # endif
  1776. #endif
  1777. /*
  1778. * The following macros access the values of the above variables.
  1779. * They have to skip over the name. They return the null string
  1780. * for unset variables.
  1781. */
  1782. #define ifsval() (vifs.var_text + 4)
  1783. #define ifsset() ((vifs.flags & VUNSET) == 0)
  1784. #if ENABLE_ASH_MAIL
  1785. # define mailval() (vmail.var_text + 5)
  1786. # define mpathval() (vmpath.var_text + 9)
  1787. # define mpathset() ((vmpath.flags & VUNSET) == 0)
  1788. #endif
  1789. #define pathval() (vpath.var_text + 5)
  1790. #define ps1val() (vps1.var_text + 4)
  1791. #define ps2val() (vps2.var_text + 4)
  1792. #define ps4val() (vps4.var_text + 4)
  1793. #if ENABLE_ASH_GETOPTS
  1794. # define optindval() (voptind.var_text + 7)
  1795. #endif
  1796. #if ENABLE_ASH_GETOPTS
  1797. static void FAST_FUNC
  1798. getoptsreset(const char *value)
  1799. {
  1800. shellparam.optind = number(value);
  1801. shellparam.optoff = -1;
  1802. }
  1803. #endif
  1804. /*
  1805. * Compares two strings up to the first = or '\0'. The first
  1806. * string must be terminated by '='; the second may be terminated by
  1807. * either '=' or '\0'.
  1808. */
  1809. static int
  1810. varcmp(const char *p, const char *q)
  1811. {
  1812. int c, d;
  1813. while ((c = *p) == (d = *q)) {
  1814. if (!c || c == '=')
  1815. goto out;
  1816. p++;
  1817. q++;
  1818. }
  1819. if (c == '=')
  1820. c = '\0';
  1821. if (d == '=')
  1822. d = '\0';
  1823. out:
  1824. return c - d;
  1825. }
  1826. /*
  1827. * Find the appropriate entry in the hash table from the name.
  1828. */
  1829. static struct var **
  1830. hashvar(const char *p)
  1831. {
  1832. unsigned hashval;
  1833. hashval = ((unsigned char) *p) << 4;
  1834. while (*p && *p != '=')
  1835. hashval += (unsigned char) *p++;
  1836. return &vartab[hashval % VTABSIZE];
  1837. }
  1838. static int
  1839. vpcmp(const void *a, const void *b)
  1840. {
  1841. return varcmp(*(const char **)a, *(const char **)b);
  1842. }
  1843. /*
  1844. * This routine initializes the builtin variables.
  1845. */
  1846. static void
  1847. initvar(void)
  1848. {
  1849. struct var *vp;
  1850. struct var *end;
  1851. struct var **vpp;
  1852. /*
  1853. * PS1 depends on uid
  1854. */
  1855. #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
  1856. vps1.var_text = "PS1=\\w \\$ ";
  1857. #else
  1858. if (!geteuid())
  1859. vps1.var_text = "PS1=# ";
  1860. #endif
  1861. vp = varinit;
  1862. end = vp + ARRAY_SIZE(varinit);
  1863. do {
  1864. vpp = hashvar(vp->var_text);
  1865. vp->next = *vpp;
  1866. *vpp = vp;
  1867. } while (++vp < end);
  1868. }
  1869. static struct var **
  1870. findvar(struct var **vpp, const char *name)
  1871. {
  1872. for (; *vpp; vpp = &(*vpp)->next) {
  1873. if (varcmp((*vpp)->var_text, name) == 0) {
  1874. break;
  1875. }
  1876. }
  1877. return vpp;
  1878. }
  1879. /*
  1880. * Find the value of a variable. Returns NULL if not set.
  1881. */
  1882. static const char* FAST_FUNC
  1883. lookupvar(const char *name)
  1884. {
  1885. struct var *v;
  1886. v = *findvar(hashvar(name), name);
  1887. if (v) {
  1888. #if ENABLE_ASH_RANDOM_SUPPORT
  1889. /*
  1890. * Dynamic variables are implemented roughly the same way they are
  1891. * in bash. Namely, they're "special" so long as they aren't unset.
  1892. * As soon as they're unset, they're no longer dynamic, and dynamic
  1893. * lookup will no longer happen at that point. -- PFM.
  1894. */
  1895. if (v->flags & VDYNAMIC)
  1896. v->var_func(NULL);
  1897. #endif
  1898. if (!(v->flags & VUNSET))
  1899. return var_end(v->var_text);
  1900. }
  1901. return NULL;
  1902. }
  1903. static void reinit_unicode_for_ash(void)
  1904. {
  1905. /* Unicode support should be activated even if LANG is set
  1906. * _during_ shell execution, not only if it was set when
  1907. * shell was started. Therefore, re-check LANG every time:
  1908. */
  1909. if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
  1910. || ENABLE_UNICODE_USING_LOCALE
  1911. ) {
  1912. const char *s = lookupvar("LC_ALL");
  1913. if (!s) s = lookupvar("LC_CTYPE");
  1914. if (!s) s = lookupvar("LANG");
  1915. reinit_unicode(s);
  1916. }
  1917. }
  1918. /*
  1919. * Search the environment of a builtin command.
  1920. */
  1921. static const char *
  1922. bltinlookup(const char *name)
  1923. {
  1924. struct strlist *sp;
  1925. for (sp = cmdenviron; sp; sp = sp->next) {
  1926. if (varcmp(sp->text, name) == 0)
  1927. return var_end(sp->text);
  1928. }
  1929. return lookupvar(name);
  1930. }
  1931. /*
  1932. * Same as setvar except that the variable and value are passed in
  1933. * the first argument as name=value. Since the first argument will
  1934. * be actually stored in the table, it should not be a string that
  1935. * will go away.
  1936. * Called with interrupts off.
  1937. */
  1938. static void
  1939. setvareq(char *s, int flags)
  1940. {
  1941. struct var *vp, **vpp;
  1942. vpp = hashvar(s);
  1943. flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
  1944. vp = *findvar(vpp, s);
  1945. if (vp) {
  1946. if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
  1947. const char *n;
  1948. if (flags & VNOSAVE)
  1949. free(s);
  1950. n = vp->var_text;
  1951. ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
  1952. }
  1953. if (flags & VNOSET)
  1954. return;
  1955. if (vp->var_func && !(flags & VNOFUNC))
  1956. vp->var_func(var_end(s));
  1957. if (!(vp->flags & (VTEXTFIXED|VSTACK)))
  1958. free((char*)vp->var_text);
  1959. flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
  1960. } else {
  1961. /* variable s is not found */
  1962. if (flags & VNOSET)
  1963. return;
  1964. vp = ckzalloc(sizeof(*vp));
  1965. vp->next = *vpp;
  1966. /*vp->func = NULL; - ckzalloc did it */
  1967. *vpp = vp;
  1968. }
  1969. if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
  1970. s = ckstrdup(s);
  1971. vp->var_text = s;
  1972. vp->flags = flags;
  1973. }
  1974. /*
  1975. * Set the value of a variable. The flags argument is ored with the
  1976. * flags of the variable. If val is NULL, the variable is unset.
  1977. */
  1978. static void
  1979. setvar(const char *name, const char *val, int flags)
  1980. {
  1981. const char *q;
  1982. char *p;
  1983. char *nameeq;
  1984. size_t namelen;
  1985. size_t vallen;
  1986. q = endofname(name);
  1987. p = strchrnul(q, '=');
  1988. namelen = p - name;
  1989. if (!namelen || p != q)
  1990. ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
  1991. vallen = 0;
  1992. if (val == NULL) {
  1993. flags |= VUNSET;
  1994. } else {
  1995. vallen = strlen(val);
  1996. }
  1997. INT_OFF;
  1998. nameeq = ckmalloc(namelen + vallen + 2);
  1999. p = memcpy(nameeq, name, namelen) + namelen;
  2000. if (val) {
  2001. *p++ = '=';
  2002. p = memcpy(p, val, vallen) + vallen;
  2003. }
  2004. *p = '\0';
  2005. setvareq(nameeq, flags | VNOSAVE);
  2006. INT_ON;
  2007. }
  2008. static void FAST_FUNC
  2009. setvar2(const char *name, const char *val)
  2010. {
  2011. setvar(name, val, 0);
  2012. }
  2013. #if ENABLE_ASH_GETOPTS
  2014. /*
  2015. * Safe version of setvar, returns 1 on success 0 on failure.
  2016. */
  2017. static int
  2018. setvarsafe(const char *name, const char *val, int flags)
  2019. {
  2020. int err;
  2021. volatile int saveint;
  2022. struct jmploc *volatile savehandler = exception_handler;
  2023. struct jmploc jmploc;
  2024. SAVE_INT(saveint);
  2025. if (setjmp(jmploc.loc))
  2026. err = 1;
  2027. else {
  2028. exception_handler = &jmploc;
  2029. setvar(name, val, flags);
  2030. err = 0;
  2031. }
  2032. exception_handler = savehandler;
  2033. RESTORE_INT(saveint);
  2034. return err;
  2035. }
  2036. #endif
  2037. /*
  2038. * Unset the specified variable.
  2039. */
  2040. static int
  2041. unsetvar(const char *s)
  2042. {
  2043. struct var **vpp;
  2044. struct var *vp;
  2045. int retval;
  2046. vpp = findvar(hashvar(s), s);
  2047. vp = *vpp;
  2048. retval = 2;
  2049. if (vp) {
  2050. int flags = vp->flags;
  2051. retval = 1;
  2052. if (flags & VREADONLY)
  2053. goto out;
  2054. #if ENABLE_ASH_RANDOM_SUPPORT
  2055. vp->flags &= ~VDYNAMIC;
  2056. #endif
  2057. if (flags & VUNSET)
  2058. goto ok;
  2059. if ((flags & VSTRFIXED) == 0) {
  2060. INT_OFF;
  2061. if ((flags & (VTEXTFIXED|VSTACK)) == 0)
  2062. free((char*)vp->var_text);
  2063. *vpp = vp->next;
  2064. free(vp);
  2065. INT_ON;
  2066. } else {
  2067. setvar2(s, 0);
  2068. vp->flags &= ~VEXPORT;
  2069. }
  2070. ok:
  2071. retval = 0;
  2072. }
  2073. out:
  2074. return retval;
  2075. }
  2076. /*
  2077. * Process a linked list of variable assignments.
  2078. */
  2079. static void
  2080. listsetvar(struct strlist *list_set_var, int flags)
  2081. {
  2082. struct strlist *lp = list_set_var;
  2083. if (!lp)
  2084. return;
  2085. INT_OFF;
  2086. do {
  2087. setvareq(lp->text, flags);
  2088. lp = lp->next;
  2089. } while (lp);
  2090. INT_ON;
  2091. }
  2092. /*
  2093. * Generate a list of variables satisfying the given conditions.
  2094. */
  2095. static char **
  2096. listvars(int on, int off, char ***end)
  2097. {
  2098. struct var **vpp;
  2099. struct var *vp;
  2100. char **ep;
  2101. int mask;
  2102. STARTSTACKSTR(ep);
  2103. vpp = vartab;
  2104. mask = on | off;
  2105. do {
  2106. for (vp = *vpp; vp; vp = vp->next) {
  2107. if ((vp->flags & mask) == on) {
  2108. if (ep == stackstrend())
  2109. ep = growstackstr();
  2110. *ep++ = (char*)vp->var_text;
  2111. }
  2112. }
  2113. } while (++vpp < vartab + VTABSIZE);
  2114. if (ep == stackstrend())
  2115. ep = growstackstr();
  2116. if (end)
  2117. *end = ep;
  2118. *ep++ = NULL;
  2119. return grabstackstr(ep);
  2120. }
  2121. /* ============ Path search helper
  2122. *
  2123. * The variable path (passed by reference) should be set to the start
  2124. * of the path before the first call; path_advance will update
  2125. * this value as it proceeds. Successive calls to path_advance will return
  2126. * the possible path expansions in sequence. If an option (indicated by
  2127. * a percent sign) appears in the path entry then the global variable
  2128. * pathopt will be set to point to it; otherwise pathopt will be set to
  2129. * NULL.
  2130. */
  2131. static const char *pathopt; /* set by path_advance */
  2132. static char *
  2133. path_advance(const char **path, const char *name)
  2134. {
  2135. const char *p;
  2136. char *q;
  2137. const char *start;
  2138. size_t len;
  2139. if (*path == NULL)
  2140. return NULL;
  2141. start = *path;
  2142. for (p = start; *p && *p != ':' && *p != '%'; p++)
  2143. continue;
  2144. len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
  2145. while (stackblocksize() < len)
  2146. growstackblock();
  2147. q = stackblock();
  2148. if (p != start) {
  2149. memcpy(q, start, p - start);
  2150. q += p - start;
  2151. *q++ = '/';
  2152. }
  2153. strcpy(q, name);
  2154. pathopt = NULL;
  2155. if (*p == '%') {
  2156. pathopt = ++p;
  2157. while (*p && *p != ':')
  2158. p++;
  2159. }
  2160. if (*p == ':')
  2161. *path = p + 1;
  2162. else
  2163. *path = NULL;
  2164. return stalloc(len);
  2165. }
  2166. /* ============ Prompt */
  2167. static smallint doprompt; /* if set, prompt the user */
  2168. static smallint needprompt; /* true if interactive and at start of line */
  2169. #if ENABLE_FEATURE_EDITING
  2170. static line_input_t *line_input_state;
  2171. static const char *cmdedit_prompt;
  2172. static void
  2173. putprompt(const char *s)
  2174. {
  2175. if (ENABLE_ASH_EXPAND_PRMT) {
  2176. free((char*)cmdedit_prompt);
  2177. cmdedit_prompt = ckstrdup(s);
  2178. return;
  2179. }
  2180. cmdedit_prompt = s;
  2181. }
  2182. #else
  2183. static void
  2184. putprompt(const char *s)
  2185. {
  2186. out2str(s);
  2187. }
  2188. #endif
  2189. #if ENABLE_ASH_EXPAND_PRMT
  2190. /* expandstr() needs parsing machinery, so it is far away ahead... */
  2191. static const char *expandstr(const char *ps);
  2192. #else
  2193. #define expandstr(s) s
  2194. #endif
  2195. static void
  2196. setprompt_if(smallint do_set, int whichprompt)
  2197. {
  2198. const char *prompt;
  2199. IF_ASH_EXPAND_PRMT(struct stackmark smark;)
  2200. if (!do_set)
  2201. return;
  2202. needprompt = 0;
  2203. switch (whichprompt) {
  2204. case 1:
  2205. prompt = ps1val();
  2206. break;
  2207. case 2:
  2208. prompt = ps2val();
  2209. break;
  2210. default: /* 0 */
  2211. prompt = nullstr;
  2212. }
  2213. #if ENABLE_ASH_EXPAND_PRMT
  2214. setstackmark(&smark);
  2215. stalloc(stackblocksize());
  2216. #endif
  2217. putprompt(expandstr(prompt));
  2218. #if ENABLE_ASH_EXPAND_PRMT
  2219. popstackmark(&smark);
  2220. #endif
  2221. }
  2222. /* ============ The cd and pwd commands */
  2223. #define CD_PHYSICAL 1
  2224. #define CD_PRINT 2
  2225. static int
  2226. cdopt(void)
  2227. {
  2228. int flags = 0;
  2229. int i, j;
  2230. j = 'L';
  2231. while ((i = nextopt("LP")) != '\0') {
  2232. if (i != j) {
  2233. flags ^= CD_PHYSICAL;
  2234. j = i;
  2235. }
  2236. }
  2237. return flags;
  2238. }
  2239. /*
  2240. * Update curdir (the name of the current directory) in response to a
  2241. * cd command.
  2242. */
  2243. static const char *
  2244. updatepwd(const char *dir)
  2245. {
  2246. char *new;
  2247. char *p;
  2248. char *cdcomppath;
  2249. const char *lim;
  2250. cdcomppath = ststrdup(dir);
  2251. STARTSTACKSTR(new);
  2252. if (*dir != '/') {
  2253. if (curdir == nullstr)
  2254. return 0;
  2255. new = stack_putstr(curdir, new);
  2256. }
  2257. new = makestrspace(strlen(dir) + 2, new);
  2258. lim = (char *)stackblock() + 1;
  2259. if (*dir != '/') {
  2260. if (new[-1] != '/')
  2261. USTPUTC('/', new);
  2262. if (new > lim && *lim == '/')
  2263. lim++;
  2264. } else {
  2265. USTPUTC('/', new);
  2266. cdcomppath++;
  2267. if (dir[1] == '/' && dir[2] != '/') {
  2268. USTPUTC('/', new);
  2269. cdcomppath++;
  2270. lim++;
  2271. }
  2272. }
  2273. p = strtok(cdcomppath, "/");
  2274. while (p) {
  2275. switch (*p) {
  2276. case '.':
  2277. if (p[1] == '.' && p[2] == '\0') {
  2278. while (new > lim) {
  2279. STUNPUTC(new);
  2280. if (new[-1] == '/')
  2281. break;
  2282. }
  2283. break;
  2284. }
  2285. if (p[1] == '\0')
  2286. break;
  2287. /* fall through */
  2288. default:
  2289. new = stack_putstr(p, new);
  2290. USTPUTC('/', new);
  2291. }
  2292. p = strtok(0, "/");
  2293. }
  2294. if (new > lim)
  2295. STUNPUTC(new);
  2296. *new = 0;
  2297. return stackblock();
  2298. }
  2299. /*
  2300. * Find out what the current directory is. If we already know the current
  2301. * directory, this routine returns immediately.
  2302. */
  2303. static char *
  2304. getpwd(void)
  2305. {
  2306. char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
  2307. return dir ? dir : nullstr;
  2308. }
  2309. static void
  2310. setpwd(const char *val, int setold)
  2311. {
  2312. char *oldcur, *dir;
  2313. oldcur = dir = curdir;
  2314. if (setold) {
  2315. setvar("OLDPWD", oldcur, VEXPORT);
  2316. }
  2317. INT_OFF;
  2318. if (physdir != nullstr) {
  2319. if (physdir != oldcur)
  2320. free(physdir);
  2321. physdir = nullstr;
  2322. }
  2323. if (oldcur == val || !val) {
  2324. char *s = getpwd();
  2325. physdir = s;
  2326. if (!val)
  2327. dir = s;
  2328. } else
  2329. dir = ckstrdup(val);
  2330. if (oldcur != dir && oldcur != nullstr) {
  2331. free(oldcur);
  2332. }
  2333. curdir = dir;
  2334. INT_ON;
  2335. setvar("PWD", dir, VEXPORT);
  2336. }
  2337. static void hashcd(void);
  2338. /*
  2339. * Actually do the chdir. We also call hashcd to let the routines in exec.c
  2340. * know that the current directory has changed.
  2341. */
  2342. static int
  2343. docd(const char *dest, int flags)
  2344. {
  2345. const char *dir = NULL;
  2346. int err;
  2347. TRACE(("docd(\"%s\", %d) called\n", dest, flags));
  2348. INT_OFF;
  2349. if (!(flags & CD_PHYSICAL)) {
  2350. dir = updatepwd(dest);
  2351. if (dir)
  2352. dest = dir;
  2353. }
  2354. err = chdir(dest);
  2355. if (err)
  2356. goto out;
  2357. setpwd(dir, 1);
  2358. hashcd();
  2359. out:
  2360. INT_ON;
  2361. return err;
  2362. }
  2363. static int FAST_FUNC
  2364. cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  2365. {
  2366. const char *dest;
  2367. const char *path;
  2368. const char *p;
  2369. char c;
  2370. struct stat statb;
  2371. int flags;
  2372. flags = cdopt();
  2373. dest = *argptr;
  2374. if (!dest)
  2375. dest = bltinlookup("HOME");
  2376. else if (LONE_DASH(dest)) {
  2377. dest = bltinlookup("OLDPWD");
  2378. flags |= CD_PRINT;
  2379. }
  2380. if (!dest)
  2381. dest = nullstr;
  2382. if (*dest == '/')
  2383. goto step7;
  2384. if (*dest == '.') {
  2385. c = dest[1];
  2386. dotdot:
  2387. switch (c) {
  2388. case '\0':
  2389. case '/':
  2390. goto step6;
  2391. case '.':
  2392. c = dest[2];
  2393. if (c != '.')
  2394. goto dotdot;
  2395. }
  2396. }
  2397. if (!*dest)
  2398. dest = ".";
  2399. path = bltinlookup("CDPATH");
  2400. if (!path) {
  2401. step6:
  2402. step7:
  2403. p = dest;
  2404. goto docd;
  2405. }
  2406. do {
  2407. c = *path;
  2408. p = path_advance(&path, dest);
  2409. if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
  2410. if (c && c != ':')
  2411. flags |= CD_PRINT;
  2412. docd:
  2413. if (!docd(p, flags))
  2414. goto out;
  2415. break;
  2416. }
  2417. } while (path);
  2418. ash_msg_and_raise_error("can't cd to %s", dest);
  2419. /* NOTREACHED */
  2420. out:
  2421. if (flags & CD_PRINT)
  2422. out1fmt("%s\n", curdir);
  2423. return 0;
  2424. }
  2425. static int FAST_FUNC
  2426. pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  2427. {
  2428. int flags;
  2429. const char *dir = curdir;
  2430. flags = cdopt();
  2431. if (flags) {
  2432. if (physdir == nullstr)
  2433. setpwd(dir, 0);
  2434. dir = physdir;
  2435. }
  2436. out1fmt("%s\n", dir);
  2437. return 0;
  2438. }
  2439. /* ============ ... */
  2440. #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
  2441. /* Syntax classes */
  2442. #define CWORD 0 /* character is nothing special */
  2443. #define CNL 1 /* newline character */
  2444. #define CBACK 2 /* a backslash character */
  2445. #define CSQUOTE 3 /* single quote */
  2446. #define CDQUOTE 4 /* double quote */
  2447. #define CENDQUOTE 5 /* a terminating quote */
  2448. #define CBQUOTE 6 /* backwards single quote */
  2449. #define CVAR 7 /* a dollar sign */
  2450. #define CENDVAR 8 /* a '}' character */
  2451. #define CLP 9 /* a left paren in arithmetic */
  2452. #define CRP 10 /* a right paren in arithmetic */
  2453. #define CENDFILE 11 /* end of file */
  2454. #define CCTL 12 /* like CWORD, except it must be escaped */
  2455. #define CSPCL 13 /* these terminate a word */
  2456. #define CIGN 14 /* character should be ignored */
  2457. #define PEOF 256
  2458. #if ENABLE_ASH_ALIAS
  2459. # define PEOA 257
  2460. #endif
  2461. #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
  2462. #if ENABLE_SH_MATH_SUPPORT
  2463. # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
  2464. #else
  2465. # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
  2466. #endif
  2467. static const uint16_t S_I_T[] = {
  2468. #if ENABLE_ASH_ALIAS
  2469. SIT_ITEM(CSPCL , CIGN , CIGN , CIGN ), /* 0, PEOA */
  2470. #endif
  2471. SIT_ITEM(CSPCL , CWORD , CWORD, CWORD ), /* 1, ' ' */
  2472. SIT_ITEM(CNL , CNL , CNL , CNL ), /* 2, \n */
  2473. SIT_ITEM(CWORD , CCTL , CCTL , CWORD ), /* 3, !*-/:=?[]~ */
  2474. SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD ), /* 4, '"' */
  2475. SIT_ITEM(CVAR , CVAR , CWORD, CVAR ), /* 5, $ */
  2476. SIT_ITEM(CSQUOTE , CWORD , CENDQUOTE, CWORD), /* 6, "'" */
  2477. SIT_ITEM(CSPCL , CWORD , CWORD, CLP ), /* 7, ( */
  2478. SIT_ITEM(CSPCL , CWORD , CWORD, CRP ), /* 8, ) */
  2479. SIT_ITEM(CBACK , CBACK , CCTL , CBACK ), /* 9, \ */
  2480. SIT_ITEM(CBQUOTE , CBQUOTE , CWORD, CBQUOTE), /* 10, ` */
  2481. SIT_ITEM(CENDVAR , CENDVAR , CWORD, CENDVAR), /* 11, } */
  2482. #if !USE_SIT_FUNCTION
  2483. SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
  2484. SIT_ITEM(CWORD , CWORD , CWORD, CWORD ), /* 13, 0-9A-Za-z */
  2485. SIT_ITEM(CCTL , CCTL , CCTL , CCTL ) /* 14, CTLESC ... */
  2486. #endif
  2487. #undef SIT_ITEM
  2488. };
  2489. /* Constants below must match table above */
  2490. enum {
  2491. #if ENABLE_ASH_ALIAS
  2492. CSPCL_CIGN_CIGN_CIGN , /* 0 */
  2493. #endif
  2494. CSPCL_CWORD_CWORD_CWORD , /* 1 */
  2495. CNL_CNL_CNL_CNL , /* 2 */
  2496. CWORD_CCTL_CCTL_CWORD , /* 3 */
  2497. CDQUOTE_CENDQUOTE_CWORD_CWORD , /* 4 */
  2498. CVAR_CVAR_CWORD_CVAR , /* 5 */
  2499. CSQUOTE_CWORD_CENDQUOTE_CWORD , /* 6 */
  2500. CSPCL_CWORD_CWORD_CLP , /* 7 */
  2501. CSPCL_CWORD_CWORD_CRP , /* 8 */
  2502. CBACK_CBACK_CCTL_CBACK , /* 9 */
  2503. CBQUOTE_CBQUOTE_CWORD_CBQUOTE , /* 10 */
  2504. CENDVAR_CENDVAR_CWORD_CENDVAR , /* 11 */
  2505. CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
  2506. CWORD_CWORD_CWORD_CWORD , /* 13 */
  2507. CCTL_CCTL_CCTL_CCTL , /* 14 */
  2508. };
  2509. /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
  2510. * caller must ensure proper cast on it if c is *char_ptr!
  2511. */
  2512. /* Values for syntax param */
  2513. #define BASESYNTAX 0 /* not in quotes */
  2514. #define DQSYNTAX 1 /* in double quotes */
  2515. #define SQSYNTAX 2 /* in single quotes */
  2516. #define ARISYNTAX 3 /* in arithmetic */
  2517. #define PSSYNTAX 4 /* prompt. never passed to SIT() */
  2518. #if USE_SIT_FUNCTION
  2519. static int
  2520. SIT(int c, int syntax)
  2521. {
  2522. static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
  2523. # if ENABLE_ASH_ALIAS
  2524. static const uint8_t syntax_index_table[] ALIGN1 = {
  2525. 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
  2526. 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
  2527. 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
  2528. 11, 3 /* "}~" */
  2529. };
  2530. # else
  2531. static const uint8_t syntax_index_table[] ALIGN1 = {
  2532. 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
  2533. 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
  2534. 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
  2535. 10, 2 /* "}~" */
  2536. };
  2537. # endif
  2538. const char *s;
  2539. int indx;
  2540. if (c == PEOF)
  2541. return CENDFILE;
  2542. # if ENABLE_ASH_ALIAS
  2543. if (c == PEOA)
  2544. indx = 0;
  2545. else
  2546. # endif
  2547. {
  2548. /* Cast is purely for paranoia here,
  2549. * just in case someone passed signed char to us */
  2550. if ((unsigned char)c >= CTL_FIRST
  2551. && (unsigned char)c <= CTL_LAST
  2552. ) {
  2553. return CCTL;
  2554. }
  2555. s = strchrnul(spec_symbls, c);
  2556. if (*s == '\0')
  2557. return CWORD;
  2558. indx = syntax_index_table[s - spec_symbls];
  2559. }
  2560. return (S_I_T[indx] >> (syntax*4)) & 0xf;
  2561. }
  2562. #else /* !USE_SIT_FUNCTION */
  2563. static const uint8_t syntax_index_table[] = {
  2564. /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
  2565. /* 0 */ CWORD_CWORD_CWORD_CWORD,
  2566. /* 1 */ CWORD_CWORD_CWORD_CWORD,
  2567. /* 2 */ CWORD_CWORD_CWORD_CWORD,
  2568. /* 3 */ CWORD_CWORD_CWORD_CWORD,
  2569. /* 4 */ CWORD_CWORD_CWORD_CWORD,
  2570. /* 5 */ CWORD_CWORD_CWORD_CWORD,
  2571. /* 6 */ CWORD_CWORD_CWORD_CWORD,
  2572. /* 7 */ CWORD_CWORD_CWORD_CWORD,
  2573. /* 8 */ CWORD_CWORD_CWORD_CWORD,
  2574. /* 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
  2575. /* 10 "\n" */ CNL_CNL_CNL_CNL,
  2576. /* 11 */ CWORD_CWORD_CWORD_CWORD,
  2577. /* 12 */ CWORD_CWORD_CWORD_CWORD,
  2578. /* 13 */ CWORD_CWORD_CWORD_CWORD,
  2579. /* 14 */ CWORD_CWORD_CWORD_CWORD,
  2580. /* 15 */ CWORD_CWORD_CWORD_CWORD,
  2581. /* 16 */ CWORD_CWORD_CWORD_CWORD,
  2582. /* 17 */ CWORD_CWORD_CWORD_CWORD,
  2583. /* 18 */ CWORD_CWORD_CWORD_CWORD,
  2584. /* 19 */ CWORD_CWORD_CWORD_CWORD,
  2585. /* 20 */ CWORD_CWORD_CWORD_CWORD,
  2586. /* 21 */ CWORD_CWORD_CWORD_CWORD,
  2587. /* 22 */ CWORD_CWORD_CWORD_CWORD,
  2588. /* 23 */ CWORD_CWORD_CWORD_CWORD,
  2589. /* 24 */ CWORD_CWORD_CWORD_CWORD,
  2590. /* 25 */ CWORD_CWORD_CWORD_CWORD,
  2591. /* 26 */ CWORD_CWORD_CWORD_CWORD,
  2592. /* 27 */ CWORD_CWORD_CWORD_CWORD,
  2593. /* 28 */ CWORD_CWORD_CWORD_CWORD,
  2594. /* 29 */ CWORD_CWORD_CWORD_CWORD,
  2595. /* 30 */ CWORD_CWORD_CWORD_CWORD,
  2596. /* 31 */ CWORD_CWORD_CWORD_CWORD,
  2597. /* 32 " " */ CSPCL_CWORD_CWORD_CWORD,
  2598. /* 33 "!" */ CWORD_CCTL_CCTL_CWORD,
  2599. /* 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
  2600. /* 35 "#" */ CWORD_CWORD_CWORD_CWORD,
  2601. /* 36 "$" */ CVAR_CVAR_CWORD_CVAR,
  2602. /* 37 "%" */ CWORD_CWORD_CWORD_CWORD,
  2603. /* 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
  2604. /* 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
  2605. /* 40 "(" */ CSPCL_CWORD_CWORD_CLP,
  2606. /* 41 ")" */ CSPCL_CWORD_CWORD_CRP,
  2607. /* 42 "*" */ CWORD_CCTL_CCTL_CWORD,
  2608. /* 43 "+" */ CWORD_CWORD_CWORD_CWORD,
  2609. /* 44 "," */ CWORD_CWORD_CWORD_CWORD,
  2610. /* 45 "-" */ CWORD_CCTL_CCTL_CWORD,
  2611. /* 46 "." */ CWORD_CWORD_CWORD_CWORD,
  2612. /* 47 "/" */ CWORD_CCTL_CCTL_CWORD,
  2613. /* 48 "0" */ CWORD_CWORD_CWORD_CWORD,
  2614. /* 49 "1" */ CWORD_CWORD_CWORD_CWORD,
  2615. /* 50 "2" */ CWORD_CWORD_CWORD_CWORD,
  2616. /* 51 "3" */ CWORD_CWORD_CWORD_CWORD,
  2617. /* 52 "4" */ CWORD_CWORD_CWORD_CWORD,
  2618. /* 53 "5" */ CWORD_CWORD_CWORD_CWORD,
  2619. /* 54 "6" */ CWORD_CWORD_CWORD_CWORD,
  2620. /* 55 "7" */ CWORD_CWORD_CWORD_CWORD,
  2621. /* 56 "8" */ CWORD_CWORD_CWORD_CWORD,
  2622. /* 57 "9" */ CWORD_CWORD_CWORD_CWORD,
  2623. /* 58 ":" */ CWORD_CCTL_CCTL_CWORD,
  2624. /* 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
  2625. /* 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
  2626. /* 61 "=" */ CWORD_CCTL_CCTL_CWORD,
  2627. /* 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
  2628. /* 63 "?" */ CWORD_CCTL_CCTL_CWORD,
  2629. /* 64 "@" */ CWORD_CWORD_CWORD_CWORD,
  2630. /* 65 "A" */ CWORD_CWORD_CWORD_CWORD,
  2631. /* 66 "B" */ CWORD_CWORD_CWORD_CWORD,
  2632. /* 67 "C" */ CWORD_CWORD_CWORD_CWORD,
  2633. /* 68 "D" */ CWORD_CWORD_CWORD_CWORD,
  2634. /* 69 "E" */ CWORD_CWORD_CWORD_CWORD,
  2635. /* 70 "F" */ CWORD_CWORD_CWORD_CWORD,
  2636. /* 71 "G" */ CWORD_CWORD_CWORD_CWORD,
  2637. /* 72 "H" */ CWORD_CWORD_CWORD_CWORD,
  2638. /* 73 "I" */ CWORD_CWORD_CWORD_CWORD,
  2639. /* 74 "J" */ CWORD_CWORD_CWORD_CWORD,
  2640. /* 75 "K" */ CWORD_CWORD_CWORD_CWORD,
  2641. /* 76 "L" */ CWORD_CWORD_CWORD_CWORD,
  2642. /* 77 "M" */ CWORD_CWORD_CWORD_CWORD,
  2643. /* 78 "N" */ CWORD_CWORD_CWORD_CWORD,
  2644. /* 79 "O" */ CWORD_CWORD_CWORD_CWORD,
  2645. /* 80 "P" */ CWORD_CWORD_CWORD_CWORD,
  2646. /* 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
  2647. /* 82 "R" */ CWORD_CWORD_CWORD_CWORD,
  2648. /* 83 "S" */ CWORD_CWORD_CWORD_CWORD,
  2649. /* 84 "T" */ CWORD_CWORD_CWORD_CWORD,
  2650. /* 85 "U" */ CWORD_CWORD_CWORD_CWORD,
  2651. /* 86 "V" */ CWORD_CWORD_CWORD_CWORD,
  2652. /* 87 "W" */ CWORD_CWORD_CWORD_CWORD,
  2653. /* 88 "X" */ CWORD_CWORD_CWORD_CWORD,
  2654. /* 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
  2655. /* 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
  2656. /* 91 "[" */ CWORD_CCTL_CCTL_CWORD,
  2657. /* 92 "\" */ CBACK_CBACK_CCTL_CBACK,
  2658. /* 93 "]" */ CWORD_CCTL_CCTL_CWORD,
  2659. /* 94 "^" */ CWORD_CWORD_CWORD_CWORD,
  2660. /* 95 "_" */ CWORD_CWORD_CWORD_CWORD,
  2661. /* 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
  2662. /* 97 "a" */ CWORD_CWORD_CWORD_CWORD,
  2663. /* 98 "b" */ CWORD_CWORD_CWORD_CWORD,
  2664. /* 99 "c" */ CWORD_CWORD_CWORD_CWORD,
  2665. /* 100 "d" */ CWORD_CWORD_CWORD_CWORD,
  2666. /* 101 "e" */ CWORD_CWORD_CWORD_CWORD,
  2667. /* 102 "f" */ CWORD_CWORD_CWORD_CWORD,
  2668. /* 103 "g" */ CWORD_CWORD_CWORD_CWORD,
  2669. /* 104 "h" */ CWORD_CWORD_CWORD_CWORD,
  2670. /* 105 "i" */ CWORD_CWORD_CWORD_CWORD,
  2671. /* 106 "j" */ CWORD_CWORD_CWORD_CWORD,
  2672. /* 107 "k" */ CWORD_CWORD_CWORD_CWORD,
  2673. /* 108 "l" */ CWORD_CWORD_CWORD_CWORD,
  2674. /* 109 "m" */ CWORD_CWORD_CWORD_CWORD,
  2675. /* 110 "n" */ CWORD_CWORD_CWORD_CWORD,
  2676. /* 111 "o" */ CWORD_CWORD_CWORD_CWORD,
  2677. /* 112 "p" */ CWORD_CWORD_CWORD_CWORD,
  2678. /* 113 "q" */ CWORD_CWORD_CWORD_CWORD,
  2679. /* 114 "r" */ CWORD_CWORD_CWORD_CWORD,
  2680. /* 115 "s" */ CWORD_CWORD_CWORD_CWORD,
  2681. /* 116 "t" */ CWORD_CWORD_CWORD_CWORD,
  2682. /* 117 "u" */ CWORD_CWORD_CWORD_CWORD,
  2683. /* 118 "v" */ CWORD_CWORD_CWORD_CWORD,
  2684. /* 119 "w" */ CWORD_CWORD_CWORD_CWORD,
  2685. /* 120 "x" */ CWORD_CWORD_CWORD_CWORD,
  2686. /* 121 "y" */ CWORD_CWORD_CWORD_CWORD,
  2687. /* 122 "z" */ CWORD_CWORD_CWORD_CWORD,
  2688. /* 123 "{" */ CWORD_CWORD_CWORD_CWORD,
  2689. /* 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
  2690. /* 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
  2691. /* 126 "~" */ CWORD_CCTL_CCTL_CWORD,
  2692. /* 127 del */ CWORD_CWORD_CWORD_CWORD,
  2693. /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
  2694. /* 129 CTLESC */ CCTL_CCTL_CCTL_CCTL,
  2695. /* 130 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
  2696. /* 131 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
  2697. /* 132 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
  2698. /* 133 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
  2699. /* 134 CTLARI */ CCTL_CCTL_CCTL_CCTL,
  2700. /* 135 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
  2701. /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
  2702. /* 137 */ CWORD_CWORD_CWORD_CWORD,
  2703. /* 138 */ CWORD_CWORD_CWORD_CWORD,
  2704. /* 139 */ CWORD_CWORD_CWORD_CWORD,
  2705. /* 140 */ CWORD_CWORD_CWORD_CWORD,
  2706. /* 141 */ CWORD_CWORD_CWORD_CWORD,
  2707. /* 142 */ CWORD_CWORD_CWORD_CWORD,
  2708. /* 143 */ CWORD_CWORD_CWORD_CWORD,
  2709. /* 144 */ CWORD_CWORD_CWORD_CWORD,
  2710. /* 145 */ CWORD_CWORD_CWORD_CWORD,
  2711. /* 146 */ CWORD_CWORD_CWORD_CWORD,
  2712. /* 147 */ CWORD_CWORD_CWORD_CWORD,
  2713. /* 148 */ CWORD_CWORD_CWORD_CWORD,
  2714. /* 149 */ CWORD_CWORD_CWORD_CWORD,
  2715. /* 150 */ CWORD_CWORD_CWORD_CWORD,
  2716. /* 151 */ CWORD_CWORD_CWORD_CWORD,
  2717. /* 152 */ CWORD_CWORD_CWORD_CWORD,
  2718. /* 153 */ CWORD_CWORD_CWORD_CWORD,
  2719. /* 154 */ CWORD_CWORD_CWORD_CWORD,
  2720. /* 155 */ CWORD_CWORD_CWORD_CWORD,
  2721. /* 156 */ CWORD_CWORD_CWORD_CWORD,
  2722. /* 157 */ CWORD_CWORD_CWORD_CWORD,
  2723. /* 158 */ CWORD_CWORD_CWORD_CWORD,
  2724. /* 159 */ CWORD_CWORD_CWORD_CWORD,
  2725. /* 160 */ CWORD_CWORD_CWORD_CWORD,
  2726. /* 161 */ CWORD_CWORD_CWORD_CWORD,
  2727. /* 162 */ CWORD_CWORD_CWORD_CWORD,
  2728. /* 163 */ CWORD_CWORD_CWORD_CWORD,
  2729. /* 164 */ CWORD_CWORD_CWORD_CWORD,
  2730. /* 165 */ CWORD_CWORD_CWORD_CWORD,
  2731. /* 166 */ CWORD_CWORD_CWORD_CWORD,
  2732. /* 167 */ CWORD_CWORD_CWORD_CWORD,
  2733. /* 168 */ CWORD_CWORD_CWORD_CWORD,
  2734. /* 169 */ CWORD_CWORD_CWORD_CWORD,
  2735. /* 170 */ CWORD_CWORD_CWORD_CWORD,
  2736. /* 171 */ CWORD_CWORD_CWORD_CWORD,
  2737. /* 172 */ CWORD_CWORD_CWORD_CWORD,
  2738. /* 173 */ CWORD_CWORD_CWORD_CWORD,
  2739. /* 174 */ CWORD_CWORD_CWORD_CWORD,
  2740. /* 175 */ CWORD_CWORD_CWORD_CWORD,
  2741. /* 176 */ CWORD_CWORD_CWORD_CWORD,
  2742. /* 177 */ CWORD_CWORD_CWORD_CWORD,
  2743. /* 178 */ CWORD_CWORD_CWORD_CWORD,
  2744. /* 179 */ CWORD_CWORD_CWORD_CWORD,
  2745. /* 180 */ CWORD_CWORD_CWORD_CWORD,
  2746. /* 181 */ CWORD_CWORD_CWORD_CWORD,
  2747. /* 182 */ CWORD_CWORD_CWORD_CWORD,
  2748. /* 183 */ CWORD_CWORD_CWORD_CWORD,
  2749. /* 184 */ CWORD_CWORD_CWORD_CWORD,
  2750. /* 185 */ CWORD_CWORD_CWORD_CWORD,
  2751. /* 186 */ CWORD_CWORD_CWORD_CWORD,
  2752. /* 187 */ CWORD_CWORD_CWORD_CWORD,
  2753. /* 188 */ CWORD_CWORD_CWORD_CWORD,
  2754. /* 189 */ CWORD_CWORD_CWORD_CWORD,
  2755. /* 190 */ CWORD_CWORD_CWORD_CWORD,
  2756. /* 191 */ CWORD_CWORD_CWORD_CWORD,
  2757. /* 192 */ CWORD_CWORD_CWORD_CWORD,
  2758. /* 193 */ CWORD_CWORD_CWORD_CWORD,
  2759. /* 194 */ CWORD_CWORD_CWORD_CWORD,
  2760. /* 195 */ CWORD_CWORD_CWORD_CWORD,
  2761. /* 196 */ CWORD_CWORD_CWORD_CWORD,
  2762. /* 197 */ CWORD_CWORD_CWORD_CWORD,
  2763. /* 198 */ CWORD_CWORD_CWORD_CWORD,
  2764. /* 199 */ CWORD_CWORD_CWORD_CWORD,
  2765. /* 200 */ CWORD_CWORD_CWORD_CWORD,
  2766. /* 201 */ CWORD_CWORD_CWORD_CWORD,
  2767. /* 202 */ CWORD_CWORD_CWORD_CWORD,
  2768. /* 203 */ CWORD_CWORD_CWORD_CWORD,
  2769. /* 204 */ CWORD_CWORD_CWORD_CWORD,
  2770. /* 205 */ CWORD_CWORD_CWORD_CWORD,
  2771. /* 206 */ CWORD_CWORD_CWORD_CWORD,
  2772. /* 207 */ CWORD_CWORD_CWORD_CWORD,
  2773. /* 208 */ CWORD_CWORD_CWORD_CWORD,
  2774. /* 209 */ CWORD_CWORD_CWORD_CWORD,
  2775. /* 210 */ CWORD_CWORD_CWORD_CWORD,
  2776. /* 211 */ CWORD_CWORD_CWORD_CWORD,
  2777. /* 212 */ CWORD_CWORD_CWORD_CWORD,
  2778. /* 213 */ CWORD_CWORD_CWORD_CWORD,
  2779. /* 214 */ CWORD_CWORD_CWORD_CWORD,
  2780. /* 215 */ CWORD_CWORD_CWORD_CWORD,
  2781. /* 216 */ CWORD_CWORD_CWORD_CWORD,
  2782. /* 217 */ CWORD_CWORD_CWORD_CWORD,
  2783. /* 218 */ CWORD_CWORD_CWORD_CWORD,
  2784. /* 219 */ CWORD_CWORD_CWORD_CWORD,
  2785. /* 220 */ CWORD_CWORD_CWORD_CWORD,
  2786. /* 221 */ CWORD_CWORD_CWORD_CWORD,
  2787. /* 222 */ CWORD_CWORD_CWORD_CWORD,
  2788. /* 223 */ CWORD_CWORD_CWORD_CWORD,
  2789. /* 224 */ CWORD_CWORD_CWORD_CWORD,
  2790. /* 225 */ CWORD_CWORD_CWORD_CWORD,
  2791. /* 226 */ CWORD_CWORD_CWORD_CWORD,
  2792. /* 227 */ CWORD_CWORD_CWORD_CWORD,
  2793. /* 228 */ CWORD_CWORD_CWORD_CWORD,
  2794. /* 229 */ CWORD_CWORD_CWORD_CWORD,
  2795. /* 230 */ CWORD_CWORD_CWORD_CWORD,
  2796. /* 231 */ CWORD_CWORD_CWORD_CWORD,
  2797. /* 232 */ CWORD_CWORD_CWORD_CWORD,
  2798. /* 233 */ CWORD_CWORD_CWORD_CWORD,
  2799. /* 234 */ CWORD_CWORD_CWORD_CWORD,
  2800. /* 235 */ CWORD_CWORD_CWORD_CWORD,
  2801. /* 236 */ CWORD_CWORD_CWORD_CWORD,
  2802. /* 237 */ CWORD_CWORD_CWORD_CWORD,
  2803. /* 238 */ CWORD_CWORD_CWORD_CWORD,
  2804. /* 239 */ CWORD_CWORD_CWORD_CWORD,
  2805. /* 230 */ CWORD_CWORD_CWORD_CWORD,
  2806. /* 241 */ CWORD_CWORD_CWORD_CWORD,
  2807. /* 242 */ CWORD_CWORD_CWORD_CWORD,
  2808. /* 243 */ CWORD_CWORD_CWORD_CWORD,
  2809. /* 244 */ CWORD_CWORD_CWORD_CWORD,
  2810. /* 245 */ CWORD_CWORD_CWORD_CWORD,
  2811. /* 246 */ CWORD_CWORD_CWORD_CWORD,
  2812. /* 247 */ CWORD_CWORD_CWORD_CWORD,
  2813. /* 248 */ CWORD_CWORD_CWORD_CWORD,
  2814. /* 249 */ CWORD_CWORD_CWORD_CWORD,
  2815. /* 250 */ CWORD_CWORD_CWORD_CWORD,
  2816. /* 251 */ CWORD_CWORD_CWORD_CWORD,
  2817. /* 252 */ CWORD_CWORD_CWORD_CWORD,
  2818. /* 253 */ CWORD_CWORD_CWORD_CWORD,
  2819. /* 254 */ CWORD_CWORD_CWORD_CWORD,
  2820. /* 255 */ CWORD_CWORD_CWORD_CWORD,
  2821. /* PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
  2822. # if ENABLE_ASH_ALIAS
  2823. /* PEOA */ CSPCL_CIGN_CIGN_CIGN,
  2824. # endif
  2825. };
  2826. # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
  2827. #endif /* !USE_SIT_FUNCTION */
  2828. /* ============ Alias handling */
  2829. #if ENABLE_ASH_ALIAS
  2830. #define ALIASINUSE 1
  2831. #define ALIASDEAD 2
  2832. struct alias {
  2833. struct alias *next;
  2834. char *name;
  2835. char *val;
  2836. int flag;
  2837. };
  2838. static struct alias **atab; // [ATABSIZE];
  2839. #define INIT_G_alias() do { \
  2840. atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
  2841. } while (0)
  2842. static struct alias **
  2843. __lookupalias(const char *name) {
  2844. unsigned int hashval;
  2845. struct alias **app;
  2846. const char *p;
  2847. unsigned int ch;
  2848. p = name;
  2849. ch = (unsigned char)*p;
  2850. hashval = ch << 4;
  2851. while (ch) {
  2852. hashval += ch;
  2853. ch = (unsigned char)*++p;
  2854. }
  2855. app = &atab[hashval % ATABSIZE];
  2856. for (; *app; app = &(*app)->next) {
  2857. if (strcmp(name, (*app)->name) == 0) {
  2858. break;
  2859. }
  2860. }
  2861. return app;
  2862. }
  2863. static struct alias *
  2864. lookupalias(const char *name, int check)
  2865. {
  2866. struct alias *ap = *__lookupalias(name);
  2867. if (check && ap && (ap->flag & ALIASINUSE))
  2868. return NULL;
  2869. return ap;
  2870. }
  2871. static struct alias *
  2872. freealias(struct alias *ap)
  2873. {
  2874. struct alias *next;
  2875. if (ap->flag & ALIASINUSE) {
  2876. ap->flag |= ALIASDEAD;
  2877. return ap;
  2878. }
  2879. next = ap->next;
  2880. free(ap->name);
  2881. free(ap->val);
  2882. free(ap);
  2883. return next;
  2884. }
  2885. static void
  2886. setalias(const char *name, const char *val)
  2887. {
  2888. struct alias *ap, **app;
  2889. app = __lookupalias(name);
  2890. ap = *app;
  2891. INT_OFF;
  2892. if (ap) {
  2893. if (!(ap->flag & ALIASINUSE)) {
  2894. free(ap->val);
  2895. }
  2896. ap->val = ckstrdup(val);
  2897. ap->flag &= ~ALIASDEAD;
  2898. } else {
  2899. /* not found */
  2900. ap = ckzalloc(sizeof(struct alias));
  2901. ap->name = ckstrdup(name);
  2902. ap->val = ckstrdup(val);
  2903. /*ap->flag = 0; - ckzalloc did it */
  2904. /*ap->next = NULL;*/
  2905. *app = ap;
  2906. }
  2907. INT_ON;
  2908. }
  2909. static int
  2910. unalias(const char *name)
  2911. {
  2912. struct alias **app;
  2913. app = __lookupalias(name);
  2914. if (*app) {
  2915. INT_OFF;
  2916. *app = freealias(*app);
  2917. INT_ON;
  2918. return 0;
  2919. }
  2920. return 1;
  2921. }
  2922. static void
  2923. rmaliases(void)
  2924. {
  2925. struct alias *ap, **app;
  2926. int i;
  2927. INT_OFF;
  2928. for (i = 0; i < ATABSIZE; i++) {
  2929. app = &atab[i];
  2930. for (ap = *app; ap; ap = *app) {
  2931. *app = freealias(*app);
  2932. if (ap == *app) {
  2933. app = &ap->next;
  2934. }
  2935. }
  2936. }
  2937. INT_ON;
  2938. }
  2939. static void
  2940. printalias(const struct alias *ap)
  2941. {
  2942. out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
  2943. }
  2944. /*
  2945. * TODO - sort output
  2946. */
  2947. static int FAST_FUNC
  2948. aliascmd(int argc UNUSED_PARAM, char **argv)
  2949. {
  2950. char *n, *v;
  2951. int ret = 0;
  2952. struct alias *ap;
  2953. if (!argv[1]) {
  2954. int i;
  2955. for (i = 0; i < ATABSIZE; i++) {
  2956. for (ap = atab[i]; ap; ap = ap->next) {
  2957. printalias(ap);
  2958. }
  2959. }
  2960. return 0;
  2961. }
  2962. while ((n = *++argv) != NULL) {
  2963. v = strchr(n+1, '=');
  2964. if (v == NULL) { /* n+1: funny ksh stuff */
  2965. ap = *__lookupalias(n);
  2966. if (ap == NULL) {
  2967. fprintf(stderr, "%s: %s not found\n", "alias", n);
  2968. ret = 1;
  2969. } else
  2970. printalias(ap);
  2971. } else {
  2972. *v++ = '\0';
  2973. setalias(n, v);
  2974. }
  2975. }
  2976. return ret;
  2977. }
  2978. static int FAST_FUNC
  2979. unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  2980. {
  2981. int i;
  2982. while ((i = nextopt("a")) != '\0') {
  2983. if (i == 'a') {
  2984. rmaliases();
  2985. return 0;
  2986. }
  2987. }
  2988. for (i = 0; *argptr; argptr++) {
  2989. if (unalias(*argptr)) {
  2990. fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
  2991. i = 1;
  2992. }
  2993. }
  2994. return i;
  2995. }
  2996. #endif /* ASH_ALIAS */
  2997. /* ============ jobs.c */
  2998. /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
  2999. #define FORK_FG 0
  3000. #define FORK_BG 1
  3001. #define FORK_NOJOB 2
  3002. /* mode flags for showjob(s) */
  3003. #define SHOW_ONLY_PGID 0x01 /* show only pgid (jobs -p) */
  3004. #define SHOW_PIDS 0x02 /* show individual pids, not just one line per job */
  3005. #define SHOW_CHANGED 0x04 /* only jobs whose state has changed */
  3006. /*
  3007. * A job structure contains information about a job. A job is either a
  3008. * single process or a set of processes contained in a pipeline. In the
  3009. * latter case, pidlist will be non-NULL, and will point to a -1 terminated
  3010. * array of pids.
  3011. */
  3012. struct procstat {
  3013. pid_t ps_pid; /* process id */
  3014. int ps_status; /* last process status from wait() */
  3015. char *ps_cmd; /* text of command being run */
  3016. };
  3017. struct job {
  3018. struct procstat ps0; /* status of process */
  3019. struct procstat *ps; /* status or processes when more than one */
  3020. #if JOBS
  3021. int stopstatus; /* status of a stopped job */
  3022. #endif
  3023. uint32_t
  3024. nprocs: 16, /* number of processes */
  3025. state: 8,
  3026. #define JOBRUNNING 0 /* at least one proc running */
  3027. #define JOBSTOPPED 1 /* all procs are stopped */
  3028. #define JOBDONE 2 /* all procs are completed */
  3029. #if JOBS
  3030. sigint: 1, /* job was killed by SIGINT */
  3031. jobctl: 1, /* job running under job control */
  3032. #endif
  3033. waited: 1, /* true if this entry has been waited for */
  3034. used: 1, /* true if this entry is in used */
  3035. changed: 1; /* true if status has changed */
  3036. struct job *prev_job; /* previous job */
  3037. };
  3038. static struct job *makejob(/*union node *,*/ int);
  3039. static int forkshell(struct job *, union node *, int);
  3040. static int waitforjob(struct job *);
  3041. #if !JOBS
  3042. enum { doing_jobctl = 0 };
  3043. #define setjobctl(on) do {} while (0)
  3044. #else
  3045. static smallint doing_jobctl; //references:8
  3046. static void setjobctl(int);
  3047. #endif
  3048. /*
  3049. * Ignore a signal.
  3050. */
  3051. static void
  3052. ignoresig(int signo)
  3053. {
  3054. /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
  3055. if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
  3056. /* No, need to do it */
  3057. signal(signo, SIG_IGN);
  3058. }
  3059. sigmode[signo - 1] = S_HARD_IGN;
  3060. }
  3061. /*
  3062. * Only one usage site - in setsignal()
  3063. */
  3064. static void
  3065. signal_handler(int signo)
  3066. {
  3067. gotsig[signo - 1] = 1;
  3068. if (signo == SIGINT && !trap[SIGINT]) {
  3069. if (!suppress_int) {
  3070. pending_sig = 0;
  3071. raise_interrupt(); /* does not return */
  3072. }
  3073. pending_int = 1;
  3074. } else {
  3075. pending_sig = signo;
  3076. }
  3077. }
  3078. /*
  3079. * Set the signal handler for the specified signal. The routine figures
  3080. * out what it should be set to.
  3081. */
  3082. static void
  3083. setsignal(int signo)
  3084. {
  3085. char *t;
  3086. char cur_act, new_act;
  3087. struct sigaction act;
  3088. t = trap[signo];
  3089. new_act = S_DFL;
  3090. if (t != NULL) { /* trap for this sig is set */
  3091. new_act = S_CATCH;
  3092. if (t[0] == '\0') /* trap is "": ignore this sig */
  3093. new_act = S_IGN;
  3094. }
  3095. if (rootshell && new_act == S_DFL) {
  3096. switch (signo) {
  3097. case SIGINT:
  3098. if (iflag || minusc || sflag == 0)
  3099. new_act = S_CATCH;
  3100. break;
  3101. case SIGQUIT:
  3102. #if DEBUG
  3103. if (debug)
  3104. break;
  3105. #endif
  3106. /* man bash:
  3107. * "In all cases, bash ignores SIGQUIT. Non-builtin
  3108. * commands run by bash have signal handlers
  3109. * set to the values inherited by the shell
  3110. * from its parent". */
  3111. new_act = S_IGN;
  3112. break;
  3113. case SIGTERM:
  3114. if (iflag)
  3115. new_act = S_IGN;
  3116. break;
  3117. #if JOBS
  3118. case SIGTSTP:
  3119. case SIGTTOU:
  3120. if (mflag)
  3121. new_act = S_IGN;
  3122. break;
  3123. #endif
  3124. }
  3125. }
  3126. //TODO: if !rootshell, we reset SIGQUIT to DFL,
  3127. //whereas we have to restore it to what shell got on entry
  3128. //from the parent. See comment above
  3129. t = &sigmode[signo - 1];
  3130. cur_act = *t;
  3131. if (cur_act == 0) {
  3132. /* current setting is not yet known */
  3133. if (sigaction(signo, NULL, &act)) {
  3134. /* pretend it worked; maybe we should give a warning,
  3135. * but other shells don't. We don't alter sigmode,
  3136. * so we retry every time.
  3137. * btw, in Linux it never fails. --vda */
  3138. return;
  3139. }
  3140. if (act.sa_handler == SIG_IGN) {
  3141. cur_act = S_HARD_IGN;
  3142. if (mflag
  3143. && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
  3144. ) {
  3145. cur_act = S_IGN; /* don't hard ignore these */
  3146. }
  3147. }
  3148. }
  3149. if (cur_act == S_HARD_IGN || cur_act == new_act)
  3150. return;
  3151. act.sa_handler = SIG_DFL;
  3152. switch (new_act) {
  3153. case S_CATCH:
  3154. act.sa_handler = signal_handler;
  3155. break;
  3156. case S_IGN:
  3157. act.sa_handler = SIG_IGN;
  3158. break;
  3159. }
  3160. /* flags and mask matter only if !DFL and !IGN, but we do it
  3161. * for all cases for more deterministic behavior:
  3162. */
  3163. act.sa_flags = 0;
  3164. sigfillset(&act.sa_mask);
  3165. sigaction_set(signo, &act);
  3166. *t = new_act;
  3167. }
  3168. /* mode flags for set_curjob */
  3169. #define CUR_DELETE 2
  3170. #define CUR_RUNNING 1
  3171. #define CUR_STOPPED 0
  3172. /* mode flags for dowait */
  3173. #define DOWAIT_NONBLOCK WNOHANG
  3174. #define DOWAIT_BLOCK 0
  3175. #if JOBS
  3176. /* pgrp of shell on invocation */
  3177. static int initialpgrp; //references:2
  3178. static int ttyfd = -1; //5
  3179. #endif
  3180. /* array of jobs */
  3181. static struct job *jobtab; //5
  3182. /* size of array */
  3183. static unsigned njobs; //4
  3184. /* current job */
  3185. static struct job *curjob; //lots
  3186. /* number of presumed living untracked jobs */
  3187. static int jobless; //4
  3188. static void
  3189. set_curjob(struct job *jp, unsigned mode)
  3190. {
  3191. struct job *jp1;
  3192. struct job **jpp, **curp;
  3193. /* first remove from list */
  3194. jpp = curp = &curjob;
  3195. while (1) {
  3196. jp1 = *jpp;
  3197. if (jp1 == jp)
  3198. break;
  3199. jpp = &jp1->prev_job;
  3200. }
  3201. *jpp = jp1->prev_job;
  3202. /* Then re-insert in correct position */
  3203. jpp = curp;
  3204. switch (mode) {
  3205. default:
  3206. #if DEBUG
  3207. abort();
  3208. #endif
  3209. case CUR_DELETE:
  3210. /* job being deleted */
  3211. break;
  3212. case CUR_RUNNING:
  3213. /* newly created job or backgrounded job,
  3214. * put after all stopped jobs.
  3215. */
  3216. while (1) {
  3217. jp1 = *jpp;
  3218. #if JOBS
  3219. if (!jp1 || jp1->state != JOBSTOPPED)
  3220. #endif
  3221. break;
  3222. jpp = &jp1->prev_job;
  3223. }
  3224. /* FALLTHROUGH */
  3225. #if JOBS
  3226. case CUR_STOPPED:
  3227. #endif
  3228. /* newly stopped job - becomes curjob */
  3229. jp->prev_job = *jpp;
  3230. *jpp = jp;
  3231. break;
  3232. }
  3233. }
  3234. #if JOBS || DEBUG
  3235. static int
  3236. jobno(const struct job *jp)
  3237. {
  3238. return jp - jobtab + 1;
  3239. }
  3240. #endif
  3241. /*
  3242. * Convert a job name to a job structure.
  3243. */
  3244. #if !JOBS
  3245. #define getjob(name, getctl) getjob(name)
  3246. #endif
  3247. static struct job *
  3248. getjob(const char *name, int getctl)
  3249. {
  3250. struct job *jp;
  3251. struct job *found;
  3252. const char *err_msg = "%s: no such job";
  3253. unsigned num;
  3254. int c;
  3255. const char *p;
  3256. char *(*match)(const char *, const char *);
  3257. jp = curjob;
  3258. p = name;
  3259. if (!p)
  3260. goto currentjob;
  3261. if (*p != '%')
  3262. goto err;
  3263. c = *++p;
  3264. if (!c)
  3265. goto currentjob;
  3266. if (!p[1]) {
  3267. if (c == '+' || c == '%') {
  3268. currentjob:
  3269. err_msg = "No current job";
  3270. goto check;
  3271. }
  3272. if (c == '-') {
  3273. if (jp)
  3274. jp = jp->prev_job;
  3275. err_msg = "No previous job";
  3276. check:
  3277. if (!jp)
  3278. goto err;
  3279. goto gotit;
  3280. }
  3281. }
  3282. if (is_number(p)) {
  3283. num = atoi(p);
  3284. if (num <= njobs) {
  3285. jp = jobtab + num - 1;
  3286. if (jp->used)
  3287. goto gotit;
  3288. goto err;
  3289. }
  3290. }
  3291. match = prefix;
  3292. if (*p == '?') {
  3293. match = strstr;
  3294. p++;
  3295. }
  3296. found = NULL;
  3297. while (jp) {
  3298. if (match(jp->ps[0].ps_cmd, p)) {
  3299. if (found)
  3300. goto err;
  3301. found = jp;
  3302. err_msg = "%s: ambiguous";
  3303. }
  3304. jp = jp->prev_job;
  3305. }
  3306. if (!found)
  3307. goto err;
  3308. jp = found;
  3309. gotit:
  3310. #if JOBS
  3311. err_msg = "job %s not created under job control";
  3312. if (getctl && jp->jobctl == 0)
  3313. goto err;
  3314. #endif
  3315. return jp;
  3316. err:
  3317. ash_msg_and_raise_error(err_msg, name);
  3318. }
  3319. /*
  3320. * Mark a job structure as unused.
  3321. */
  3322. static void
  3323. freejob(struct job *jp)
  3324. {
  3325. struct procstat *ps;
  3326. int i;
  3327. INT_OFF;
  3328. for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
  3329. if (ps->ps_cmd != nullstr)
  3330. free(ps->ps_cmd);
  3331. }
  3332. if (jp->ps != &jp->ps0)
  3333. free(jp->ps);
  3334. jp->used = 0;
  3335. set_curjob(jp, CUR_DELETE);
  3336. INT_ON;
  3337. }
  3338. #if JOBS
  3339. static void
  3340. xtcsetpgrp(int fd, pid_t pgrp)
  3341. {
  3342. if (tcsetpgrp(fd, pgrp))
  3343. ash_msg_and_raise_error("can't set tty process group (%m)");
  3344. }
  3345. /*
  3346. * Turn job control on and off.
  3347. *
  3348. * Note: This code assumes that the third arg to ioctl is a character
  3349. * pointer, which is true on Berkeley systems but not System V. Since
  3350. * System V doesn't have job control yet, this isn't a problem now.
  3351. *
  3352. * Called with interrupts off.
  3353. */
  3354. static void
  3355. setjobctl(int on)
  3356. {
  3357. int fd;
  3358. int pgrp;
  3359. if (on == doing_jobctl || rootshell == 0)
  3360. return;
  3361. if (on) {
  3362. int ofd;
  3363. ofd = fd = open(_PATH_TTY, O_RDWR);
  3364. if (fd < 0) {
  3365. /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
  3366. * That sometimes helps to acquire controlling tty.
  3367. * Obviously, a workaround for bugs when someone
  3368. * failed to provide a controlling tty to bash! :) */
  3369. fd = 2;
  3370. while (!isatty(fd))
  3371. if (--fd < 0)
  3372. goto out;
  3373. }
  3374. fd = fcntl(fd, F_DUPFD, 10);
  3375. if (ofd >= 0)
  3376. close(ofd);
  3377. if (fd < 0)
  3378. goto out;
  3379. /* fd is a tty at this point */
  3380. close_on_exec_on(fd);
  3381. while (1) { /* while we are in the background */
  3382. pgrp = tcgetpgrp(fd);
  3383. if (pgrp < 0) {
  3384. out:
  3385. ash_msg("can't access tty; job control turned off");
  3386. mflag = on = 0;
  3387. goto close;
  3388. }
  3389. if (pgrp == getpgrp())
  3390. break;
  3391. killpg(0, SIGTTIN);
  3392. }
  3393. initialpgrp = pgrp;
  3394. setsignal(SIGTSTP);
  3395. setsignal(SIGTTOU);
  3396. setsignal(SIGTTIN);
  3397. pgrp = rootpid;
  3398. setpgid(0, pgrp);
  3399. xtcsetpgrp(fd, pgrp);
  3400. } else {
  3401. /* turning job control off */
  3402. fd = ttyfd;
  3403. pgrp = initialpgrp;
  3404. /* was xtcsetpgrp, but this can make exiting ash
  3405. * loop forever if pty is already deleted */
  3406. tcsetpgrp(fd, pgrp);
  3407. setpgid(0, pgrp);
  3408. setsignal(SIGTSTP);
  3409. setsignal(SIGTTOU);
  3410. setsignal(SIGTTIN);
  3411. close:
  3412. if (fd >= 0)
  3413. close(fd);
  3414. fd = -1;
  3415. }
  3416. ttyfd = fd;
  3417. doing_jobctl = on;
  3418. }
  3419. static int FAST_FUNC
  3420. killcmd(int argc, char **argv)
  3421. {
  3422. if (argv[1] && strcmp(argv[1], "-l") != 0) {
  3423. int i = 1;
  3424. do {
  3425. if (argv[i][0] == '%') {
  3426. /*
  3427. * "kill %N" - job kill
  3428. * Converting to pgrp / pid kill
  3429. */
  3430. struct job *jp;
  3431. char *dst;
  3432. int j, n;
  3433. jp = getjob(argv[i], 0);
  3434. /*
  3435. * In jobs started under job control, we signal
  3436. * entire process group by kill -PGRP_ID.
  3437. * This happens, f.e., in interactive shell.
  3438. *
  3439. * Otherwise, we signal each child via
  3440. * kill PID1 PID2 PID3.
  3441. * Testcases:
  3442. * sh -c 'sleep 1|sleep 1 & kill %1'
  3443. * sh -c 'true|sleep 2 & sleep 1; kill %1'
  3444. * sh -c 'true|sleep 1 & sleep 2; kill %1'
  3445. */
  3446. n = jp->nprocs; /* can't be 0 (I hope) */
  3447. if (jp->jobctl)
  3448. n = 1;
  3449. dst = alloca(n * sizeof(int)*4);
  3450. argv[i] = dst;
  3451. for (j = 0; j < n; j++) {
  3452. struct procstat *ps = &jp->ps[j];
  3453. /* Skip non-running and not-stopped members
  3454. * (i.e. dead members) of the job
  3455. */
  3456. if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
  3457. continue;
  3458. /*
  3459. * kill_main has matching code to expect
  3460. * leading space. Needed to not confuse
  3461. * negative pids with "kill -SIGNAL_NO" syntax
  3462. */
  3463. dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
  3464. }
  3465. *dst = '\0';
  3466. }
  3467. } while (argv[++i]);
  3468. }
  3469. return kill_main(argc, argv);
  3470. }
  3471. static void
  3472. showpipe(struct job *jp /*, FILE *out*/)
  3473. {
  3474. struct procstat *ps;
  3475. struct procstat *psend;
  3476. psend = jp->ps + jp->nprocs;
  3477. for (ps = jp->ps + 1; ps < psend; ps++)
  3478. printf(" | %s", ps->ps_cmd);
  3479. outcslow('\n', stdout);
  3480. flush_stdout_stderr();
  3481. }
  3482. static int
  3483. restartjob(struct job *jp, int mode)
  3484. {
  3485. struct procstat *ps;
  3486. int i;
  3487. int status;
  3488. pid_t pgid;
  3489. INT_OFF;
  3490. if (jp->state == JOBDONE)
  3491. goto out;
  3492. jp->state = JOBRUNNING;
  3493. pgid = jp->ps[0].ps_pid;
  3494. if (mode == FORK_FG)
  3495. xtcsetpgrp(ttyfd, pgid);
  3496. killpg(pgid, SIGCONT);
  3497. ps = jp->ps;
  3498. i = jp->nprocs;
  3499. do {
  3500. if (WIFSTOPPED(ps->ps_status)) {
  3501. ps->ps_status = -1;
  3502. }
  3503. ps++;
  3504. } while (--i);
  3505. out:
  3506. status = (mode == FORK_FG) ? waitforjob(jp) : 0;
  3507. INT_ON;
  3508. return status;
  3509. }
  3510. static int FAST_FUNC
  3511. fg_bgcmd(int argc UNUSED_PARAM, char **argv)
  3512. {
  3513. struct job *jp;
  3514. int mode;
  3515. int retval;
  3516. mode = (**argv == 'f') ? FORK_FG : FORK_BG;
  3517. nextopt(nullstr);
  3518. argv = argptr;
  3519. do {
  3520. jp = getjob(*argv, 1);
  3521. if (mode == FORK_BG) {
  3522. set_curjob(jp, CUR_RUNNING);
  3523. printf("[%d] ", jobno(jp));
  3524. }
  3525. out1str(jp->ps[0].ps_cmd);
  3526. showpipe(jp /*, stdout*/);
  3527. retval = restartjob(jp, mode);
  3528. } while (*argv && *++argv);
  3529. return retval;
  3530. }
  3531. #endif
  3532. static int
  3533. sprint_status(char *s, int status, int sigonly)
  3534. {
  3535. int col;
  3536. int st;
  3537. col = 0;
  3538. if (!WIFEXITED(status)) {
  3539. #if JOBS
  3540. if (WIFSTOPPED(status))
  3541. st = WSTOPSIG(status);
  3542. else
  3543. #endif
  3544. st = WTERMSIG(status);
  3545. if (sigonly) {
  3546. if (st == SIGINT || st == SIGPIPE)
  3547. goto out;
  3548. #if JOBS
  3549. if (WIFSTOPPED(status))
  3550. goto out;
  3551. #endif
  3552. }
  3553. st &= 0x7f;
  3554. //TODO: use bbox's get_signame? strsignal adds ~600 bytes to text+rodata
  3555. col = fmtstr(s, 32, strsignal(st));
  3556. if (WCOREDUMP(status)) {
  3557. col += fmtstr(s + col, 16, " (core dumped)");
  3558. }
  3559. } else if (!sigonly) {
  3560. st = WEXITSTATUS(status);
  3561. if (st)
  3562. col = fmtstr(s, 16, "Done(%d)", st);
  3563. else
  3564. col = fmtstr(s, 16, "Done");
  3565. }
  3566. out:
  3567. return col;
  3568. }
  3569. static int
  3570. dowait(int wait_flags, struct job *job)
  3571. {
  3572. int pid;
  3573. int status;
  3574. struct job *jp;
  3575. struct job *thisjob;
  3576. int state;
  3577. TRACE(("dowait(0x%x) called\n", wait_flags));
  3578. /* Do a wait system call. If job control is compiled in, we accept
  3579. * stopped processes. wait_flags may have WNOHANG, preventing blocking.
  3580. * NB: _not_ safe_waitpid, we need to detect EINTR */
  3581. if (doing_jobctl)
  3582. wait_flags |= WUNTRACED;
  3583. pid = waitpid(-1, &status, wait_flags);
  3584. TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n",
  3585. pid, status, errno, strerror(errno)));
  3586. if (pid <= 0)
  3587. return pid;
  3588. INT_OFF;
  3589. thisjob = NULL;
  3590. for (jp = curjob; jp; jp = jp->prev_job) {
  3591. struct procstat *ps;
  3592. struct procstat *psend;
  3593. if (jp->state == JOBDONE)
  3594. continue;
  3595. state = JOBDONE;
  3596. ps = jp->ps;
  3597. psend = ps + jp->nprocs;
  3598. do {
  3599. if (ps->ps_pid == pid) {
  3600. TRACE(("Job %d: changing status of proc %d "
  3601. "from 0x%x to 0x%x\n",
  3602. jobno(jp), pid, ps->ps_status, status));
  3603. ps->ps_status = status;
  3604. thisjob = jp;
  3605. }
  3606. if (ps->ps_status == -1)
  3607. state = JOBRUNNING;
  3608. #if JOBS
  3609. if (state == JOBRUNNING)
  3610. continue;
  3611. if (WIFSTOPPED(ps->ps_status)) {
  3612. jp->stopstatus = ps->ps_status;
  3613. state = JOBSTOPPED;
  3614. }
  3615. #endif
  3616. } while (++ps < psend);
  3617. if (thisjob)
  3618. goto gotjob;
  3619. }
  3620. #if JOBS
  3621. if (!WIFSTOPPED(status))
  3622. #endif
  3623. jobless--;
  3624. goto out;
  3625. gotjob:
  3626. if (state != JOBRUNNING) {
  3627. thisjob->changed = 1;
  3628. if (thisjob->state != state) {
  3629. TRACE(("Job %d: changing state from %d to %d\n",
  3630. jobno(thisjob), thisjob->state, state));
  3631. thisjob->state = state;
  3632. #if JOBS
  3633. if (state == JOBSTOPPED) {
  3634. set_curjob(thisjob, CUR_STOPPED);
  3635. }
  3636. #endif
  3637. }
  3638. }
  3639. out:
  3640. INT_ON;
  3641. if (thisjob && thisjob == job) {
  3642. char s[48 + 1];
  3643. int len;
  3644. len = sprint_status(s, status, 1);
  3645. if (len) {
  3646. s[len] = '\n';
  3647. s[len + 1] = '\0';
  3648. out2str(s);
  3649. }
  3650. }
  3651. return pid;
  3652. }
  3653. static int
  3654. blocking_wait_with_raise_on_sig(void)
  3655. {
  3656. pid_t pid = dowait(DOWAIT_BLOCK, NULL);
  3657. if (pid <= 0 && pending_sig)
  3658. raise_exception(EXSIG);
  3659. return pid;
  3660. }
  3661. #if JOBS
  3662. static void
  3663. showjob(FILE *out, struct job *jp, int mode)
  3664. {
  3665. struct procstat *ps;
  3666. struct procstat *psend;
  3667. int col;
  3668. int indent_col;
  3669. char s[80];
  3670. ps = jp->ps;
  3671. if (mode & SHOW_ONLY_PGID) { /* jobs -p */
  3672. /* just output process (group) id of pipeline */
  3673. fprintf(out, "%d\n", ps->ps_pid);
  3674. return;
  3675. }
  3676. col = fmtstr(s, 16, "[%d] ", jobno(jp));
  3677. indent_col = col;
  3678. if (jp == curjob)
  3679. s[col - 3] = '+';
  3680. else if (curjob && jp == curjob->prev_job)
  3681. s[col - 3] = '-';
  3682. if (mode & SHOW_PIDS)
  3683. col += fmtstr(s + col, 16, "%d ", ps->ps_pid);
  3684. psend = ps + jp->nprocs;
  3685. if (jp->state == JOBRUNNING) {
  3686. strcpy(s + col, "Running");
  3687. col += sizeof("Running") - 1;
  3688. } else {
  3689. int status = psend[-1].ps_status;
  3690. if (jp->state == JOBSTOPPED)
  3691. status = jp->stopstatus;
  3692. col += sprint_status(s + col, status, 0);
  3693. }
  3694. /* By now, "[JOBID]* [maybe PID] STATUS" is printed */
  3695. /* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
  3696. * or prints several "PID | <cmdN>" lines,
  3697. * depending on SHOW_PIDS bit.
  3698. * We do not print status of individual processes
  3699. * between PID and <cmdN>. bash does it, but not very well:
  3700. * first line shows overall job status, not process status,
  3701. * making it impossible to know 1st process status.
  3702. */
  3703. goto start;
  3704. do {
  3705. /* for each process */
  3706. s[0] = '\0';
  3707. col = 33;
  3708. if (mode & SHOW_PIDS)
  3709. col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->ps_pid) - 1;
  3710. start:
  3711. fprintf(out, "%s%*c%s%s",
  3712. s,
  3713. 33 - col >= 0 ? 33 - col : 0, ' ',
  3714. ps == jp->ps ? "" : "| ",
  3715. ps->ps_cmd
  3716. );
  3717. } while (++ps != psend);
  3718. outcslow('\n', out);
  3719. jp->changed = 0;
  3720. if (jp->state == JOBDONE) {
  3721. TRACE(("showjob: freeing job %d\n", jobno(jp)));
  3722. freejob(jp);
  3723. }
  3724. }
  3725. /*
  3726. * Print a list of jobs. If "change" is nonzero, only print jobs whose
  3727. * statuses have changed since the last call to showjobs.
  3728. */
  3729. static void
  3730. showjobs(FILE *out, int mode)
  3731. {
  3732. struct job *jp;
  3733. TRACE(("showjobs(0x%x) called\n", mode));
  3734. /* Handle all finished jobs */
  3735. while (dowait(DOWAIT_NONBLOCK, NULL) > 0)
  3736. continue;
  3737. for (jp = curjob; jp; jp = jp->prev_job) {
  3738. if (!(mode & SHOW_CHANGED) || jp->changed) {
  3739. showjob(out, jp, mode);
  3740. }
  3741. }
  3742. }
  3743. static int FAST_FUNC
  3744. jobscmd(int argc UNUSED_PARAM, char **argv)
  3745. {
  3746. int mode, m;
  3747. mode = 0;
  3748. while ((m = nextopt("lp")) != '\0') {
  3749. if (m == 'l')
  3750. mode |= SHOW_PIDS;
  3751. else
  3752. mode |= SHOW_ONLY_PGID;
  3753. }
  3754. argv = argptr;
  3755. if (*argv) {
  3756. do
  3757. showjob(stdout, getjob(*argv, 0), mode);
  3758. while (*++argv);
  3759. } else {
  3760. showjobs(stdout, mode);
  3761. }
  3762. return 0;
  3763. }
  3764. #endif /* JOBS */
  3765. /* Called only on finished or stopped jobs (no members are running) */
  3766. static int
  3767. getstatus(struct job *job)
  3768. {
  3769. int status;
  3770. int retval;
  3771. struct procstat *ps;
  3772. /* Fetch last member's status */
  3773. ps = job->ps + job->nprocs - 1;
  3774. status = ps->ps_status;
  3775. if (pipefail) {
  3776. /* "set -o pipefail" mode: use last _nonzero_ status */
  3777. while (status == 0 && --ps >= job->ps)
  3778. status = ps->ps_status;
  3779. }
  3780. retval = WEXITSTATUS(status);
  3781. if (!WIFEXITED(status)) {
  3782. #if JOBS
  3783. retval = WSTOPSIG(status);
  3784. if (!WIFSTOPPED(status))
  3785. #endif
  3786. {
  3787. /* XXX: limits number of signals */
  3788. retval = WTERMSIG(status);
  3789. #if JOBS
  3790. if (retval == SIGINT)
  3791. job->sigint = 1;
  3792. #endif
  3793. }
  3794. retval += 128;
  3795. }
  3796. TRACE(("getstatus: job %d, nproc %d, status 0x%x, retval 0x%x\n",
  3797. jobno(job), job->nprocs, status, retval));
  3798. return retval;
  3799. }
  3800. static int FAST_FUNC
  3801. waitcmd(int argc UNUSED_PARAM, char **argv)
  3802. {
  3803. struct job *job;
  3804. int retval;
  3805. struct job *jp;
  3806. if (pending_sig)
  3807. raise_exception(EXSIG);
  3808. nextopt(nullstr);
  3809. retval = 0;
  3810. argv = argptr;
  3811. if (!*argv) {
  3812. /* wait for all jobs */
  3813. for (;;) {
  3814. jp = curjob;
  3815. while (1) {
  3816. if (!jp) /* no running procs */
  3817. goto ret;
  3818. if (jp->state == JOBRUNNING)
  3819. break;
  3820. jp->waited = 1;
  3821. jp = jp->prev_job;
  3822. }
  3823. blocking_wait_with_raise_on_sig();
  3824. /* man bash:
  3825. * "When bash is waiting for an asynchronous command via
  3826. * the wait builtin, the reception of a signal for which a trap
  3827. * has been set will cause the wait builtin to return immediately
  3828. * with an exit status greater than 128, immediately after which
  3829. * the trap is executed."
  3830. *
  3831. * blocking_wait_with_raise_on_sig raises signal handlers
  3832. * if it gets no pid (pid < 0). However,
  3833. * if child sends us a signal *and immediately exits*,
  3834. * blocking_wait_with_raise_on_sig gets pid > 0
  3835. * and does not handle pending_sig. Check this case: */
  3836. if (pending_sig)
  3837. raise_exception(EXSIG);
  3838. }
  3839. }
  3840. retval = 127;
  3841. do {
  3842. if (**argv != '%') {
  3843. pid_t pid = number(*argv);
  3844. job = curjob;
  3845. while (1) {
  3846. if (!job)
  3847. goto repeat;
  3848. if (job->ps[job->nprocs - 1].ps_pid == pid)
  3849. break;
  3850. job = job->prev_job;
  3851. }
  3852. } else {
  3853. job = getjob(*argv, 0);
  3854. }
  3855. /* loop until process terminated or stopped */
  3856. while (job->state == JOBRUNNING)
  3857. blocking_wait_with_raise_on_sig();
  3858. job->waited = 1;
  3859. retval = getstatus(job);
  3860. repeat: ;
  3861. } while (*++argv);
  3862. ret:
  3863. return retval;
  3864. }
  3865. static struct job *
  3866. growjobtab(void)
  3867. {
  3868. size_t len;
  3869. ptrdiff_t offset;
  3870. struct job *jp, *jq;
  3871. len = njobs * sizeof(*jp);
  3872. jq = jobtab;
  3873. jp = ckrealloc(jq, len + 4 * sizeof(*jp));
  3874. offset = (char *)jp - (char *)jq;
  3875. if (offset) {
  3876. /* Relocate pointers */
  3877. size_t l = len;
  3878. jq = (struct job *)((char *)jq + l);
  3879. while (l) {
  3880. l -= sizeof(*jp);
  3881. jq--;
  3882. #define joff(p) ((struct job *)((char *)(p) + l))
  3883. #define jmove(p) (p) = (void *)((char *)(p) + offset)
  3884. if (joff(jp)->ps == &jq->ps0)
  3885. jmove(joff(jp)->ps);
  3886. if (joff(jp)->prev_job)
  3887. jmove(joff(jp)->prev_job);
  3888. }
  3889. if (curjob)
  3890. jmove(curjob);
  3891. #undef joff
  3892. #undef jmove
  3893. }
  3894. njobs += 4;
  3895. jobtab = jp;
  3896. jp = (struct job *)((char *)jp + len);
  3897. jq = jp + 3;
  3898. do {
  3899. jq->used = 0;
  3900. } while (--jq >= jp);
  3901. return jp;
  3902. }
  3903. /*
  3904. * Return a new job structure.
  3905. * Called with interrupts off.
  3906. */
  3907. static struct job *
  3908. makejob(/*union node *node,*/ int nprocs)
  3909. {
  3910. int i;
  3911. struct job *jp;
  3912. for (i = njobs, jp = jobtab; ; jp++) {
  3913. if (--i < 0) {
  3914. jp = growjobtab();
  3915. break;
  3916. }
  3917. if (jp->used == 0)
  3918. break;
  3919. if (jp->state != JOBDONE || !jp->waited)
  3920. continue;
  3921. #if JOBS
  3922. if (doing_jobctl)
  3923. continue;
  3924. #endif
  3925. freejob(jp);
  3926. break;
  3927. }
  3928. memset(jp, 0, sizeof(*jp));
  3929. #if JOBS
  3930. /* jp->jobctl is a bitfield.
  3931. * "jp->jobctl |= jobctl" likely to give awful code */
  3932. if (doing_jobctl)
  3933. jp->jobctl = 1;
  3934. #endif
  3935. jp->prev_job = curjob;
  3936. curjob = jp;
  3937. jp->used = 1;
  3938. jp->ps = &jp->ps0;
  3939. if (nprocs > 1) {
  3940. jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
  3941. }
  3942. TRACE(("makejob(%d) returns %%%d\n", nprocs,
  3943. jobno(jp)));
  3944. return jp;
  3945. }
  3946. #if JOBS
  3947. /*
  3948. * Return a string identifying a command (to be printed by the
  3949. * jobs command).
  3950. */
  3951. static char *cmdnextc;
  3952. static void
  3953. cmdputs(const char *s)
  3954. {
  3955. static const char vstype[VSTYPE + 1][3] = {
  3956. "", "}", "-", "+", "?", "=",
  3957. "%", "%%", "#", "##"
  3958. IF_ASH_BASH_COMPAT(, ":", "/", "//")
  3959. };
  3960. const char *p, *str;
  3961. char cc[2];
  3962. char *nextc;
  3963. unsigned char c;
  3964. unsigned char subtype = 0;
  3965. int quoted = 0;
  3966. cc[1] = '\0';
  3967. nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
  3968. p = s;
  3969. while ((c = *p++) != '\0') {
  3970. str = NULL;
  3971. switch (c) {
  3972. case CTLESC:
  3973. c = *p++;
  3974. break;
  3975. case CTLVAR:
  3976. subtype = *p++;
  3977. if ((subtype & VSTYPE) == VSLENGTH)
  3978. str = "${#";
  3979. else
  3980. str = "${";
  3981. if (!(subtype & VSQUOTE) == !(quoted & 1))
  3982. goto dostr;
  3983. quoted ^= 1;
  3984. c = '"';
  3985. break;
  3986. case CTLENDVAR:
  3987. str = "\"}" + !(quoted & 1);
  3988. quoted >>= 1;
  3989. subtype = 0;
  3990. goto dostr;
  3991. case CTLBACKQ:
  3992. str = "$(...)";
  3993. goto dostr;
  3994. case CTLBACKQ+CTLQUOTE:
  3995. str = "\"$(...)\"";
  3996. goto dostr;
  3997. #if ENABLE_SH_MATH_SUPPORT
  3998. case CTLARI:
  3999. str = "$((";
  4000. goto dostr;
  4001. case CTLENDARI:
  4002. str = "))";
  4003. goto dostr;
  4004. #endif
  4005. case CTLQUOTEMARK:
  4006. quoted ^= 1;
  4007. c = '"';
  4008. break;
  4009. case '=':
  4010. if (subtype == 0)
  4011. break;
  4012. if ((subtype & VSTYPE) != VSNORMAL)
  4013. quoted <<= 1;
  4014. str = vstype[subtype & VSTYPE];
  4015. if (subtype & VSNUL)
  4016. c = ':';
  4017. else
  4018. goto checkstr;
  4019. break;
  4020. case '\'':
  4021. case '\\':
  4022. case '"':
  4023. case '$':
  4024. /* These can only happen inside quotes */
  4025. cc[0] = c;
  4026. str = cc;
  4027. c = '\\';
  4028. break;
  4029. default:
  4030. break;
  4031. }
  4032. USTPUTC(c, nextc);
  4033. checkstr:
  4034. if (!str)
  4035. continue;
  4036. dostr:
  4037. while ((c = *str++) != '\0') {
  4038. USTPUTC(c, nextc);
  4039. }
  4040. } /* while *p++ not NUL */
  4041. if (quoted & 1) {
  4042. USTPUTC('"', nextc);
  4043. }
  4044. *nextc = 0;
  4045. cmdnextc = nextc;
  4046. }
  4047. /* cmdtxt() and cmdlist() call each other */
  4048. static void cmdtxt(union node *n);
  4049. static void
  4050. cmdlist(union node *np, int sep)
  4051. {
  4052. for (; np; np = np->narg.next) {
  4053. if (!sep)
  4054. cmdputs(" ");
  4055. cmdtxt(np);
  4056. if (sep && np->narg.next)
  4057. cmdputs(" ");
  4058. }
  4059. }
  4060. static void
  4061. cmdtxt(union node *n)
  4062. {
  4063. union node *np;
  4064. struct nodelist *lp;
  4065. const char *p;
  4066. if (!n)
  4067. return;
  4068. switch (n->type) {
  4069. default:
  4070. #if DEBUG
  4071. abort();
  4072. #endif
  4073. case NPIPE:
  4074. lp = n->npipe.cmdlist;
  4075. for (;;) {
  4076. cmdtxt(lp->n);
  4077. lp = lp->next;
  4078. if (!lp)
  4079. break;
  4080. cmdputs(" | ");
  4081. }
  4082. break;
  4083. case NSEMI:
  4084. p = "; ";
  4085. goto binop;
  4086. case NAND:
  4087. p = " && ";
  4088. goto binop;
  4089. case NOR:
  4090. p = " || ";
  4091. binop:
  4092. cmdtxt(n->nbinary.ch1);
  4093. cmdputs(p);
  4094. n = n->nbinary.ch2;
  4095. goto donode;
  4096. case NREDIR:
  4097. case NBACKGND:
  4098. n = n->nredir.n;
  4099. goto donode;
  4100. case NNOT:
  4101. cmdputs("!");
  4102. n = n->nnot.com;
  4103. donode:
  4104. cmdtxt(n);
  4105. break;
  4106. case NIF:
  4107. cmdputs("if ");
  4108. cmdtxt(n->nif.test);
  4109. cmdputs("; then ");
  4110. if (n->nif.elsepart) {
  4111. cmdtxt(n->nif.ifpart);
  4112. cmdputs("; else ");
  4113. n = n->nif.elsepart;
  4114. } else {
  4115. n = n->nif.ifpart;
  4116. }
  4117. p = "; fi";
  4118. goto dotail;
  4119. case NSUBSHELL:
  4120. cmdputs("(");
  4121. n = n->nredir.n;
  4122. p = ")";
  4123. goto dotail;
  4124. case NWHILE:
  4125. p = "while ";
  4126. goto until;
  4127. case NUNTIL:
  4128. p = "until ";
  4129. until:
  4130. cmdputs(p);
  4131. cmdtxt(n->nbinary.ch1);
  4132. n = n->nbinary.ch2;
  4133. p = "; done";
  4134. dodo:
  4135. cmdputs("; do ");
  4136. dotail:
  4137. cmdtxt(n);
  4138. goto dotail2;
  4139. case NFOR:
  4140. cmdputs("for ");
  4141. cmdputs(n->nfor.var);
  4142. cmdputs(" in ");
  4143. cmdlist(n->nfor.args, 1);
  4144. n = n->nfor.body;
  4145. p = "; done";
  4146. goto dodo;
  4147. case NDEFUN:
  4148. cmdputs(n->narg.text);
  4149. p = "() { ... }";
  4150. goto dotail2;
  4151. case NCMD:
  4152. cmdlist(n->ncmd.args, 1);
  4153. cmdlist(n->ncmd.redirect, 0);
  4154. break;
  4155. case NARG:
  4156. p = n->narg.text;
  4157. dotail2:
  4158. cmdputs(p);
  4159. break;
  4160. case NHERE:
  4161. case NXHERE:
  4162. p = "<<...";
  4163. goto dotail2;
  4164. case NCASE:
  4165. cmdputs("case ");
  4166. cmdputs(n->ncase.expr->narg.text);
  4167. cmdputs(" in ");
  4168. for (np = n->ncase.cases; np; np = np->nclist.next) {
  4169. cmdtxt(np->nclist.pattern);
  4170. cmdputs(") ");
  4171. cmdtxt(np->nclist.body);
  4172. cmdputs(";; ");
  4173. }
  4174. p = "esac";
  4175. goto dotail2;
  4176. case NTO:
  4177. p = ">";
  4178. goto redir;
  4179. case NCLOBBER:
  4180. p = ">|";
  4181. goto redir;
  4182. case NAPPEND:
  4183. p = ">>";
  4184. goto redir;
  4185. #if ENABLE_ASH_BASH_COMPAT
  4186. case NTO2:
  4187. #endif
  4188. case NTOFD:
  4189. p = ">&";
  4190. goto redir;
  4191. case NFROM:
  4192. p = "<";
  4193. goto redir;
  4194. case NFROMFD:
  4195. p = "<&";
  4196. goto redir;
  4197. case NFROMTO:
  4198. p = "<>";
  4199. redir:
  4200. cmdputs(utoa(n->nfile.fd));
  4201. cmdputs(p);
  4202. if (n->type == NTOFD || n->type == NFROMFD) {
  4203. cmdputs(utoa(n->ndup.dupfd));
  4204. break;
  4205. }
  4206. n = n->nfile.fname;
  4207. goto donode;
  4208. }
  4209. }
  4210. static char *
  4211. commandtext(union node *n)
  4212. {
  4213. char *name;
  4214. STARTSTACKSTR(cmdnextc);
  4215. cmdtxt(n);
  4216. name = stackblock();
  4217. TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
  4218. name, cmdnextc, cmdnextc));
  4219. return ckstrdup(name);
  4220. }
  4221. #endif /* JOBS */
  4222. /*
  4223. * Fork off a subshell. If we are doing job control, give the subshell its
  4224. * own process group. Jp is a job structure that the job is to be added to.
  4225. * N is the command that will be evaluated by the child. Both jp and n may
  4226. * be NULL. The mode parameter can be one of the following:
  4227. * FORK_FG - Fork off a foreground process.
  4228. * FORK_BG - Fork off a background process.
  4229. * FORK_NOJOB - Like FORK_FG, but don't give the process its own
  4230. * process group even if job control is on.
  4231. *
  4232. * When job control is turned off, background processes have their standard
  4233. * input redirected to /dev/null (except for the second and later processes
  4234. * in a pipeline).
  4235. *
  4236. * Called with interrupts off.
  4237. */
  4238. /*
  4239. * Clear traps on a fork.
  4240. */
  4241. static void
  4242. clear_traps(void)
  4243. {
  4244. char **tp;
  4245. for (tp = trap; tp < &trap[NSIG]; tp++) {
  4246. if (*tp && **tp) { /* trap not NULL or "" (SIG_IGN) */
  4247. INT_OFF;
  4248. if (trap_ptr == trap)
  4249. free(*tp);
  4250. /* else: it "belongs" to trap_ptr vector, don't free */
  4251. *tp = NULL;
  4252. if ((tp - trap) != 0)
  4253. setsignal(tp - trap);
  4254. INT_ON;
  4255. }
  4256. }
  4257. may_have_traps = 0;
  4258. }
  4259. /* Lives far away from here, needed for forkchild */
  4260. static void closescript(void);
  4261. /* Called after fork(), in child */
  4262. static NOINLINE void
  4263. forkchild(struct job *jp, union node *n, int mode)
  4264. {
  4265. int oldlvl;
  4266. TRACE(("Child shell %d\n", getpid()));
  4267. oldlvl = shlvl;
  4268. shlvl++;
  4269. /* man bash: "Non-builtin commands run by bash have signal handlers
  4270. * set to the values inherited by the shell from its parent".
  4271. * Do we do it correctly? */
  4272. closescript();
  4273. if (mode == FORK_NOJOB /* is it `xxx` ? */
  4274. && n && n->type == NCMD /* is it single cmd? */
  4275. /* && n->ncmd.args->type == NARG - always true? */
  4276. && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "trap") == 0
  4277. && n->ncmd.args->narg.next == NULL /* "trap" with no arguments */
  4278. /* && n->ncmd.args->narg.backquote == NULL - do we need to check this? */
  4279. ) {
  4280. TRACE(("Trap hack\n"));
  4281. /* Awful hack for `trap` or $(trap).
  4282. *
  4283. * http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html
  4284. * contains an example where "trap" is executed in a subshell:
  4285. *
  4286. * save_traps=$(trap)
  4287. * ...
  4288. * eval "$save_traps"
  4289. *
  4290. * Standard does not say that "trap" in subshell shall print
  4291. * parent shell's traps. It only says that its output
  4292. * must have suitable form, but then, in the above example
  4293. * (which is not supposed to be normative), it implies that.
  4294. *
  4295. * bash (and probably other shell) does implement it
  4296. * (traps are reset to defaults, but "trap" still shows them),
  4297. * but as a result, "trap" logic is hopelessly messed up:
  4298. *
  4299. * # trap
  4300. * trap -- 'echo Ho' SIGWINCH <--- we have a handler
  4301. * # (trap) <--- trap is in subshell - no output (correct, traps are reset)
  4302. * # true | trap <--- trap is in subshell - no output (ditto)
  4303. * # echo `true | trap` <--- in subshell - output (but traps are reset!)
  4304. * trap -- 'echo Ho' SIGWINCH
  4305. * # echo `(trap)` <--- in subshell in subshell - output
  4306. * trap -- 'echo Ho' SIGWINCH
  4307. * # echo `true | (trap)` <--- in subshell in subshell in subshell - output!
  4308. * trap -- 'echo Ho' SIGWINCH
  4309. *
  4310. * The rules when to forget and when to not forget traps
  4311. * get really complex and nonsensical.
  4312. *
  4313. * Our solution: ONLY bare $(trap) or `trap` is special.
  4314. */
  4315. /* Save trap handler strings for trap builtin to print */
  4316. trap_ptr = memcpy(xmalloc(sizeof(trap)), trap, sizeof(trap));
  4317. /* Fall through into clearing traps */
  4318. }
  4319. clear_traps();
  4320. #if JOBS
  4321. /* do job control only in root shell */
  4322. doing_jobctl = 0;
  4323. if (mode != FORK_NOJOB && jp->jobctl && oldlvl == 0) {
  4324. pid_t pgrp;
  4325. if (jp->nprocs == 0)
  4326. pgrp = getpid();
  4327. else
  4328. pgrp = jp->ps[0].ps_pid;
  4329. /* this can fail because we are doing it in the parent also */
  4330. setpgid(0, pgrp);
  4331. if (mode == FORK_FG)
  4332. xtcsetpgrp(ttyfd, pgrp);
  4333. setsignal(SIGTSTP);
  4334. setsignal(SIGTTOU);
  4335. } else
  4336. #endif
  4337. if (mode == FORK_BG) {
  4338. /* man bash: "When job control is not in effect,
  4339. * asynchronous commands ignore SIGINT and SIGQUIT" */
  4340. ignoresig(SIGINT);
  4341. ignoresig(SIGQUIT);
  4342. if (jp->nprocs == 0) {
  4343. close(0);
  4344. if (open(bb_dev_null, O_RDONLY) != 0)
  4345. ash_msg_and_raise_error("can't open '%s'", bb_dev_null);
  4346. }
  4347. }
  4348. if (oldlvl == 0) {
  4349. if (iflag) { /* why if iflag only? */
  4350. setsignal(SIGINT);
  4351. setsignal(SIGTERM);
  4352. }
  4353. /* man bash:
  4354. * "In all cases, bash ignores SIGQUIT. Non-builtin
  4355. * commands run by bash have signal handlers
  4356. * set to the values inherited by the shell
  4357. * from its parent".
  4358. * Take care of the second rule: */
  4359. setsignal(SIGQUIT);
  4360. }
  4361. #if JOBS
  4362. if (n && n->type == NCMD
  4363. && n->ncmd.args && strcmp(n->ncmd.args->narg.text, "jobs") == 0
  4364. ) {
  4365. TRACE(("Job hack\n"));
  4366. /* "jobs": we do not want to clear job list for it,
  4367. * instead we remove only _its_ own_ job from job list.
  4368. * This makes "jobs .... | cat" more useful.
  4369. */
  4370. freejob(curjob);
  4371. return;
  4372. }
  4373. #endif
  4374. for (jp = curjob; jp; jp = jp->prev_job)
  4375. freejob(jp);
  4376. jobless = 0;
  4377. }
  4378. /* Called after fork(), in parent */
  4379. #if !JOBS
  4380. #define forkparent(jp, n, mode, pid) forkparent(jp, mode, pid)
  4381. #endif
  4382. static void
  4383. forkparent(struct job *jp, union node *n, int mode, pid_t pid)
  4384. {
  4385. TRACE(("In parent shell: child = %d\n", pid));
  4386. if (!jp) {
  4387. while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0)
  4388. continue;
  4389. jobless++;
  4390. return;
  4391. }
  4392. #if JOBS
  4393. if (mode != FORK_NOJOB && jp->jobctl) {
  4394. int pgrp;
  4395. if (jp->nprocs == 0)
  4396. pgrp = pid;
  4397. else
  4398. pgrp = jp->ps[0].ps_pid;
  4399. /* This can fail because we are doing it in the child also */
  4400. setpgid(pid, pgrp);
  4401. }
  4402. #endif
  4403. if (mode == FORK_BG) {
  4404. backgndpid = pid; /* set $! */
  4405. set_curjob(jp, CUR_RUNNING);
  4406. }
  4407. if (jp) {
  4408. struct procstat *ps = &jp->ps[jp->nprocs++];
  4409. ps->ps_pid = pid;
  4410. ps->ps_status = -1;
  4411. ps->ps_cmd = nullstr;
  4412. #if JOBS
  4413. if (doing_jobctl && n)
  4414. ps->ps_cmd = commandtext(n);
  4415. #endif
  4416. }
  4417. }
  4418. static int
  4419. forkshell(struct job *jp, union node *n, int mode)
  4420. {
  4421. int pid;
  4422. TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
  4423. pid = fork();
  4424. if (pid < 0) {
  4425. TRACE(("Fork failed, errno=%d", errno));
  4426. if (jp)
  4427. freejob(jp);
  4428. ash_msg_and_raise_error("can't fork");
  4429. }
  4430. if (pid == 0) {
  4431. CLEAR_RANDOM_T(&random_gen); /* or else $RANDOM repeats in child */
  4432. forkchild(jp, n, mode);
  4433. } else {
  4434. forkparent(jp, n, mode, pid);
  4435. }
  4436. return pid;
  4437. }
  4438. /*
  4439. * Wait for job to finish.
  4440. *
  4441. * Under job control we have the problem that while a child process
  4442. * is running interrupts generated by the user are sent to the child
  4443. * but not to the shell. This means that an infinite loop started by
  4444. * an interactive user may be hard to kill. With job control turned off,
  4445. * an interactive user may place an interactive program inside a loop.
  4446. * If the interactive program catches interrupts, the user doesn't want
  4447. * these interrupts to also abort the loop. The approach we take here
  4448. * is to have the shell ignore interrupt signals while waiting for a
  4449. * foreground process to terminate, and then send itself an interrupt
  4450. * signal if the child process was terminated by an interrupt signal.
  4451. * Unfortunately, some programs want to do a bit of cleanup and then
  4452. * exit on interrupt; unless these processes terminate themselves by
  4453. * sending a signal to themselves (instead of calling exit) they will
  4454. * confuse this approach.
  4455. *
  4456. * Called with interrupts off.
  4457. */
  4458. static int
  4459. waitforjob(struct job *jp)
  4460. {
  4461. int st;
  4462. TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
  4463. INT_OFF;
  4464. while (jp->state == JOBRUNNING) {
  4465. /* In non-interactive shells, we _can_ get
  4466. * a keyboard signal here and be EINTRed,
  4467. * but we just loop back, waiting for command to complete.
  4468. *
  4469. * man bash:
  4470. * "If bash is waiting for a command to complete and receives
  4471. * a signal for which a trap has been set, the trap
  4472. * will not be executed until the command completes."
  4473. *
  4474. * Reality is that even if trap is not set, bash
  4475. * will not act on the signal until command completes.
  4476. * Try this. sleep5intoff.c:
  4477. * #include <signal.h>
  4478. * #include <unistd.h>
  4479. * int main() {
  4480. * sigset_t set;
  4481. * sigemptyset(&set);
  4482. * sigaddset(&set, SIGINT);
  4483. * sigaddset(&set, SIGQUIT);
  4484. * sigprocmask(SIG_BLOCK, &set, NULL);
  4485. * sleep(5);
  4486. * return 0;
  4487. * }
  4488. * $ bash -c './sleep5intoff; echo hi'
  4489. * ^C^C^C^C <--- pressing ^C once a second
  4490. * $ _
  4491. * $ bash -c './sleep5intoff; echo hi'
  4492. * ^\^\^\^\hi <--- pressing ^\ (SIGQUIT)
  4493. * $ _
  4494. */
  4495. dowait(DOWAIT_BLOCK, jp);
  4496. }
  4497. INT_ON;
  4498. st = getstatus(jp);
  4499. #if JOBS
  4500. if (jp->jobctl) {
  4501. xtcsetpgrp(ttyfd, rootpid);
  4502. /*
  4503. * This is truly gross.
  4504. * If we're doing job control, then we did a TIOCSPGRP which
  4505. * caused us (the shell) to no longer be in the controlling
  4506. * session -- so we wouldn't have seen any ^C/SIGINT. So, we
  4507. * intuit from the subprocess exit status whether a SIGINT
  4508. * occurred, and if so interrupt ourselves. Yuck. - mycroft
  4509. */
  4510. if (jp->sigint) /* TODO: do the same with all signals */
  4511. raise(SIGINT); /* ... by raise(jp->sig) instead? */
  4512. }
  4513. if (jp->state == JOBDONE)
  4514. #endif
  4515. freejob(jp);
  4516. return st;
  4517. }
  4518. /*
  4519. * return 1 if there are stopped jobs, otherwise 0
  4520. */
  4521. static int
  4522. stoppedjobs(void)
  4523. {
  4524. struct job *jp;
  4525. int retval;
  4526. retval = 0;
  4527. if (job_warning)
  4528. goto out;
  4529. jp = curjob;
  4530. if (jp && jp->state == JOBSTOPPED) {
  4531. out2str("You have stopped jobs.\n");
  4532. job_warning = 2;
  4533. retval++;
  4534. }
  4535. out:
  4536. return retval;
  4537. }
  4538. /* ============ redir.c
  4539. *
  4540. * Code for dealing with input/output redirection.
  4541. */
  4542. #undef EMPTY
  4543. #undef CLOSED
  4544. #define EMPTY -2 /* marks an unused slot in redirtab */
  4545. #define CLOSED -3 /* marks a slot of previously-closed fd */
  4546. /*
  4547. * Open a file in noclobber mode.
  4548. * The code was copied from bash.
  4549. */
  4550. static int
  4551. noclobberopen(const char *fname)
  4552. {
  4553. int r, fd;
  4554. struct stat finfo, finfo2;
  4555. /*
  4556. * If the file exists and is a regular file, return an error
  4557. * immediately.
  4558. */
  4559. r = stat(fname, &finfo);
  4560. if (r == 0 && S_ISREG(finfo.st_mode)) {
  4561. errno = EEXIST;
  4562. return -1;
  4563. }
  4564. /*
  4565. * If the file was not present (r != 0), make sure we open it
  4566. * exclusively so that if it is created before we open it, our open
  4567. * will fail. Make sure that we do not truncate an existing file.
  4568. * Note that we don't turn on O_EXCL unless the stat failed -- if the
  4569. * file was not a regular file, we leave O_EXCL off.
  4570. */
  4571. if (r != 0)
  4572. return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
  4573. fd = open(fname, O_WRONLY|O_CREAT, 0666);
  4574. /* If the open failed, return the file descriptor right away. */
  4575. if (fd < 0)
  4576. return fd;
  4577. /*
  4578. * OK, the open succeeded, but the file may have been changed from a
  4579. * non-regular file to a regular file between the stat and the open.
  4580. * We are assuming that the O_EXCL open handles the case where FILENAME
  4581. * did not exist and is symlinked to an existing file between the stat
  4582. * and open.
  4583. */
  4584. /*
  4585. * If we can open it and fstat the file descriptor, and neither check
  4586. * revealed that it was a regular file, and the file has not been
  4587. * replaced, return the file descriptor.
  4588. */
  4589. if (fstat(fd, &finfo2) == 0
  4590. && !S_ISREG(finfo2.st_mode)
  4591. && finfo.st_dev == finfo2.st_dev
  4592. && finfo.st_ino == finfo2.st_ino
  4593. ) {
  4594. return fd;
  4595. }
  4596. /* The file has been replaced. badness. */
  4597. close(fd);
  4598. errno = EEXIST;
  4599. return -1;
  4600. }
  4601. /*
  4602. * Handle here documents. Normally we fork off a process to write the
  4603. * data to a pipe. If the document is short, we can stuff the data in
  4604. * the pipe without forking.
  4605. */
  4606. /* openhere needs this forward reference */
  4607. static void expandhere(union node *arg, int fd);
  4608. static int
  4609. openhere(union node *redir)
  4610. {
  4611. int pip[2];
  4612. size_t len = 0;
  4613. if (pipe(pip) < 0)
  4614. ash_msg_and_raise_error("pipe call failed");
  4615. if (redir->type == NHERE) {
  4616. len = strlen(redir->nhere.doc->narg.text);
  4617. if (len <= PIPE_BUF) {
  4618. full_write(pip[1], redir->nhere.doc->narg.text, len);
  4619. goto out;
  4620. }
  4621. }
  4622. if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
  4623. /* child */
  4624. close(pip[0]);
  4625. ignoresig(SIGINT); //signal(SIGINT, SIG_IGN);
  4626. ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN);
  4627. ignoresig(SIGHUP); //signal(SIGHUP, SIG_IGN);
  4628. ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN);
  4629. signal(SIGPIPE, SIG_DFL);
  4630. if (redir->type == NHERE)
  4631. full_write(pip[1], redir->nhere.doc->narg.text, len);
  4632. else /* NXHERE */
  4633. expandhere(redir->nhere.doc, pip[1]);
  4634. _exit(EXIT_SUCCESS);
  4635. }
  4636. out:
  4637. close(pip[1]);
  4638. return pip[0];
  4639. }
  4640. static int
  4641. openredirect(union node *redir)
  4642. {
  4643. char *fname;
  4644. int f;
  4645. fname = redir->nfile.expfname;
  4646. switch (redir->nfile.type) {
  4647. case NFROM:
  4648. f = open(fname, O_RDONLY);
  4649. if (f < 0)
  4650. goto eopen;
  4651. break;
  4652. case NFROMTO:
  4653. f = open(fname, O_RDWR|O_CREAT, 0666);
  4654. if (f < 0)
  4655. goto ecreate;
  4656. break;
  4657. case NTO:
  4658. #if ENABLE_ASH_BASH_COMPAT
  4659. case NTO2:
  4660. #endif
  4661. /* Take care of noclobber mode. */
  4662. if (Cflag) {
  4663. f = noclobberopen(fname);
  4664. if (f < 0)
  4665. goto ecreate;
  4666. break;
  4667. }
  4668. /* FALLTHROUGH */
  4669. case NCLOBBER:
  4670. f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666);
  4671. if (f < 0)
  4672. goto ecreate;
  4673. break;
  4674. case NAPPEND:
  4675. f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666);
  4676. if (f < 0)
  4677. goto ecreate;
  4678. break;
  4679. default:
  4680. #if DEBUG
  4681. abort();
  4682. #endif
  4683. /* Fall through to eliminate warning. */
  4684. /* Our single caller does this itself */
  4685. // case NTOFD:
  4686. // case NFROMFD:
  4687. // f = -1;
  4688. // break;
  4689. case NHERE:
  4690. case NXHERE:
  4691. f = openhere(redir);
  4692. break;
  4693. }
  4694. return f;
  4695. ecreate:
  4696. ash_msg_and_raise_error("can't create %s: %s", fname, errmsg(errno, "nonexistent directory"));
  4697. eopen:
  4698. ash_msg_and_raise_error("can't open %s: %s", fname, errmsg(errno, "no such file"));
  4699. }
  4700. /*
  4701. * Copy a file descriptor to be >= to. Returns -1
  4702. * if the source file descriptor is closed, EMPTY if there are no unused
  4703. * file descriptors left.
  4704. */
  4705. /* 0x800..00: bit to set in "to" to request dup2 instead of fcntl(F_DUPFD).
  4706. * old code was doing close(to) prior to copyfd() to achieve the same */
  4707. enum {
  4708. COPYFD_EXACT = (int)~(INT_MAX),
  4709. COPYFD_RESTORE = (int)((unsigned)COPYFD_EXACT >> 1),
  4710. };
  4711. static int
  4712. copyfd(int from, int to)
  4713. {
  4714. int newfd;
  4715. if (to & COPYFD_EXACT) {
  4716. to &= ~COPYFD_EXACT;
  4717. /*if (from != to)*/
  4718. newfd = dup2(from, to);
  4719. } else {
  4720. newfd = fcntl(from, F_DUPFD, to);
  4721. }
  4722. if (newfd < 0) {
  4723. if (errno == EMFILE)
  4724. return EMPTY;
  4725. /* Happens when source fd is not open: try "echo >&99" */
  4726. ash_msg_and_raise_error("%d: %m", from);
  4727. }
  4728. return newfd;
  4729. }
  4730. /* Struct def and variable are moved down to the first usage site */
  4731. struct two_fd_t {
  4732. int orig, copy;
  4733. };
  4734. struct redirtab {
  4735. struct redirtab *next;
  4736. int nullredirs;
  4737. int pair_count;
  4738. struct two_fd_t two_fd[];
  4739. };
  4740. #define redirlist (G_var.redirlist)
  4741. static int need_to_remember(struct redirtab *rp, int fd)
  4742. {
  4743. int i;
  4744. if (!rp) /* remembering was not requested */
  4745. return 0;
  4746. for (i = 0; i < rp->pair_count; i++) {
  4747. if (rp->two_fd[i].orig == fd) {
  4748. /* already remembered */
  4749. return 0;
  4750. }
  4751. }
  4752. return 1;
  4753. }
  4754. /* "hidden" fd is a fd used to read scripts, or a copy of such */
  4755. static int is_hidden_fd(struct redirtab *rp, int fd)
  4756. {
  4757. int i;
  4758. struct parsefile *pf;
  4759. if (fd == -1)
  4760. return 0;
  4761. /* Check open scripts' fds */
  4762. pf = g_parsefile;
  4763. while (pf) {
  4764. /* We skip pf_fd == 0 case because of the following case:
  4765. * $ ash # running ash interactively
  4766. * $ . ./script.sh
  4767. * and in script.sh: "exec 9>&0".
  4768. * Even though top-level pf_fd _is_ 0,
  4769. * it's still ok to use it: "read" builtin uses it,
  4770. * why should we cripple "exec" builtin?
  4771. */
  4772. if (pf->pf_fd > 0 && fd == pf->pf_fd) {
  4773. return 1;
  4774. }
  4775. pf = pf->prev;
  4776. }
  4777. if (!rp)
  4778. return 0;
  4779. /* Check saved fds of redirects */
  4780. fd |= COPYFD_RESTORE;
  4781. for (i = 0; i < rp->pair_count; i++) {
  4782. if (rp->two_fd[i].copy == fd) {
  4783. return 1;
  4784. }
  4785. }
  4786. return 0;
  4787. }
  4788. /*
  4789. * Process a list of redirection commands. If the REDIR_PUSH flag is set,
  4790. * old file descriptors are stashed away so that the redirection can be
  4791. * undone by calling popredir.
  4792. */
  4793. /* flags passed to redirect */
  4794. #define REDIR_PUSH 01 /* save previous values of file descriptors */
  4795. #define REDIR_SAVEFD2 03 /* set preverrout */
  4796. static void
  4797. redirect(union node *redir, int flags)
  4798. {
  4799. struct redirtab *sv;
  4800. int sv_pos;
  4801. int i;
  4802. int fd;
  4803. int newfd;
  4804. int copied_fd2 = -1;
  4805. g_nullredirs++;
  4806. if (!redir) {
  4807. return;
  4808. }
  4809. sv = NULL;
  4810. sv_pos = 0;
  4811. INT_OFF;
  4812. if (flags & REDIR_PUSH) {
  4813. union node *tmp = redir;
  4814. do {
  4815. sv_pos++;
  4816. #if ENABLE_ASH_BASH_COMPAT
  4817. if (tmp->nfile.type == NTO2)
  4818. sv_pos++;
  4819. #endif
  4820. tmp = tmp->nfile.next;
  4821. } while (tmp);
  4822. sv = ckmalloc(sizeof(*sv) + sv_pos * sizeof(sv->two_fd[0]));
  4823. sv->next = redirlist;
  4824. sv->pair_count = sv_pos;
  4825. redirlist = sv;
  4826. sv->nullredirs = g_nullredirs - 1;
  4827. g_nullredirs = 0;
  4828. while (sv_pos > 0) {
  4829. sv_pos--;
  4830. sv->two_fd[sv_pos].orig = sv->two_fd[sv_pos].copy = EMPTY;
  4831. }
  4832. }
  4833. do {
  4834. int right_fd = -1;
  4835. fd = redir->nfile.fd;
  4836. if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
  4837. right_fd = redir->ndup.dupfd;
  4838. //bb_error_msg("doing %d > %d", fd, right_fd);
  4839. /* redirect from/to same file descriptor? */
  4840. if (right_fd == fd)
  4841. continue;
  4842. /* "echo >&10" and 10 is a fd opened to a sh script? */
  4843. if (is_hidden_fd(sv, right_fd)) {
  4844. errno = EBADF; /* as if it is closed */
  4845. ash_msg_and_raise_error("%d: %m", right_fd);
  4846. }
  4847. newfd = -1;
  4848. } else {
  4849. newfd = openredirect(redir); /* always >= 0 */
  4850. if (fd == newfd) {
  4851. /* Descriptor wasn't open before redirect.
  4852. * Mark it for close in the future */
  4853. if (need_to_remember(sv, fd)) {
  4854. goto remember_to_close;
  4855. }
  4856. continue;
  4857. }
  4858. }
  4859. #if ENABLE_ASH_BASH_COMPAT
  4860. redirect_more:
  4861. #endif
  4862. if (need_to_remember(sv, fd)) {
  4863. /* Copy old descriptor */
  4864. /* Careful to not accidentally "save"
  4865. * to the same fd as right side fd in N>&M */
  4866. int minfd = right_fd < 10 ? 10 : right_fd + 1;
  4867. i = fcntl(fd, F_DUPFD, minfd);
  4868. /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds
  4869. * are closed in popredir() in the child, preventing them from leaking
  4870. * into child. (popredir() also cleans up the mess in case of failures)
  4871. */
  4872. if (i == -1) {
  4873. i = errno;
  4874. if (i != EBADF) {
  4875. /* Strange error (e.g. "too many files" EMFILE?) */
  4876. if (newfd >= 0)
  4877. close(newfd);
  4878. errno = i;
  4879. ash_msg_and_raise_error("%d: %m", fd);
  4880. /* NOTREACHED */
  4881. }
  4882. /* EBADF: it is not open - good, remember to close it */
  4883. remember_to_close:
  4884. i = CLOSED;
  4885. } else { /* fd is open, save its copy */
  4886. /* "exec fd>&-" should not close fds
  4887. * which point to script file(s).
  4888. * Force them to be restored afterwards */
  4889. if (is_hidden_fd(sv, fd))
  4890. i |= COPYFD_RESTORE;
  4891. }
  4892. if (fd == 2)
  4893. copied_fd2 = i;
  4894. sv->two_fd[sv_pos].orig = fd;
  4895. sv->two_fd[sv_pos].copy = i;
  4896. sv_pos++;
  4897. }
  4898. if (newfd < 0) {
  4899. /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
  4900. if (redir->ndup.dupfd < 0) { /* "fd>&-" */
  4901. /* Don't want to trigger debugging */
  4902. if (fd != -1)
  4903. close(fd);
  4904. } else {
  4905. copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
  4906. }
  4907. } else if (fd != newfd) { /* move newfd to fd */
  4908. copyfd(newfd, fd | COPYFD_EXACT);
  4909. #if ENABLE_ASH_BASH_COMPAT
  4910. if (!(redir->nfile.type == NTO2 && fd == 2))
  4911. #endif
  4912. close(newfd);
  4913. }
  4914. #if ENABLE_ASH_BASH_COMPAT
  4915. if (redir->nfile.type == NTO2 && fd == 1) {
  4916. /* We already redirected it to fd 1, now copy it to 2 */
  4917. newfd = 1;
  4918. fd = 2;
  4919. goto redirect_more;
  4920. }
  4921. #endif
  4922. } while ((redir = redir->nfile.next) != NULL);
  4923. INT_ON;
  4924. if ((flags & REDIR_SAVEFD2) && copied_fd2 >= 0)
  4925. preverrout_fd = copied_fd2;
  4926. }
  4927. /*
  4928. * Undo the effects of the last redirection.
  4929. */
  4930. static void
  4931. popredir(int drop, int restore)
  4932. {
  4933. struct redirtab *rp;
  4934. int i;
  4935. if (--g_nullredirs >= 0)
  4936. return;
  4937. INT_OFF;
  4938. rp = redirlist;
  4939. for (i = 0; i < rp->pair_count; i++) {
  4940. int fd = rp->two_fd[i].orig;
  4941. int copy = rp->two_fd[i].copy;
  4942. if (copy == CLOSED) {
  4943. if (!drop)
  4944. close(fd);
  4945. continue;
  4946. }
  4947. if (copy != EMPTY) {
  4948. if (!drop || (restore && (copy & COPYFD_RESTORE))) {
  4949. copy &= ~COPYFD_RESTORE;
  4950. /*close(fd);*/
  4951. copyfd(copy, fd | COPYFD_EXACT);
  4952. }
  4953. close(copy & ~COPYFD_RESTORE);
  4954. }
  4955. }
  4956. redirlist = rp->next;
  4957. g_nullredirs = rp->nullredirs;
  4958. free(rp);
  4959. INT_ON;
  4960. }
  4961. /*
  4962. * Undo all redirections. Called on error or interrupt.
  4963. */
  4964. /*
  4965. * Discard all saved file descriptors.
  4966. */
  4967. static void
  4968. clearredir(int drop)
  4969. {
  4970. for (;;) {
  4971. g_nullredirs = 0;
  4972. if (!redirlist)
  4973. break;
  4974. popredir(drop, /*restore:*/ 0);
  4975. }
  4976. }
  4977. static int
  4978. redirectsafe(union node *redir, int flags)
  4979. {
  4980. int err;
  4981. volatile int saveint;
  4982. struct jmploc *volatile savehandler = exception_handler;
  4983. struct jmploc jmploc;
  4984. SAVE_INT(saveint);
  4985. /* "echo 9>/dev/null; echo >&9; echo result: $?" - result should be 1, not 2! */
  4986. err = setjmp(jmploc.loc); // huh?? was = setjmp(jmploc.loc) * 2;
  4987. if (!err) {
  4988. exception_handler = &jmploc;
  4989. redirect(redir, flags);
  4990. }
  4991. exception_handler = savehandler;
  4992. if (err && exception_type != EXERROR)
  4993. longjmp(exception_handler->loc, 1);
  4994. RESTORE_INT(saveint);
  4995. return err;
  4996. }
  4997. /* ============ Routines to expand arguments to commands
  4998. *
  4999. * We have to deal with backquotes, shell variables, and file metacharacters.
  5000. */
  5001. #if ENABLE_SH_MATH_SUPPORT
  5002. static arith_t
  5003. ash_arith(const char *s)
  5004. {
  5005. arith_state_t math_state;
  5006. arith_t result;
  5007. math_state.lookupvar = lookupvar;
  5008. math_state.setvar = setvar2;
  5009. //math_state.endofname = endofname;
  5010. INT_OFF;
  5011. result = arith(&math_state, s);
  5012. if (math_state.errmsg)
  5013. ash_msg_and_raise_error(math_state.errmsg);
  5014. INT_ON;
  5015. return result;
  5016. }
  5017. #endif
  5018. /*
  5019. * expandarg flags
  5020. */
  5021. #define EXP_FULL 0x1 /* perform word splitting & file globbing */
  5022. #define EXP_TILDE 0x2 /* do normal tilde expansion */
  5023. #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
  5024. #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
  5025. #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
  5026. #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
  5027. #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
  5028. #define EXP_WORD 0x80 /* expand word in parameter expansion */
  5029. #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
  5030. /*
  5031. * rmescape() flags
  5032. */
  5033. #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
  5034. #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
  5035. #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
  5036. #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
  5037. #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
  5038. /*
  5039. * Structure specifying which parts of the string should be searched
  5040. * for IFS characters.
  5041. */
  5042. struct ifsregion {
  5043. struct ifsregion *next; /* next region in list */
  5044. int begoff; /* offset of start of region */
  5045. int endoff; /* offset of end of region */
  5046. int nulonly; /* search for nul bytes only */
  5047. };
  5048. struct arglist {
  5049. struct strlist *list;
  5050. struct strlist **lastp;
  5051. };
  5052. /* output of current string */
  5053. static char *expdest;
  5054. /* list of back quote expressions */
  5055. static struct nodelist *argbackq;
  5056. /* first struct in list of ifs regions */
  5057. static struct ifsregion ifsfirst;
  5058. /* last struct in list */
  5059. static struct ifsregion *ifslastp;
  5060. /* holds expanded arg list */
  5061. static struct arglist exparg;
  5062. /*
  5063. * Our own itoa().
  5064. */
  5065. #if !ENABLE_SH_MATH_SUPPORT
  5066. /* cvtnum() is used even if math support is off (to prepare $? values and such) */
  5067. typedef long arith_t;
  5068. # define ARITH_FMT "%ld"
  5069. #endif
  5070. static int
  5071. cvtnum(arith_t num)
  5072. {
  5073. int len;
  5074. expdest = makestrspace(32, expdest);
  5075. len = fmtstr(expdest, 32, ARITH_FMT, num);
  5076. STADJUST(len, expdest);
  5077. return len;
  5078. }
  5079. static size_t
  5080. esclen(const char *start, const char *p)
  5081. {
  5082. size_t esc = 0;
  5083. while (p > start && (unsigned char)*--p == CTLESC) {
  5084. esc++;
  5085. }
  5086. return esc;
  5087. }
  5088. /*
  5089. * Remove any CTLESC characters from a string.
  5090. */
  5091. static char *
  5092. rmescapes(char *str, int flag)
  5093. {
  5094. static const char qchars[] ALIGN1 = { CTLESC, CTLQUOTEMARK, '\0' };
  5095. char *p, *q, *r;
  5096. unsigned inquotes;
  5097. unsigned protect_against_glob;
  5098. unsigned globbing;
  5099. p = strpbrk(str, qchars);
  5100. if (!p)
  5101. return str;
  5102. q = p;
  5103. r = str;
  5104. if (flag & RMESCAPE_ALLOC) {
  5105. size_t len = p - str;
  5106. size_t fulllen = len + strlen(p) + 1;
  5107. if (flag & RMESCAPE_GROW) {
  5108. int strloc = str - (char *)stackblock();
  5109. r = makestrspace(fulllen, expdest);
  5110. /* p and str may be invalidated by makestrspace */
  5111. str = (char *)stackblock() + strloc;
  5112. p = str + len;
  5113. } else if (flag & RMESCAPE_HEAP) {
  5114. r = ckmalloc(fulllen);
  5115. } else {
  5116. r = stalloc(fulllen);
  5117. }
  5118. q = r;
  5119. if (len > 0) {
  5120. q = (char *)memcpy(q, str, len) + len;
  5121. }
  5122. }
  5123. inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
  5124. globbing = flag & RMESCAPE_GLOB;
  5125. protect_against_glob = globbing;
  5126. while (*p) {
  5127. if ((unsigned char)*p == CTLQUOTEMARK) {
  5128. // TODO: if no RMESCAPE_QUOTED in flags, inquotes never becomes 0
  5129. // (alternates between RMESCAPE_QUOTED and ~RMESCAPE_QUOTED). Is it ok?
  5130. // Note: both inquotes and protect_against_glob only affect whether
  5131. // CTLESC,<ch> gets converted to <ch> or to \<ch>
  5132. inquotes = ~inquotes;
  5133. p++;
  5134. protect_against_glob = globbing;
  5135. continue;
  5136. }
  5137. if (*p == '\\') {
  5138. /* naked back slash */
  5139. protect_against_glob = 0;
  5140. goto copy;
  5141. }
  5142. if ((unsigned char)*p == CTLESC) {
  5143. p++;
  5144. if (protect_against_glob && inquotes && *p != '/') {
  5145. *q++ = '\\';
  5146. }
  5147. }
  5148. protect_against_glob = globbing;
  5149. copy:
  5150. *q++ = *p++;
  5151. }
  5152. *q = '\0';
  5153. if (flag & RMESCAPE_GROW) {
  5154. expdest = r;
  5155. STADJUST(q - r + 1, expdest);
  5156. }
  5157. return r;
  5158. }
  5159. #define pmatch(a, b) !fnmatch((a), (b), 0)
  5160. /*
  5161. * Prepare a pattern for a expmeta (internal glob(3)) call.
  5162. *
  5163. * Returns an stalloced string.
  5164. */
  5165. static char *
  5166. preglob(const char *pattern, int quoted, int flag)
  5167. {
  5168. flag |= RMESCAPE_GLOB;
  5169. if (quoted) {
  5170. flag |= RMESCAPE_QUOTED;
  5171. }
  5172. return rmescapes((char *)pattern, flag);
  5173. }
  5174. /*
  5175. * Put a string on the stack.
  5176. */
  5177. static void
  5178. memtodest(const char *p, size_t len, int syntax, int quotes)
  5179. {
  5180. char *q = expdest;
  5181. q = makestrspace(quotes ? len * 2 : len, q);
  5182. while (len--) {
  5183. unsigned char c = *p++;
  5184. if (c == '\0')
  5185. continue;
  5186. if (quotes) {
  5187. int n = SIT(c, syntax);
  5188. if (n == CCTL || n == CBACK)
  5189. USTPUTC(CTLESC, q);
  5190. }
  5191. USTPUTC(c, q);
  5192. }
  5193. expdest = q;
  5194. }
  5195. static void
  5196. strtodest(const char *p, int syntax, int quotes)
  5197. {
  5198. memtodest(p, strlen(p), syntax, quotes);
  5199. }
  5200. /*
  5201. * Record the fact that we have to scan this region of the
  5202. * string for IFS characters.
  5203. */
  5204. static void
  5205. recordregion(int start, int end, int nulonly)
  5206. {
  5207. struct ifsregion *ifsp;
  5208. if (ifslastp == NULL) {
  5209. ifsp = &ifsfirst;
  5210. } else {
  5211. INT_OFF;
  5212. ifsp = ckzalloc(sizeof(*ifsp));
  5213. /*ifsp->next = NULL; - ckzalloc did it */
  5214. ifslastp->next = ifsp;
  5215. INT_ON;
  5216. }
  5217. ifslastp = ifsp;
  5218. ifslastp->begoff = start;
  5219. ifslastp->endoff = end;
  5220. ifslastp->nulonly = nulonly;
  5221. }
  5222. static void
  5223. removerecordregions(int endoff)
  5224. {
  5225. if (ifslastp == NULL)
  5226. return;
  5227. if (ifsfirst.endoff > endoff) {
  5228. while (ifsfirst.next) {
  5229. struct ifsregion *ifsp;
  5230. INT_OFF;
  5231. ifsp = ifsfirst.next->next;
  5232. free(ifsfirst.next);
  5233. ifsfirst.next = ifsp;
  5234. INT_ON;
  5235. }
  5236. if (ifsfirst.begoff > endoff) {
  5237. ifslastp = NULL;
  5238. } else {
  5239. ifslastp = &ifsfirst;
  5240. ifsfirst.endoff = endoff;
  5241. }
  5242. return;
  5243. }
  5244. ifslastp = &ifsfirst;
  5245. while (ifslastp->next && ifslastp->next->begoff < endoff)
  5246. ifslastp = ifslastp->next;
  5247. while (ifslastp->next) {
  5248. struct ifsregion *ifsp;
  5249. INT_OFF;
  5250. ifsp = ifslastp->next->next;
  5251. free(ifslastp->next);
  5252. ifslastp->next = ifsp;
  5253. INT_ON;
  5254. }
  5255. if (ifslastp->endoff > endoff)
  5256. ifslastp->endoff = endoff;
  5257. }
  5258. static char *
  5259. exptilde(char *startp, char *p, int flags)
  5260. {
  5261. unsigned char c;
  5262. char *name;
  5263. struct passwd *pw;
  5264. const char *home;
  5265. int quotes = flags & (EXP_FULL | EXP_CASE | EXP_REDIR);
  5266. int startloc;
  5267. name = p + 1;
  5268. while ((c = *++p) != '\0') {
  5269. switch (c) {
  5270. case CTLESC:
  5271. return startp;
  5272. case CTLQUOTEMARK:
  5273. return startp;
  5274. case ':':
  5275. if (flags & EXP_VARTILDE)
  5276. goto done;
  5277. break;
  5278. case '/':
  5279. case CTLENDVAR:
  5280. goto done;
  5281. }
  5282. }
  5283. done:
  5284. *p = '\0';
  5285. if (*name == '\0') {
  5286. home = lookupvar("HOME");
  5287. } else {
  5288. pw = getpwnam(name);
  5289. if (pw == NULL)
  5290. goto lose;
  5291. home = pw->pw_dir;
  5292. }
  5293. if (!home || !*home)
  5294. goto lose;
  5295. *p = c;
  5296. startloc = expdest - (char *)stackblock();
  5297. strtodest(home, SQSYNTAX, quotes);
  5298. recordregion(startloc, expdest - (char *)stackblock(), 0);
  5299. return p;
  5300. lose:
  5301. *p = c;
  5302. return startp;
  5303. }
  5304. /*
  5305. * Execute a command inside back quotes. If it's a builtin command, we
  5306. * want to save its output in a block obtained from malloc. Otherwise
  5307. * we fork off a subprocess and get the output of the command via a pipe.
  5308. * Should be called with interrupts off.
  5309. */
  5310. struct backcmd { /* result of evalbackcmd */
  5311. int fd; /* file descriptor to read from */
  5312. int nleft; /* number of chars in buffer */
  5313. char *buf; /* buffer */
  5314. struct job *jp; /* job structure for command */
  5315. };
  5316. /* These forward decls are needed to use "eval" code for backticks handling: */
  5317. static uint8_t back_exitstatus; /* exit status of backquoted command */
  5318. #define EV_EXIT 01 /* exit after evaluating tree */
  5319. static void evaltree(union node *, int);
  5320. static void FAST_FUNC
  5321. evalbackcmd(union node *n, struct backcmd *result)
  5322. {
  5323. int saveherefd;
  5324. result->fd = -1;
  5325. result->buf = NULL;
  5326. result->nleft = 0;
  5327. result->jp = NULL;
  5328. if (n == NULL)
  5329. goto out;
  5330. saveherefd = herefd;
  5331. herefd = -1;
  5332. {
  5333. int pip[2];
  5334. struct job *jp;
  5335. if (pipe(pip) < 0)
  5336. ash_msg_and_raise_error("pipe call failed");
  5337. jp = makejob(/*n,*/ 1);
  5338. if (forkshell(jp, n, FORK_NOJOB) == 0) {
  5339. FORCE_INT_ON;
  5340. close(pip[0]);
  5341. if (pip[1] != 1) {
  5342. /*close(1);*/
  5343. copyfd(pip[1], 1 | COPYFD_EXACT);
  5344. close(pip[1]);
  5345. }
  5346. eflag = 0;
  5347. evaltree(n, EV_EXIT); /* actually evaltreenr... */
  5348. /* NOTREACHED */
  5349. }
  5350. close(pip[1]);
  5351. result->fd = pip[0];
  5352. result->jp = jp;
  5353. }
  5354. herefd = saveherefd;
  5355. out:
  5356. TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
  5357. result->fd, result->buf, result->nleft, result->jp));
  5358. }
  5359. /*
  5360. * Expand stuff in backwards quotes.
  5361. */
  5362. static void
  5363. expbackq(union node *cmd, int quoted, int quotes)
  5364. {
  5365. struct backcmd in;
  5366. int i;
  5367. char buf[128];
  5368. char *p;
  5369. char *dest;
  5370. int startloc;
  5371. int syntax = quoted ? DQSYNTAX : BASESYNTAX;
  5372. struct stackmark smark;
  5373. INT_OFF;
  5374. setstackmark(&smark);
  5375. dest = expdest;
  5376. startloc = dest - (char *)stackblock();
  5377. grabstackstr(dest);
  5378. evalbackcmd(cmd, &in);
  5379. popstackmark(&smark);
  5380. p = in.buf;
  5381. i = in.nleft;
  5382. if (i == 0)
  5383. goto read;
  5384. for (;;) {
  5385. memtodest(p, i, syntax, quotes);
  5386. read:
  5387. if (in.fd < 0)
  5388. break;
  5389. i = nonblock_immune_read(in.fd, buf, sizeof(buf), /*loop_on_EINTR:*/ 1);
  5390. TRACE(("expbackq: read returns %d\n", i));
  5391. if (i <= 0)
  5392. break;
  5393. p = buf;
  5394. }
  5395. free(in.buf);
  5396. if (in.fd >= 0) {
  5397. close(in.fd);
  5398. back_exitstatus = waitforjob(in.jp);
  5399. }
  5400. INT_ON;
  5401. /* Eat all trailing newlines */
  5402. dest = expdest;
  5403. for (; dest > (char *)stackblock() && dest[-1] == '\n';)
  5404. STUNPUTC(dest);
  5405. expdest = dest;
  5406. if (quoted == 0)
  5407. recordregion(startloc, dest - (char *)stackblock(), 0);
  5408. TRACE(("evalbackq: size:%d:'%.*s'\n",
  5409. (int)((dest - (char *)stackblock()) - startloc),
  5410. (int)((dest - (char *)stackblock()) - startloc),
  5411. stackblock() + startloc));
  5412. }
  5413. #if ENABLE_SH_MATH_SUPPORT
  5414. /*
  5415. * Expand arithmetic expression. Backup to start of expression,
  5416. * evaluate, place result in (backed up) result, adjust string position.
  5417. */
  5418. static void
  5419. expari(int quotes)
  5420. {
  5421. char *p, *start;
  5422. int begoff;
  5423. int flag;
  5424. int len;
  5425. /* ifsfree(); */
  5426. /*
  5427. * This routine is slightly over-complicated for
  5428. * efficiency. Next we scan backwards looking for the
  5429. * start of arithmetic.
  5430. */
  5431. start = stackblock();
  5432. p = expdest - 1;
  5433. *p = '\0';
  5434. p--;
  5435. while (1) {
  5436. int esc;
  5437. while ((unsigned char)*p != CTLARI) {
  5438. p--;
  5439. #if DEBUG
  5440. if (p < start) {
  5441. ash_msg_and_raise_error("missing CTLARI (shouldn't happen)");
  5442. }
  5443. #endif
  5444. }
  5445. esc = esclen(start, p);
  5446. if (!(esc % 2)) {
  5447. break;
  5448. }
  5449. p -= esc + 1;
  5450. }
  5451. begoff = p - start;
  5452. removerecordregions(begoff);
  5453. flag = p[1];
  5454. expdest = p;
  5455. if (quotes)
  5456. rmescapes(p + 2, 0);
  5457. len = cvtnum(ash_arith(p + 2));
  5458. if (flag != '"')
  5459. recordregion(begoff, begoff + len, 0);
  5460. }
  5461. #endif
  5462. /* argstr needs it */
  5463. static char *evalvar(char *p, int flags, struct strlist *var_str_list);
  5464. /*
  5465. * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
  5466. * characters to allow for further processing. Otherwise treat
  5467. * $@ like $* since no splitting will be performed.
  5468. *
  5469. * var_str_list (can be NULL) is a list of "VAR=val" strings which take precedence
  5470. * over shell varables. Needed for "A=a B=$A; echo $B" case - we use it
  5471. * for correct expansion of "B=$A" word.
  5472. */
  5473. static void
  5474. argstr(char *p, int flags, struct strlist *var_str_list)
  5475. {
  5476. static const char spclchars[] ALIGN1 = {
  5477. '=',
  5478. ':',
  5479. CTLQUOTEMARK,
  5480. CTLENDVAR,
  5481. CTLESC,
  5482. CTLVAR,
  5483. CTLBACKQ,
  5484. CTLBACKQ | CTLQUOTE,
  5485. #if ENABLE_SH_MATH_SUPPORT
  5486. CTLENDARI,
  5487. #endif
  5488. '\0'
  5489. };
  5490. const char *reject = spclchars;
  5491. int quotes = flags & (EXP_FULL | EXP_CASE | EXP_REDIR); /* do CTLESC */
  5492. int breakall = flags & EXP_WORD;
  5493. int inquotes;
  5494. size_t length;
  5495. int startloc;
  5496. if (!(flags & EXP_VARTILDE)) {
  5497. reject += 2;
  5498. } else if (flags & EXP_VARTILDE2) {
  5499. reject++;
  5500. }
  5501. inquotes = 0;
  5502. length = 0;
  5503. if (flags & EXP_TILDE) {
  5504. char *q;
  5505. flags &= ~EXP_TILDE;
  5506. tilde:
  5507. q = p;
  5508. if ((unsigned char)*q == CTLESC && (flags & EXP_QWORD))
  5509. q++;
  5510. if (*q == '~')
  5511. p = exptilde(p, q, flags);
  5512. }
  5513. start:
  5514. startloc = expdest - (char *)stackblock();
  5515. for (;;) {
  5516. unsigned char c;
  5517. length += strcspn(p + length, reject);
  5518. c = p[length];
  5519. if (c) {
  5520. if (!(c & 0x80)
  5521. IF_SH_MATH_SUPPORT(|| c == CTLENDARI)
  5522. ) {
  5523. /* c == '=' || c == ':' || c == CTLENDARI */
  5524. length++;
  5525. }
  5526. }
  5527. if (length > 0) {
  5528. int newloc;
  5529. expdest = stack_nputstr(p, length, expdest);
  5530. newloc = expdest - (char *)stackblock();
  5531. if (breakall && !inquotes && newloc > startloc) {
  5532. recordregion(startloc, newloc, 0);
  5533. }
  5534. startloc = newloc;
  5535. }
  5536. p += length + 1;
  5537. length = 0;
  5538. switch (c) {
  5539. case '\0':
  5540. goto breakloop;
  5541. case '=':
  5542. if (flags & EXP_VARTILDE2) {
  5543. p--;
  5544. continue;
  5545. }
  5546. flags |= EXP_VARTILDE2;
  5547. reject++;
  5548. /* fall through */
  5549. case ':':
  5550. /*
  5551. * sort of a hack - expand tildes in variable
  5552. * assignments (after the first '=' and after ':'s).
  5553. */
  5554. if (*--p == '~') {
  5555. goto tilde;
  5556. }
  5557. continue;
  5558. }
  5559. switch (c) {
  5560. case CTLENDVAR: /* ??? */
  5561. goto breakloop;
  5562. case CTLQUOTEMARK:
  5563. /* "$@" syntax adherence hack */
  5564. if (!inquotes
  5565. && memcmp(p, dolatstr, 4) == 0
  5566. && ( p[4] == (char)CTLQUOTEMARK
  5567. || (p[4] == (char)CTLENDVAR && p[5] == (char)CTLQUOTEMARK)
  5568. )
  5569. ) {
  5570. p = evalvar(p + 1, flags, /* var_str_list: */ NULL) + 1;
  5571. goto start;
  5572. }
  5573. inquotes = !inquotes;
  5574. addquote:
  5575. if (quotes) {
  5576. p--;
  5577. length++;
  5578. startloc++;
  5579. }
  5580. break;
  5581. case CTLESC:
  5582. startloc++;
  5583. length++;
  5584. goto addquote;
  5585. case CTLVAR:
  5586. TRACE(("argstr: evalvar('%s')\n", p));
  5587. p = evalvar(p, flags, var_str_list);
  5588. TRACE(("argstr: evalvar:'%s'\n", (char *)stackblock()));
  5589. goto start;
  5590. case CTLBACKQ:
  5591. c = '\0';
  5592. case CTLBACKQ|CTLQUOTE:
  5593. expbackq(argbackq->n, c, quotes);
  5594. argbackq = argbackq->next;
  5595. goto start;
  5596. #if ENABLE_SH_MATH_SUPPORT
  5597. case CTLENDARI:
  5598. p--;
  5599. expari(quotes);
  5600. goto start;
  5601. #endif
  5602. }
  5603. }
  5604. breakloop: ;
  5605. }
  5606. static char *
  5607. scanleft(char *startp, char *rmesc, char *rmescend UNUSED_PARAM,
  5608. char *pattern, int quotes, int zero)
  5609. {
  5610. char *loc, *loc2;
  5611. char c;
  5612. loc = startp;
  5613. loc2 = rmesc;
  5614. do {
  5615. int match;
  5616. const char *s = loc2;
  5617. c = *loc2;
  5618. if (zero) {
  5619. *loc2 = '\0';
  5620. s = rmesc;
  5621. }
  5622. match = pmatch(pattern, s);
  5623. *loc2 = c;
  5624. if (match)
  5625. return loc;
  5626. if (quotes && (unsigned char)*loc == CTLESC)
  5627. loc++;
  5628. loc++;
  5629. loc2++;
  5630. } while (c);
  5631. return NULL;
  5632. }
  5633. static char *
  5634. scanright(char *startp, char *rmesc, char *rmescend,
  5635. char *pattern, int quotes, int match_at_start)
  5636. {
  5637. #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
  5638. int try2optimize = match_at_start;
  5639. #endif
  5640. int esc = 0;
  5641. char *loc;
  5642. char *loc2;
  5643. /* If we called by "${v/pattern/repl}" or "${v//pattern/repl}":
  5644. * startp="escaped_value_of_v" rmesc="raw_value_of_v"
  5645. * rmescend=""(ptr to NUL in rmesc) pattern="pattern" quotes=match_at_start=1
  5646. * Logic:
  5647. * loc starts at NUL at the end of startp, loc2 starts at the end of rmesc,
  5648. * and on each iteration they go back two/one char until they reach the beginning.
  5649. * We try to find a match in "raw_value_of_v", "raw_value_of_", "raw_value_of" etc.
  5650. */
  5651. /* TODO: document in what other circumstances we are called. */
  5652. for (loc = pattern - 1, loc2 = rmescend; loc >= startp; loc2--) {
  5653. int match;
  5654. char c = *loc2;
  5655. const char *s = loc2;
  5656. if (match_at_start) {
  5657. *loc2 = '\0';
  5658. s = rmesc;
  5659. }
  5660. match = pmatch(pattern, s);
  5661. //bb_error_msg("pmatch(pattern:'%s',s:'%s'):%d", pattern, s, match);
  5662. *loc2 = c;
  5663. if (match)
  5664. return loc;
  5665. #if !ENABLE_ASH_OPTIMIZE_FOR_SIZE
  5666. if (try2optimize) {
  5667. /* Maybe we can optimize this:
  5668. * if pattern ends with unescaped *, we can avoid checking
  5669. * shorter strings: if "foo*" doesnt match "raw_value_of_v",
  5670. * it wont match truncated "raw_value_of_" strings too.
  5671. */
  5672. unsigned plen = strlen(pattern);
  5673. /* Does it end with "*"? */
  5674. if (plen != 0 && pattern[--plen] == '*') {
  5675. /* "xxxx*" is not escaped */
  5676. /* "xxx\*" is escaped */
  5677. /* "xx\\*" is not escaped */
  5678. /* "x\\\*" is escaped */
  5679. int slashes = 0;
  5680. while (plen != 0 && pattern[--plen] == '\\')
  5681. slashes++;
  5682. if (!(slashes & 1))
  5683. break; /* ends with unescaped "*" */
  5684. }
  5685. try2optimize = 0;
  5686. }
  5687. #endif
  5688. loc--;
  5689. if (quotes) {
  5690. if (--esc < 0) {
  5691. esc = esclen(startp, loc);
  5692. }
  5693. if (esc % 2) {
  5694. esc--;
  5695. loc--;
  5696. }
  5697. }
  5698. }
  5699. return NULL;
  5700. }
  5701. static void varunset(const char *, const char *, const char *, int) NORETURN;
  5702. static void
  5703. varunset(const char *end, const char *var, const char *umsg, int varflags)
  5704. {
  5705. const char *msg;
  5706. const char *tail;
  5707. tail = nullstr;
  5708. msg = "parameter not set";
  5709. if (umsg) {
  5710. if ((unsigned char)*end == CTLENDVAR) {
  5711. if (varflags & VSNUL)
  5712. tail = " or null";
  5713. } else {
  5714. msg = umsg;
  5715. }
  5716. }
  5717. ash_msg_and_raise_error("%.*s: %s%s", (int)(end - var - 1), var, msg, tail);
  5718. }
  5719. #if ENABLE_ASH_BASH_COMPAT
  5720. static char *
  5721. parse_sub_pattern(char *arg, int varflags)
  5722. {
  5723. char *idx, *repl = NULL;
  5724. unsigned char c;
  5725. //char *org_arg = arg;
  5726. //bb_error_msg("arg:'%s' varflags:%x", arg, varflags);
  5727. idx = arg;
  5728. while (1) {
  5729. c = *arg;
  5730. if (!c)
  5731. break;
  5732. if (c == '/') {
  5733. /* Only the first '/' seen is our separator */
  5734. if (!repl) {
  5735. repl = idx + 1;
  5736. c = '\0';
  5737. }
  5738. }
  5739. *idx++ = c;
  5740. arg++;
  5741. /*
  5742. * Example: v='ab\c'; echo ${v/\\b/_\\_\z_}
  5743. * The result is a_\_z_c (not a\_\_z_c)!
  5744. *
  5745. * Enable debug prints in this function and you'll see:
  5746. * ash: arg:'\\b/_\\_z_' varflags:d
  5747. * ash: pattern:'\\b' repl:'_\_z_'
  5748. * That is, \\b is interpreted as \\b, but \\_ as \_!
  5749. * IOW: search pattern and replace string treat backslashes
  5750. * differently! That is the reason why we check repl below:
  5751. */
  5752. if (c == '\\' && *arg == '\\' && repl && !(varflags & VSQUOTE))
  5753. arg++; /* skip both '\', not just first one */
  5754. }
  5755. *idx = c; /* NUL */
  5756. //bb_error_msg("pattern:'%s' repl:'%s'", org_arg, repl);
  5757. return repl;
  5758. }
  5759. #endif /* ENABLE_ASH_BASH_COMPAT */
  5760. static const char *
  5761. subevalvar(char *p, char *varname, int strloc, int subtype,
  5762. int startloc, int varflags, int quotes, struct strlist *var_str_list)
  5763. {
  5764. struct nodelist *saveargbackq = argbackq;
  5765. char *startp;
  5766. char *loc;
  5767. char *rmesc, *rmescend;
  5768. char *str;
  5769. IF_ASH_BASH_COMPAT(const char *repl = NULL;)
  5770. IF_ASH_BASH_COMPAT(int pos, len, orig_len;)
  5771. int saveherefd = herefd;
  5772. int amount, resetloc;
  5773. IF_ASH_BASH_COMPAT(int workloc;)
  5774. int zero;
  5775. char *(*scan)(char*, char*, char*, char*, int, int);
  5776. //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d)",
  5777. // p, varname, strloc, subtype, startloc, varflags, quotes);
  5778. herefd = -1;
  5779. argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
  5780. var_str_list);
  5781. STPUTC('\0', expdest);
  5782. herefd = saveherefd;
  5783. argbackq = saveargbackq;
  5784. startp = (char *)stackblock() + startloc;
  5785. switch (subtype) {
  5786. case VSASSIGN:
  5787. setvar2(varname, startp);
  5788. amount = startp - expdest;
  5789. STADJUST(amount, expdest);
  5790. return startp;
  5791. case VSQUESTION:
  5792. varunset(p, varname, startp, varflags);
  5793. /* NOTREACHED */
  5794. #if ENABLE_ASH_BASH_COMPAT
  5795. case VSSUBSTR:
  5796. loc = str = stackblock() + strloc;
  5797. /* Read POS in ${var:POS:LEN} */
  5798. pos = atoi(loc); /* number(loc) errors out on "1:4" */
  5799. len = str - startp - 1;
  5800. /* *loc != '\0', guaranteed by parser */
  5801. if (quotes) {
  5802. char *ptr;
  5803. /* Adjust the length by the number of escapes */
  5804. for (ptr = startp; ptr < (str - 1); ptr++) {
  5805. if ((unsigned char)*ptr == CTLESC) {
  5806. len--;
  5807. ptr++;
  5808. }
  5809. }
  5810. }
  5811. orig_len = len;
  5812. if (*loc++ == ':') {
  5813. /* ${var::LEN} */
  5814. len = number(loc);
  5815. } else {
  5816. /* Skip POS in ${var:POS:LEN} */
  5817. len = orig_len;
  5818. while (*loc && *loc != ':') {
  5819. /* TODO?
  5820. * bash complains on: var=qwe; echo ${var:1a:123}
  5821. if (!isdigit(*loc))
  5822. ash_msg_and_raise_error(msg_illnum, str);
  5823. */
  5824. loc++;
  5825. }
  5826. if (*loc++ == ':') {
  5827. len = number(loc);
  5828. }
  5829. }
  5830. if (pos < 0) {
  5831. /* ${VAR:$((-n)):l} starts n chars from the end */
  5832. pos = orig_len + pos;
  5833. }
  5834. if ((unsigned)pos >= orig_len) {
  5835. /* apart from obvious ${VAR:999999:l},
  5836. * covers ${VAR:$((-9999999)):l} - result is ""
  5837. * (bash-compat)
  5838. */
  5839. pos = 0;
  5840. len = 0;
  5841. }
  5842. if (len > (orig_len - pos))
  5843. len = orig_len - pos;
  5844. for (str = startp; pos; str++, pos--) {
  5845. if (quotes && (unsigned char)*str == CTLESC)
  5846. str++;
  5847. }
  5848. for (loc = startp; len; len--) {
  5849. if (quotes && (unsigned char)*str == CTLESC)
  5850. *loc++ = *str++;
  5851. *loc++ = *str++;
  5852. }
  5853. *loc = '\0';
  5854. amount = loc - expdest;
  5855. STADJUST(amount, expdest);
  5856. return loc;
  5857. #endif
  5858. }
  5859. resetloc = expdest - (char *)stackblock();
  5860. /* We'll comeback here if we grow the stack while handling
  5861. * a VSREPLACE or VSREPLACEALL, since our pointers into the
  5862. * stack will need rebasing, and we'll need to remove our work
  5863. * areas each time
  5864. */
  5865. IF_ASH_BASH_COMPAT(restart:)
  5866. amount = expdest - ((char *)stackblock() + resetloc);
  5867. STADJUST(-amount, expdest);
  5868. startp = (char *)stackblock() + startloc;
  5869. rmesc = startp;
  5870. rmescend = (char *)stackblock() + strloc;
  5871. if (quotes) {
  5872. rmesc = rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
  5873. if (rmesc != startp) {
  5874. rmescend = expdest;
  5875. startp = (char *)stackblock() + startloc;
  5876. }
  5877. }
  5878. rmescend--;
  5879. str = (char *)stackblock() + strloc;
  5880. preglob(str, varflags & VSQUOTE, 0);
  5881. #if ENABLE_ASH_BASH_COMPAT
  5882. workloc = expdest - (char *)stackblock();
  5883. if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
  5884. char *idx, *end;
  5885. if (!repl) {
  5886. repl = parse_sub_pattern(str, varflags);
  5887. //bb_error_msg("repl:'%s'", repl);
  5888. if (!repl)
  5889. repl = nullstr;
  5890. }
  5891. /* If there's no pattern to match, return the expansion unmolested */
  5892. if (str[0] == '\0')
  5893. return NULL;
  5894. len = 0;
  5895. idx = startp;
  5896. end = str - 1;
  5897. while (idx < end) {
  5898. try_to_match:
  5899. loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
  5900. //bb_error_msg("scanright('%s'):'%s'", str, loc);
  5901. if (!loc) {
  5902. /* No match, advance */
  5903. char *restart_detect = stackblock();
  5904. skip_matching:
  5905. STPUTC(*idx, expdest);
  5906. if (quotes && (unsigned char)*idx == CTLESC) {
  5907. idx++;
  5908. len++;
  5909. STPUTC(*idx, expdest);
  5910. }
  5911. if (stackblock() != restart_detect)
  5912. goto restart;
  5913. idx++;
  5914. len++;
  5915. rmesc++;
  5916. /* continue; - prone to quadratic behavior, smarter code: */
  5917. if (idx >= end)
  5918. break;
  5919. if (str[0] == '*') {
  5920. /* Pattern is "*foo". If "*foo" does not match "long_string",
  5921. * it would never match "ong_string" etc, no point in trying.
  5922. */
  5923. goto skip_matching;
  5924. }
  5925. goto try_to_match;
  5926. }
  5927. if (subtype == VSREPLACEALL) {
  5928. while (idx < loc) {
  5929. if (quotes && (unsigned char)*idx == CTLESC)
  5930. idx++;
  5931. idx++;
  5932. rmesc++;
  5933. }
  5934. } else {
  5935. idx = loc;
  5936. }
  5937. //bb_error_msg("repl:'%s'", repl);
  5938. for (loc = (char*)repl; *loc; loc++) {
  5939. char *restart_detect = stackblock();
  5940. if (quotes && *loc == '\\') {
  5941. STPUTC(CTLESC, expdest);
  5942. len++;
  5943. }
  5944. STPUTC(*loc, expdest);
  5945. if (stackblock() != restart_detect)
  5946. goto restart;
  5947. len++;
  5948. }
  5949. if (subtype == VSREPLACE) {
  5950. //bb_error_msg("tail:'%s', quotes:%x", idx, quotes);
  5951. while (*idx) {
  5952. char *restart_detect = stackblock();
  5953. STPUTC(*idx, expdest);
  5954. if (stackblock() != restart_detect)
  5955. goto restart;
  5956. len++;
  5957. idx++;
  5958. }
  5959. break;
  5960. }
  5961. }
  5962. /* We've put the replaced text into a buffer at workloc, now
  5963. * move it to the right place and adjust the stack.
  5964. */
  5965. STPUTC('\0', expdest);
  5966. startp = (char *)stackblock() + startloc;
  5967. memmove(startp, (char *)stackblock() + workloc, len + 1);
  5968. //bb_error_msg("startp:'%s'", startp);
  5969. amount = expdest - (startp + len);
  5970. STADJUST(-amount, expdest);
  5971. return startp;
  5972. }
  5973. #endif /* ENABLE_ASH_BASH_COMPAT */
  5974. subtype -= VSTRIMRIGHT;
  5975. #if DEBUG
  5976. if (subtype < 0 || subtype > 7)
  5977. abort();
  5978. #endif
  5979. /* zero = (subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX) */
  5980. zero = subtype >> 1;
  5981. /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
  5982. scan = (subtype & 1) ^ zero ? scanleft : scanright;
  5983. loc = scan(startp, rmesc, rmescend, str, quotes, zero);
  5984. if (loc) {
  5985. if (zero) {
  5986. memmove(startp, loc, str - loc);
  5987. loc = startp + (str - loc) - 1;
  5988. }
  5989. *loc = '\0';
  5990. amount = loc - expdest;
  5991. STADJUST(amount, expdest);
  5992. }
  5993. return loc;
  5994. }
  5995. /*
  5996. * Add the value of a specialized variable to the stack string.
  5997. * name parameter (examples):
  5998. * ash -c 'echo $1' name:'1='
  5999. * ash -c 'echo $qwe' name:'qwe='
  6000. * ash -c 'echo $$' name:'$='
  6001. * ash -c 'echo ${$}' name:'$='
  6002. * ash -c 'echo ${$##q}' name:'$=q'
  6003. * ash -c 'echo ${#$}' name:'$='
  6004. * note: examples with bad shell syntax:
  6005. * ash -c 'echo ${#$1}' name:'$=1'
  6006. * ash -c 'echo ${#1#}' name:'1=#'
  6007. */
  6008. static NOINLINE ssize_t
  6009. varvalue(char *name, int varflags, int flags, struct strlist *var_str_list)
  6010. {
  6011. const char *p;
  6012. int num;
  6013. int i;
  6014. int sepq = 0;
  6015. ssize_t len = 0;
  6016. int subtype = varflags & VSTYPE;
  6017. int quotes = flags & (EXP_FULL | EXP_CASE | EXP_REDIR);
  6018. int quoted = varflags & VSQUOTE;
  6019. int syntax = quoted ? DQSYNTAX : BASESYNTAX;
  6020. switch (*name) {
  6021. case '$':
  6022. num = rootpid;
  6023. goto numvar;
  6024. case '?':
  6025. num = exitstatus;
  6026. goto numvar;
  6027. case '#':
  6028. num = shellparam.nparam;
  6029. goto numvar;
  6030. case '!':
  6031. num = backgndpid;
  6032. if (num == 0)
  6033. return -1;
  6034. numvar:
  6035. len = cvtnum(num);
  6036. goto check_1char_name;
  6037. case '-':
  6038. expdest = makestrspace(NOPTS, expdest);
  6039. for (i = NOPTS - 1; i >= 0; i--) {
  6040. if (optlist[i]) {
  6041. USTPUTC(optletters(i), expdest);
  6042. len++;
  6043. }
  6044. }
  6045. check_1char_name:
  6046. #if 0
  6047. /* handles cases similar to ${#$1} */
  6048. if (name[2] != '\0')
  6049. raise_error_syntax("bad substitution");
  6050. #endif
  6051. break;
  6052. case '@': {
  6053. char **ap;
  6054. int sep;
  6055. if (quoted && (flags & EXP_FULL)) {
  6056. /* note: this is not meant as PEOF value */
  6057. sep = 1 << CHAR_BIT;
  6058. goto param;
  6059. }
  6060. /* fall through */
  6061. case '*':
  6062. sep = ifsset() ? (unsigned char)(ifsval()[0]) : ' ';
  6063. i = SIT(sep, syntax);
  6064. if (quotes && (i == CCTL || i == CBACK))
  6065. sepq = 1;
  6066. param:
  6067. ap = shellparam.p;
  6068. if (!ap)
  6069. return -1;
  6070. while ((p = *ap++) != NULL) {
  6071. size_t partlen;
  6072. partlen = strlen(p);
  6073. len += partlen;
  6074. if (!(subtype == VSPLUS || subtype == VSLENGTH))
  6075. memtodest(p, partlen, syntax, quotes);
  6076. if (*ap && sep) {
  6077. char *q;
  6078. len++;
  6079. if (subtype == VSPLUS || subtype == VSLENGTH) {
  6080. continue;
  6081. }
  6082. q = expdest;
  6083. if (sepq)
  6084. STPUTC(CTLESC, q);
  6085. /* note: may put NUL despite sep != 0
  6086. * (see sep = 1 << CHAR_BIT above) */
  6087. STPUTC(sep, q);
  6088. expdest = q;
  6089. }
  6090. }
  6091. return len;
  6092. } /* case '@' and '*' */
  6093. case '0':
  6094. case '1':
  6095. case '2':
  6096. case '3':
  6097. case '4':
  6098. case '5':
  6099. case '6':
  6100. case '7':
  6101. case '8':
  6102. case '9':
  6103. num = atoi(name); /* number(name) fails on ${N#str} etc */
  6104. if (num < 0 || num > shellparam.nparam)
  6105. return -1;
  6106. p = num ? shellparam.p[num - 1] : arg0;
  6107. goto value;
  6108. default:
  6109. /* NB: name has form "VAR=..." */
  6110. /* "A=a B=$A" case: var_str_list is a list of "A=a" strings
  6111. * which should be considered before we check variables. */
  6112. if (var_str_list) {
  6113. unsigned name_len = (strchrnul(name, '=') - name) + 1;
  6114. p = NULL;
  6115. do {
  6116. char *str, *eq;
  6117. str = var_str_list->text;
  6118. eq = strchr(str, '=');
  6119. if (!eq) /* stop at first non-assignment */
  6120. break;
  6121. eq++;
  6122. if (name_len == (unsigned)(eq - str)
  6123. && strncmp(str, name, name_len) == 0
  6124. ) {
  6125. p = eq;
  6126. /* goto value; - WRONG! */
  6127. /* think "A=1 A=2 B=$A" */
  6128. }
  6129. var_str_list = var_str_list->next;
  6130. } while (var_str_list);
  6131. if (p)
  6132. goto value;
  6133. }
  6134. p = lookupvar(name);
  6135. value:
  6136. if (!p)
  6137. return -1;
  6138. len = strlen(p);
  6139. if (!(subtype == VSPLUS || subtype == VSLENGTH))
  6140. memtodest(p, len, syntax, quotes);
  6141. #if ENABLE_UNICODE_SUPPORT
  6142. if (subtype == VSLENGTH && len > 0) {
  6143. reinit_unicode_for_ash();
  6144. if (unicode_status == UNICODE_ON) {
  6145. len = unicode_strlen(p);
  6146. }
  6147. }
  6148. #endif
  6149. return len;
  6150. }
  6151. if (subtype == VSPLUS || subtype == VSLENGTH)
  6152. STADJUST(-len, expdest);
  6153. return len;
  6154. }
  6155. /*
  6156. * Expand a variable, and return a pointer to the next character in the
  6157. * input string.
  6158. */
  6159. static char *
  6160. evalvar(char *p, int flags, struct strlist *var_str_list)
  6161. {
  6162. char varflags;
  6163. char subtype;
  6164. char quoted;
  6165. char easy;
  6166. char *var;
  6167. int patloc;
  6168. int startloc;
  6169. ssize_t varlen;
  6170. varflags = (unsigned char) *p++;
  6171. subtype = varflags & VSTYPE;
  6172. quoted = varflags & VSQUOTE;
  6173. var = p;
  6174. easy = (!quoted || (*var == '@' && shellparam.nparam));
  6175. startloc = expdest - (char *)stackblock();
  6176. p = strchr(p, '=') + 1; //TODO: use var_end(p)?
  6177. again:
  6178. varlen = varvalue(var, varflags, flags, var_str_list);
  6179. if (varflags & VSNUL)
  6180. varlen--;
  6181. if (subtype == VSPLUS) {
  6182. varlen = -1 - varlen;
  6183. goto vsplus;
  6184. }
  6185. if (subtype == VSMINUS) {
  6186. vsplus:
  6187. if (varlen < 0) {
  6188. argstr(
  6189. p,
  6190. flags | (quoted ? EXP_TILDE|EXP_QWORD : EXP_TILDE|EXP_WORD),
  6191. var_str_list
  6192. );
  6193. goto end;
  6194. }
  6195. if (easy)
  6196. goto record;
  6197. goto end;
  6198. }
  6199. if (subtype == VSASSIGN || subtype == VSQUESTION) {
  6200. if (varlen < 0) {
  6201. if (subevalvar(p, var, /* strloc: */ 0,
  6202. subtype, startloc, varflags,
  6203. /* quotes: */ 0,
  6204. var_str_list)
  6205. ) {
  6206. varflags &= ~VSNUL;
  6207. /*
  6208. * Remove any recorded regions beyond
  6209. * start of variable
  6210. */
  6211. removerecordregions(startloc);
  6212. goto again;
  6213. }
  6214. goto end;
  6215. }
  6216. if (easy)
  6217. goto record;
  6218. goto end;
  6219. }
  6220. if (varlen < 0 && uflag)
  6221. varunset(p, var, 0, 0);
  6222. if (subtype == VSLENGTH) {
  6223. cvtnum(varlen > 0 ? varlen : 0);
  6224. goto record;
  6225. }
  6226. if (subtype == VSNORMAL) {
  6227. if (easy)
  6228. goto record;
  6229. goto end;
  6230. }
  6231. #if DEBUG
  6232. switch (subtype) {
  6233. case VSTRIMLEFT:
  6234. case VSTRIMLEFTMAX:
  6235. case VSTRIMRIGHT:
  6236. case VSTRIMRIGHTMAX:
  6237. #if ENABLE_ASH_BASH_COMPAT
  6238. case VSSUBSTR:
  6239. case VSREPLACE:
  6240. case VSREPLACEALL:
  6241. #endif
  6242. break;
  6243. default:
  6244. abort();
  6245. }
  6246. #endif
  6247. if (varlen >= 0) {
  6248. /*
  6249. * Terminate the string and start recording the pattern
  6250. * right after it
  6251. */
  6252. STPUTC('\0', expdest);
  6253. patloc = expdest - (char *)stackblock();
  6254. if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
  6255. startloc, varflags,
  6256. /* quotes: */ flags & (EXP_FULL | EXP_CASE | EXP_REDIR),
  6257. var_str_list)
  6258. ) {
  6259. int amount = expdest - (
  6260. (char *)stackblock() + patloc - 1
  6261. );
  6262. STADJUST(-amount, expdest);
  6263. }
  6264. /* Remove any recorded regions beyond start of variable */
  6265. removerecordregions(startloc);
  6266. record:
  6267. recordregion(startloc, expdest - (char *)stackblock(), quoted);
  6268. }
  6269. end:
  6270. if (subtype != VSNORMAL) { /* skip to end of alternative */
  6271. int nesting = 1;
  6272. for (;;) {
  6273. unsigned char c = *p++;
  6274. if (c == CTLESC)
  6275. p++;
  6276. else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
  6277. if (varlen >= 0)
  6278. argbackq = argbackq->next;
  6279. } else if (c == CTLVAR) {
  6280. if ((*p++ & VSTYPE) != VSNORMAL)
  6281. nesting++;
  6282. } else if (c == CTLENDVAR) {
  6283. if (--nesting == 0)
  6284. break;
  6285. }
  6286. }
  6287. }
  6288. return p;
  6289. }
  6290. /*
  6291. * Break the argument string into pieces based upon IFS and add the
  6292. * strings to the argument list. The regions of the string to be
  6293. * searched for IFS characters have been stored by recordregion.
  6294. */
  6295. static void
  6296. ifsbreakup(char *string, struct arglist *arglist)
  6297. {
  6298. struct ifsregion *ifsp;
  6299. struct strlist *sp;
  6300. char *start;
  6301. char *p;
  6302. char *q;
  6303. const char *ifs, *realifs;
  6304. int ifsspc;
  6305. int nulonly;
  6306. start = string;
  6307. if (ifslastp != NULL) {
  6308. ifsspc = 0;
  6309. nulonly = 0;
  6310. realifs = ifsset() ? ifsval() : defifs;
  6311. ifsp = &ifsfirst;
  6312. do {
  6313. p = string + ifsp->begoff;
  6314. nulonly = ifsp->nulonly;
  6315. ifs = nulonly ? nullstr : realifs;
  6316. ifsspc = 0;
  6317. while (p < string + ifsp->endoff) {
  6318. q = p;
  6319. if ((unsigned char)*p == CTLESC)
  6320. p++;
  6321. if (!strchr(ifs, *p)) {
  6322. p++;
  6323. continue;
  6324. }
  6325. if (!nulonly)
  6326. ifsspc = (strchr(defifs, *p) != NULL);
  6327. /* Ignore IFS whitespace at start */
  6328. if (q == start && ifsspc) {
  6329. p++;
  6330. start = p;
  6331. continue;
  6332. }
  6333. *q = '\0';
  6334. sp = stzalloc(sizeof(*sp));
  6335. sp->text = start;
  6336. *arglist->lastp = sp;
  6337. arglist->lastp = &sp->next;
  6338. p++;
  6339. if (!nulonly) {
  6340. for (;;) {
  6341. if (p >= string + ifsp->endoff) {
  6342. break;
  6343. }
  6344. q = p;
  6345. if ((unsigned char)*p == CTLESC)
  6346. p++;
  6347. if (strchr(ifs, *p) == NULL) {
  6348. p = q;
  6349. break;
  6350. }
  6351. if (strchr(defifs, *p) == NULL) {
  6352. if (ifsspc) {
  6353. p++;
  6354. ifsspc = 0;
  6355. } else {
  6356. p = q;
  6357. break;
  6358. }
  6359. } else
  6360. p++;
  6361. }
  6362. }
  6363. start = p;
  6364. } /* while */
  6365. ifsp = ifsp->next;
  6366. } while (ifsp != NULL);
  6367. if (nulonly)
  6368. goto add;
  6369. }
  6370. if (!*start)
  6371. return;
  6372. add:
  6373. sp = stzalloc(sizeof(*sp));
  6374. sp->text = start;
  6375. *arglist->lastp = sp;
  6376. arglist->lastp = &sp->next;
  6377. }
  6378. static void
  6379. ifsfree(void)
  6380. {
  6381. struct ifsregion *p;
  6382. INT_OFF;
  6383. p = ifsfirst.next;
  6384. do {
  6385. struct ifsregion *ifsp;
  6386. ifsp = p->next;
  6387. free(p);
  6388. p = ifsp;
  6389. } while (p);
  6390. ifslastp = NULL;
  6391. ifsfirst.next = NULL;
  6392. INT_ON;
  6393. }
  6394. /*
  6395. * Add a file name to the list.
  6396. */
  6397. static void
  6398. addfname(const char *name)
  6399. {
  6400. struct strlist *sp;
  6401. sp = stzalloc(sizeof(*sp));
  6402. sp->text = ststrdup(name);
  6403. *exparg.lastp = sp;
  6404. exparg.lastp = &sp->next;
  6405. }
  6406. /*
  6407. * Do metacharacter (i.e. *, ?, [...]) expansion.
  6408. */
  6409. static void
  6410. expmeta(char *expdir, char *enddir, char *name)
  6411. {
  6412. char *p;
  6413. const char *cp;
  6414. char *start;
  6415. char *endname;
  6416. int metaflag;
  6417. struct stat statb;
  6418. DIR *dirp;
  6419. struct dirent *dp;
  6420. int atend;
  6421. int matchdot;
  6422. metaflag = 0;
  6423. start = name;
  6424. for (p = name; *p; p++) {
  6425. if (*p == '*' || *p == '?')
  6426. metaflag = 1;
  6427. else if (*p == '[') {
  6428. char *q = p + 1;
  6429. if (*q == '!')
  6430. q++;
  6431. for (;;) {
  6432. if (*q == '\\')
  6433. q++;
  6434. if (*q == '/' || *q == '\0')
  6435. break;
  6436. if (*++q == ']') {
  6437. metaflag = 1;
  6438. break;
  6439. }
  6440. }
  6441. } else if (*p == '\\')
  6442. p++;
  6443. else if (*p == '/') {
  6444. if (metaflag)
  6445. goto out;
  6446. start = p + 1;
  6447. }
  6448. }
  6449. out:
  6450. if (metaflag == 0) { /* we've reached the end of the file name */
  6451. if (enddir != expdir)
  6452. metaflag++;
  6453. p = name;
  6454. do {
  6455. if (*p == '\\')
  6456. p++;
  6457. *enddir++ = *p;
  6458. } while (*p++);
  6459. if (metaflag == 0 || lstat(expdir, &statb) >= 0)
  6460. addfname(expdir);
  6461. return;
  6462. }
  6463. endname = p;
  6464. if (name < start) {
  6465. p = name;
  6466. do {
  6467. if (*p == '\\')
  6468. p++;
  6469. *enddir++ = *p++;
  6470. } while (p < start);
  6471. }
  6472. if (enddir == expdir) {
  6473. cp = ".";
  6474. } else if (enddir == expdir + 1 && *expdir == '/') {
  6475. cp = "/";
  6476. } else {
  6477. cp = expdir;
  6478. enddir[-1] = '\0';
  6479. }
  6480. dirp = opendir(cp);
  6481. if (dirp == NULL)
  6482. return;
  6483. if (enddir != expdir)
  6484. enddir[-1] = '/';
  6485. if (*endname == 0) {
  6486. atend = 1;
  6487. } else {
  6488. atend = 0;
  6489. *endname++ = '\0';
  6490. }
  6491. matchdot = 0;
  6492. p = start;
  6493. if (*p == '\\')
  6494. p++;
  6495. if (*p == '.')
  6496. matchdot++;
  6497. while (!pending_int && (dp = readdir(dirp)) != NULL) {
  6498. if (dp->d_name[0] == '.' && !matchdot)
  6499. continue;
  6500. if (pmatch(start, dp->d_name)) {
  6501. if (atend) {
  6502. strcpy(enddir, dp->d_name);
  6503. addfname(expdir);
  6504. } else {
  6505. for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
  6506. continue;
  6507. p[-1] = '/';
  6508. expmeta(expdir, p, endname);
  6509. }
  6510. }
  6511. }
  6512. closedir(dirp);
  6513. if (!atend)
  6514. endname[-1] = '/';
  6515. }
  6516. static struct strlist *
  6517. msort(struct strlist *list, int len)
  6518. {
  6519. struct strlist *p, *q = NULL;
  6520. struct strlist **lpp;
  6521. int half;
  6522. int n;
  6523. if (len <= 1)
  6524. return list;
  6525. half = len >> 1;
  6526. p = list;
  6527. for (n = half; --n >= 0;) {
  6528. q = p;
  6529. p = p->next;
  6530. }
  6531. q->next = NULL; /* terminate first half of list */
  6532. q = msort(list, half); /* sort first half of list */
  6533. p = msort(p, len - half); /* sort second half */
  6534. lpp = &list;
  6535. for (;;) {
  6536. #if ENABLE_LOCALE_SUPPORT
  6537. if (strcoll(p->text, q->text) < 0)
  6538. #else
  6539. if (strcmp(p->text, q->text) < 0)
  6540. #endif
  6541. {
  6542. *lpp = p;
  6543. lpp = &p->next;
  6544. p = *lpp;
  6545. if (p == NULL) {
  6546. *lpp = q;
  6547. break;
  6548. }
  6549. } else {
  6550. *lpp = q;
  6551. lpp = &q->next;
  6552. q = *lpp;
  6553. if (q == NULL) {
  6554. *lpp = p;
  6555. break;
  6556. }
  6557. }
  6558. }
  6559. return list;
  6560. }
  6561. /*
  6562. * Sort the results of file name expansion. It calculates the number of
  6563. * strings to sort and then calls msort (short for merge sort) to do the
  6564. * work.
  6565. */
  6566. static struct strlist *
  6567. expsort(struct strlist *str)
  6568. {
  6569. int len;
  6570. struct strlist *sp;
  6571. len = 0;
  6572. for (sp = str; sp; sp = sp->next)
  6573. len++;
  6574. return msort(str, len);
  6575. }
  6576. static void
  6577. expandmeta(struct strlist *str /*, int flag*/)
  6578. {
  6579. static const char metachars[] ALIGN1 = {
  6580. '*', '?', '[', 0
  6581. };
  6582. /* TODO - EXP_REDIR */
  6583. while (str) {
  6584. char *expdir;
  6585. struct strlist **savelastp;
  6586. struct strlist *sp;
  6587. char *p;
  6588. if (fflag)
  6589. goto nometa;
  6590. if (!strpbrk(str->text, metachars))
  6591. goto nometa;
  6592. savelastp = exparg.lastp;
  6593. INT_OFF;
  6594. p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
  6595. {
  6596. int i = strlen(str->text);
  6597. expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
  6598. }
  6599. expmeta(expdir, expdir, p);
  6600. free(expdir);
  6601. if (p != str->text)
  6602. free(p);
  6603. INT_ON;
  6604. if (exparg.lastp == savelastp) {
  6605. /*
  6606. * no matches
  6607. */
  6608. nometa:
  6609. *exparg.lastp = str;
  6610. rmescapes(str->text, 0);
  6611. exparg.lastp = &str->next;
  6612. } else {
  6613. *exparg.lastp = NULL;
  6614. *savelastp = sp = expsort(*savelastp);
  6615. while (sp->next != NULL)
  6616. sp = sp->next;
  6617. exparg.lastp = &sp->next;
  6618. }
  6619. str = str->next;
  6620. }
  6621. }
  6622. /*
  6623. * Perform variable substitution and command substitution on an argument,
  6624. * placing the resulting list of arguments in arglist. If EXP_FULL is true,
  6625. * perform splitting and file name expansion. When arglist is NULL, perform
  6626. * here document expansion.
  6627. */
  6628. static void
  6629. expandarg(union node *arg, struct arglist *arglist, int flag)
  6630. {
  6631. struct strlist *sp;
  6632. char *p;
  6633. argbackq = arg->narg.backquote;
  6634. STARTSTACKSTR(expdest);
  6635. ifsfirst.next = NULL;
  6636. ifslastp = NULL;
  6637. TRACE(("expandarg: argstr('%s',flags:%x)\n", arg->narg.text, flag));
  6638. argstr(arg->narg.text, flag,
  6639. /* var_str_list: */ arglist ? arglist->list : NULL);
  6640. p = _STPUTC('\0', expdest);
  6641. expdest = p - 1;
  6642. if (arglist == NULL) {
  6643. return; /* here document expanded */
  6644. }
  6645. p = grabstackstr(p);
  6646. TRACE(("expandarg: p:'%s'\n", p));
  6647. exparg.lastp = &exparg.list;
  6648. /*
  6649. * TODO - EXP_REDIR
  6650. */
  6651. if (flag & EXP_FULL) {
  6652. ifsbreakup(p, &exparg);
  6653. *exparg.lastp = NULL;
  6654. exparg.lastp = &exparg.list;
  6655. expandmeta(exparg.list /*, flag*/);
  6656. } else {
  6657. if (flag & EXP_REDIR) { /*XXX - for now, just remove escapes */
  6658. rmescapes(p, 0);
  6659. TRACE(("expandarg: rmescapes:'%s'\n", p));
  6660. }
  6661. sp = stzalloc(sizeof(*sp));
  6662. sp->text = p;
  6663. *exparg.lastp = sp;
  6664. exparg.lastp = &sp->next;
  6665. }
  6666. if (ifsfirst.next)
  6667. ifsfree();
  6668. *exparg.lastp = NULL;
  6669. if (exparg.list) {
  6670. *arglist->lastp = exparg.list;
  6671. arglist->lastp = exparg.lastp;
  6672. }
  6673. }
  6674. /*
  6675. * Expand shell variables and backquotes inside a here document.
  6676. */
  6677. static void
  6678. expandhere(union node *arg, int fd)
  6679. {
  6680. herefd = fd;
  6681. expandarg(arg, (struct arglist *)NULL, 0);
  6682. full_write(fd, stackblock(), expdest - (char *)stackblock());
  6683. }
  6684. /*
  6685. * Returns true if the pattern matches the string.
  6686. */
  6687. static int
  6688. patmatch(char *pattern, const char *string)
  6689. {
  6690. return pmatch(preglob(pattern, 0, 0), string);
  6691. }
  6692. /*
  6693. * See if a pattern matches in a case statement.
  6694. */
  6695. static int
  6696. casematch(union node *pattern, char *val)
  6697. {
  6698. struct stackmark smark;
  6699. int result;
  6700. setstackmark(&smark);
  6701. argbackq = pattern->narg.backquote;
  6702. STARTSTACKSTR(expdest);
  6703. ifslastp = NULL;
  6704. argstr(pattern->narg.text, EXP_TILDE | EXP_CASE,
  6705. /* var_str_list: */ NULL);
  6706. STACKSTRNUL(expdest);
  6707. result = patmatch(stackblock(), val);
  6708. popstackmark(&smark);
  6709. return result;
  6710. }
  6711. /* ============ find_command */
  6712. struct builtincmd {
  6713. const char *name;
  6714. int (*builtin)(int, char **) FAST_FUNC;
  6715. /* unsigned flags; */
  6716. };
  6717. #define IS_BUILTIN_SPECIAL(b) ((b)->name[0] & 1)
  6718. /* "regular" builtins always take precedence over commands,
  6719. * regardless of PATH=....%builtin... position */
  6720. #define IS_BUILTIN_REGULAR(b) ((b)->name[0] & 2)
  6721. #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
  6722. struct cmdentry {
  6723. smallint cmdtype; /* CMDxxx */
  6724. union param {
  6725. int index;
  6726. /* index >= 0 for commands without path (slashes) */
  6727. /* (TODO: what exactly does the value mean? PATH position?) */
  6728. /* index == -1 for commands with slashes */
  6729. /* index == (-2 - applet_no) for NOFORK applets */
  6730. const struct builtincmd *cmd;
  6731. struct funcnode *func;
  6732. } u;
  6733. };
  6734. /* values of cmdtype */
  6735. #define CMDUNKNOWN -1 /* no entry in table for command */
  6736. #define CMDNORMAL 0 /* command is an executable program */
  6737. #define CMDFUNCTION 1 /* command is a shell function */
  6738. #define CMDBUILTIN 2 /* command is a shell builtin */
  6739. /* action to find_command() */
  6740. #define DO_ERR 0x01 /* prints errors */
  6741. #define DO_ABS 0x02 /* checks absolute paths */
  6742. #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
  6743. #define DO_ALTPATH 0x08 /* using alternate path */
  6744. #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
  6745. static void find_command(char *, struct cmdentry *, int, const char *);
  6746. /* ============ Hashing commands */
  6747. /*
  6748. * When commands are first encountered, they are entered in a hash table.
  6749. * This ensures that a full path search will not have to be done for them
  6750. * on each invocation.
  6751. *
  6752. * We should investigate converting to a linear search, even though that
  6753. * would make the command name "hash" a misnomer.
  6754. */
  6755. struct tblentry {
  6756. struct tblentry *next; /* next entry in hash chain */
  6757. union param param; /* definition of builtin function */
  6758. smallint cmdtype; /* CMDxxx */
  6759. char rehash; /* if set, cd done since entry created */
  6760. char cmdname[1]; /* name of command */
  6761. };
  6762. static struct tblentry **cmdtable;
  6763. #define INIT_G_cmdtable() do { \
  6764. cmdtable = xzalloc(CMDTABLESIZE * sizeof(cmdtable[0])); \
  6765. } while (0)
  6766. static int builtinloc = -1; /* index in path of %builtin, or -1 */
  6767. static void
  6768. tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
  6769. {
  6770. #if ENABLE_FEATURE_SH_STANDALONE
  6771. if (applet_no >= 0) {
  6772. if (APPLET_IS_NOEXEC(applet_no)) {
  6773. clearenv();
  6774. while (*envp)
  6775. putenv(*envp++);
  6776. run_applet_no_and_exit(applet_no, argv);
  6777. }
  6778. /* re-exec ourselves with the new arguments */
  6779. execve(bb_busybox_exec_path, argv, envp);
  6780. /* If they called chroot or otherwise made the binary no longer
  6781. * executable, fall through */
  6782. }
  6783. #endif
  6784. repeat:
  6785. #ifdef SYSV
  6786. do {
  6787. execve(cmd, argv, envp);
  6788. } while (errno == EINTR);
  6789. #else
  6790. execve(cmd, argv, envp);
  6791. #endif
  6792. if (cmd == (char*) bb_busybox_exec_path) {
  6793. /* We already visited ENOEXEC branch below, don't do it again */
  6794. //TODO: try execve(initial_argv0_of_shell, argv, envp) before giving up?
  6795. free(argv);
  6796. return;
  6797. }
  6798. if (errno == ENOEXEC) {
  6799. /* Run "cmd" as a shell script:
  6800. * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
  6801. * "If the execve() function fails with ENOEXEC, the shell
  6802. * shall execute a command equivalent to having a shell invoked
  6803. * with the command name as its first operand,
  6804. * with any remaining arguments passed to the new shell"
  6805. *
  6806. * That is, do not use $SHELL, user's shell, or /bin/sh;
  6807. * just call ourselves.
  6808. *
  6809. * Note that bash reads ~80 chars of the file, and if it sees
  6810. * a zero byte before it sees newline, it doesn't try to
  6811. * interpret it, but fails with "cannot execute binary file"
  6812. * message and exit code 126. For one, this prevents attempts
  6813. * to interpret foreign ELF binaries as shell scripts.
  6814. */
  6815. char **ap;
  6816. char **new;
  6817. for (ap = argv; *ap; ap++)
  6818. continue;
  6819. new = ckmalloc((ap - argv + 2) * sizeof(new[0]));
  6820. new[0] = (char*) "ash";
  6821. new[1] = cmd;
  6822. ap = new + 2;
  6823. while ((*ap++ = *++argv) != NULL)
  6824. continue;
  6825. cmd = (char*) bb_busybox_exec_path;
  6826. argv = new;
  6827. goto repeat;
  6828. }
  6829. }
  6830. /*
  6831. * Exec a program. Never returns. If you change this routine, you may
  6832. * have to change the find_command routine as well.
  6833. */
  6834. static void shellexec(char **, const char *, int) NORETURN;
  6835. static void
  6836. shellexec(char **argv, const char *path, int idx)
  6837. {
  6838. char *cmdname;
  6839. int e;
  6840. char **envp;
  6841. int exerrno;
  6842. int applet_no = -1; /* used only by FEATURE_SH_STANDALONE */
  6843. clearredir(/*drop:*/ 1);
  6844. envp = listvars(VEXPORT, VUNSET, /*end:*/ NULL);
  6845. if (strchr(argv[0], '/') != NULL
  6846. #if ENABLE_FEATURE_SH_STANDALONE
  6847. || (applet_no = find_applet_by_name(argv[0])) >= 0
  6848. #endif
  6849. ) {
  6850. tryexec(IF_FEATURE_SH_STANDALONE(applet_no,) argv[0], argv, envp);
  6851. if (applet_no >= 0) {
  6852. /* We tried execing ourself, but it didn't work.
  6853. * Maybe /proc/self/exe doesn't exist?
  6854. * Try $PATH search.
  6855. */
  6856. goto try_PATH;
  6857. }
  6858. e = errno;
  6859. } else {
  6860. try_PATH:
  6861. e = ENOENT;
  6862. while ((cmdname = path_advance(&path, argv[0])) != NULL) {
  6863. if (--idx < 0 && pathopt == NULL) {
  6864. tryexec(IF_FEATURE_SH_STANDALONE(-1,) cmdname, argv, envp);
  6865. if (errno != ENOENT && errno != ENOTDIR)
  6866. e = errno;
  6867. }
  6868. stunalloc(cmdname);
  6869. }
  6870. }
  6871. /* Map to POSIX errors */
  6872. switch (e) {
  6873. case EACCES:
  6874. exerrno = 126;
  6875. break;
  6876. case ENOENT:
  6877. exerrno = 127;
  6878. break;
  6879. default:
  6880. exerrno = 2;
  6881. break;
  6882. }
  6883. exitstatus = exerrno;
  6884. TRACE(("shellexec failed for %s, errno %d, suppress_int %d\n",
  6885. argv[0], e, suppress_int));
  6886. ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found"));
  6887. /* NOTREACHED */
  6888. }
  6889. static void
  6890. printentry(struct tblentry *cmdp)
  6891. {
  6892. int idx;
  6893. const char *path;
  6894. char *name;
  6895. idx = cmdp->param.index;
  6896. path = pathval();
  6897. do {
  6898. name = path_advance(&path, cmdp->cmdname);
  6899. stunalloc(name);
  6900. } while (--idx >= 0);
  6901. out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
  6902. }
  6903. /*
  6904. * Clear out command entries. The argument specifies the first entry in
  6905. * PATH which has changed.
  6906. */
  6907. static void
  6908. clearcmdentry(int firstchange)
  6909. {
  6910. struct tblentry **tblp;
  6911. struct tblentry **pp;
  6912. struct tblentry *cmdp;
  6913. INT_OFF;
  6914. for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
  6915. pp = tblp;
  6916. while ((cmdp = *pp) != NULL) {
  6917. if ((cmdp->cmdtype == CMDNORMAL &&
  6918. cmdp->param.index >= firstchange)
  6919. || (cmdp->cmdtype == CMDBUILTIN &&
  6920. builtinloc >= firstchange)
  6921. ) {
  6922. *pp = cmdp->next;
  6923. free(cmdp);
  6924. } else {
  6925. pp = &cmdp->next;
  6926. }
  6927. }
  6928. }
  6929. INT_ON;
  6930. }
  6931. /*
  6932. * Locate a command in the command hash table. If "add" is nonzero,
  6933. * add the command to the table if it is not already present. The
  6934. * variable "lastcmdentry" is set to point to the address of the link
  6935. * pointing to the entry, so that delete_cmd_entry can delete the
  6936. * entry.
  6937. *
  6938. * Interrupts must be off if called with add != 0.
  6939. */
  6940. static struct tblentry **lastcmdentry;
  6941. static struct tblentry *
  6942. cmdlookup(const char *name, int add)
  6943. {
  6944. unsigned int hashval;
  6945. const char *p;
  6946. struct tblentry *cmdp;
  6947. struct tblentry **pp;
  6948. p = name;
  6949. hashval = (unsigned char)*p << 4;
  6950. while (*p)
  6951. hashval += (unsigned char)*p++;
  6952. hashval &= 0x7FFF;
  6953. pp = &cmdtable[hashval % CMDTABLESIZE];
  6954. for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
  6955. if (strcmp(cmdp->cmdname, name) == 0)
  6956. break;
  6957. pp = &cmdp->next;
  6958. }
  6959. if (add && cmdp == NULL) {
  6960. cmdp = *pp = ckzalloc(sizeof(struct tblentry)
  6961. + strlen(name)
  6962. /* + 1 - already done because
  6963. * tblentry::cmdname is char[1] */);
  6964. /*cmdp->next = NULL; - ckzalloc did it */
  6965. cmdp->cmdtype = CMDUNKNOWN;
  6966. strcpy(cmdp->cmdname, name);
  6967. }
  6968. lastcmdentry = pp;
  6969. return cmdp;
  6970. }
  6971. /*
  6972. * Delete the command entry returned on the last lookup.
  6973. */
  6974. static void
  6975. delete_cmd_entry(void)
  6976. {
  6977. struct tblentry *cmdp;
  6978. INT_OFF;
  6979. cmdp = *lastcmdentry;
  6980. *lastcmdentry = cmdp->next;
  6981. if (cmdp->cmdtype == CMDFUNCTION)
  6982. freefunc(cmdp->param.func);
  6983. free(cmdp);
  6984. INT_ON;
  6985. }
  6986. /*
  6987. * Add a new command entry, replacing any existing command entry for
  6988. * the same name - except special builtins.
  6989. */
  6990. static void
  6991. addcmdentry(char *name, struct cmdentry *entry)
  6992. {
  6993. struct tblentry *cmdp;
  6994. cmdp = cmdlookup(name, 1);
  6995. if (cmdp->cmdtype == CMDFUNCTION) {
  6996. freefunc(cmdp->param.func);
  6997. }
  6998. cmdp->cmdtype = entry->cmdtype;
  6999. cmdp->param = entry->u;
  7000. cmdp->rehash = 0;
  7001. }
  7002. static int FAST_FUNC
  7003. hashcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  7004. {
  7005. struct tblentry **pp;
  7006. struct tblentry *cmdp;
  7007. int c;
  7008. struct cmdentry entry;
  7009. char *name;
  7010. if (nextopt("r") != '\0') {
  7011. clearcmdentry(0);
  7012. return 0;
  7013. }
  7014. if (*argptr == NULL) {
  7015. for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
  7016. for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
  7017. if (cmdp->cmdtype == CMDNORMAL)
  7018. printentry(cmdp);
  7019. }
  7020. }
  7021. return 0;
  7022. }
  7023. c = 0;
  7024. while ((name = *argptr) != NULL) {
  7025. cmdp = cmdlookup(name, 0);
  7026. if (cmdp != NULL
  7027. && (cmdp->cmdtype == CMDNORMAL
  7028. || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
  7029. ) {
  7030. delete_cmd_entry();
  7031. }
  7032. find_command(name, &entry, DO_ERR, pathval());
  7033. if (entry.cmdtype == CMDUNKNOWN)
  7034. c = 1;
  7035. argptr++;
  7036. }
  7037. return c;
  7038. }
  7039. /*
  7040. * Called when a cd is done. Marks all commands so the next time they
  7041. * are executed they will be rehashed.
  7042. */
  7043. static void
  7044. hashcd(void)
  7045. {
  7046. struct tblentry **pp;
  7047. struct tblentry *cmdp;
  7048. for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
  7049. for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
  7050. if (cmdp->cmdtype == CMDNORMAL
  7051. || (cmdp->cmdtype == CMDBUILTIN
  7052. && !IS_BUILTIN_REGULAR(cmdp->param.cmd)
  7053. && builtinloc > 0)
  7054. ) {
  7055. cmdp->rehash = 1;
  7056. }
  7057. }
  7058. }
  7059. }
  7060. /*
  7061. * Fix command hash table when PATH changed.
  7062. * Called before PATH is changed. The argument is the new value of PATH;
  7063. * pathval() still returns the old value at this point.
  7064. * Called with interrupts off.
  7065. */
  7066. static void FAST_FUNC
  7067. changepath(const char *new)
  7068. {
  7069. const char *old;
  7070. int firstchange;
  7071. int idx;
  7072. int idx_bltin;
  7073. old = pathval();
  7074. firstchange = 9999; /* assume no change */
  7075. idx = 0;
  7076. idx_bltin = -1;
  7077. for (;;) {
  7078. if (*old != *new) {
  7079. firstchange = idx;
  7080. if ((*old == '\0' && *new == ':')
  7081. || (*old == ':' && *new == '\0')
  7082. ) {
  7083. firstchange++;
  7084. }
  7085. old = new; /* ignore subsequent differences */
  7086. }
  7087. if (*new == '\0')
  7088. break;
  7089. if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
  7090. idx_bltin = idx;
  7091. if (*new == ':')
  7092. idx++;
  7093. new++;
  7094. old++;
  7095. }
  7096. if (builtinloc < 0 && idx_bltin >= 0)
  7097. builtinloc = idx_bltin; /* zap builtins */
  7098. if (builtinloc >= 0 && idx_bltin < 0)
  7099. firstchange = 0;
  7100. clearcmdentry(firstchange);
  7101. builtinloc = idx_bltin;
  7102. }
  7103. #define TEOF 0
  7104. #define TNL 1
  7105. #define TREDIR 2
  7106. #define TWORD 3
  7107. #define TSEMI 4
  7108. #define TBACKGND 5
  7109. #define TAND 6
  7110. #define TOR 7
  7111. #define TPIPE 8
  7112. #define TLP 9
  7113. #define TRP 10
  7114. #define TENDCASE 11
  7115. #define TENDBQUOTE 12
  7116. #define TNOT 13
  7117. #define TCASE 14
  7118. #define TDO 15
  7119. #define TDONE 16
  7120. #define TELIF 17
  7121. #define TELSE 18
  7122. #define TESAC 19
  7123. #define TFI 20
  7124. #define TFOR 21
  7125. #define TIF 22
  7126. #define TIN 23
  7127. #define TTHEN 24
  7128. #define TUNTIL 25
  7129. #define TWHILE 26
  7130. #define TBEGIN 27
  7131. #define TEND 28
  7132. typedef smallint token_id_t;
  7133. /* first char is indicating which tokens mark the end of a list */
  7134. static const char *const tokname_array[] = {
  7135. "\1end of file",
  7136. "\0newline",
  7137. "\0redirection",
  7138. "\0word",
  7139. "\0;",
  7140. "\0&",
  7141. "\0&&",
  7142. "\0||",
  7143. "\0|",
  7144. "\0(",
  7145. "\1)",
  7146. "\1;;",
  7147. "\1`",
  7148. #define KWDOFFSET 13
  7149. /* the following are keywords */
  7150. "\0!",
  7151. "\0case",
  7152. "\1do",
  7153. "\1done",
  7154. "\1elif",
  7155. "\1else",
  7156. "\1esac",
  7157. "\1fi",
  7158. "\0for",
  7159. "\0if",
  7160. "\0in",
  7161. "\1then",
  7162. "\0until",
  7163. "\0while",
  7164. "\0{",
  7165. "\1}",
  7166. };
  7167. /* Wrapper around strcmp for qsort/bsearch/... */
  7168. static int
  7169. pstrcmp(const void *a, const void *b)
  7170. {
  7171. return strcmp((char*) a, (*(char**) b) + 1);
  7172. }
  7173. static const char *const *
  7174. findkwd(const char *s)
  7175. {
  7176. return bsearch(s, tokname_array + KWDOFFSET,
  7177. ARRAY_SIZE(tokname_array) - KWDOFFSET,
  7178. sizeof(tokname_array[0]), pstrcmp);
  7179. }
  7180. /*
  7181. * Locate and print what a word is...
  7182. */
  7183. static int
  7184. describe_command(char *command, int describe_command_verbose)
  7185. {
  7186. struct cmdentry entry;
  7187. struct tblentry *cmdp;
  7188. #if ENABLE_ASH_ALIAS
  7189. const struct alias *ap;
  7190. #endif
  7191. const char *path = pathval();
  7192. if (describe_command_verbose) {
  7193. out1str(command);
  7194. }
  7195. /* First look at the keywords */
  7196. if (findkwd(command)) {
  7197. out1str(describe_command_verbose ? " is a shell keyword" : command);
  7198. goto out;
  7199. }
  7200. #if ENABLE_ASH_ALIAS
  7201. /* Then look at the aliases */
  7202. ap = lookupalias(command, 0);
  7203. if (ap != NULL) {
  7204. if (!describe_command_verbose) {
  7205. out1str("alias ");
  7206. printalias(ap);
  7207. return 0;
  7208. }
  7209. out1fmt(" is an alias for %s", ap->val);
  7210. goto out;
  7211. }
  7212. #endif
  7213. /* Then check if it is a tracked alias */
  7214. cmdp = cmdlookup(command, 0);
  7215. if (cmdp != NULL) {
  7216. entry.cmdtype = cmdp->cmdtype;
  7217. entry.u = cmdp->param;
  7218. } else {
  7219. /* Finally use brute force */
  7220. find_command(command, &entry, DO_ABS, path);
  7221. }
  7222. switch (entry.cmdtype) {
  7223. case CMDNORMAL: {
  7224. int j = entry.u.index;
  7225. char *p;
  7226. if (j < 0) {
  7227. p = command;
  7228. } else {
  7229. do {
  7230. p = path_advance(&path, command);
  7231. stunalloc(p);
  7232. } while (--j >= 0);
  7233. }
  7234. if (describe_command_verbose) {
  7235. out1fmt(" is%s %s",
  7236. (cmdp ? " a tracked alias for" : nullstr), p
  7237. );
  7238. } else {
  7239. out1str(p);
  7240. }
  7241. break;
  7242. }
  7243. case CMDFUNCTION:
  7244. if (describe_command_verbose) {
  7245. out1str(" is a shell function");
  7246. } else {
  7247. out1str(command);
  7248. }
  7249. break;
  7250. case CMDBUILTIN:
  7251. if (describe_command_verbose) {
  7252. out1fmt(" is a %sshell builtin",
  7253. IS_BUILTIN_SPECIAL(entry.u.cmd) ?
  7254. "special " : nullstr
  7255. );
  7256. } else {
  7257. out1str(command);
  7258. }
  7259. break;
  7260. default:
  7261. if (describe_command_verbose) {
  7262. out1str(": not found\n");
  7263. }
  7264. return 127;
  7265. }
  7266. out:
  7267. out1str("\n");
  7268. return 0;
  7269. }
  7270. static int FAST_FUNC
  7271. typecmd(int argc UNUSED_PARAM, char **argv)
  7272. {
  7273. int i = 1;
  7274. int err = 0;
  7275. int verbose = 1;
  7276. /* type -p ... ? (we don't bother checking for 'p') */
  7277. if (argv[1] && argv[1][0] == '-') {
  7278. i++;
  7279. verbose = 0;
  7280. }
  7281. while (argv[i]) {
  7282. err |= describe_command(argv[i++], verbose);
  7283. }
  7284. return err;
  7285. }
  7286. #if ENABLE_ASH_CMDCMD
  7287. static int FAST_FUNC
  7288. commandcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  7289. {
  7290. int c;
  7291. enum {
  7292. VERIFY_BRIEF = 1,
  7293. VERIFY_VERBOSE = 2,
  7294. } verify = 0;
  7295. while ((c = nextopt("pvV")) != '\0')
  7296. if (c == 'V')
  7297. verify |= VERIFY_VERBOSE;
  7298. else if (c == 'v')
  7299. verify |= VERIFY_BRIEF;
  7300. #if DEBUG
  7301. else if (c != 'p')
  7302. abort();
  7303. #endif
  7304. /* Mimic bash: just "command -v" doesn't complain, it's a nop */
  7305. if (verify && (*argptr != NULL)) {
  7306. return describe_command(*argptr, verify - VERIFY_BRIEF);
  7307. }
  7308. return 0;
  7309. }
  7310. #endif
  7311. /* ============ eval.c */
  7312. static int funcblocksize; /* size of structures in function */
  7313. static int funcstringsize; /* size of strings in node */
  7314. static void *funcblock; /* block to allocate function from */
  7315. static char *funcstring; /* block to allocate strings from */
  7316. /* flags in argument to evaltree */
  7317. #define EV_EXIT 01 /* exit after evaluating tree */
  7318. #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
  7319. #define EV_BACKCMD 04 /* command executing within back quotes */
  7320. static const uint8_t nodesize[N_NUMBER] = {
  7321. [NCMD ] = SHELL_ALIGN(sizeof(struct ncmd)),
  7322. [NPIPE ] = SHELL_ALIGN(sizeof(struct npipe)),
  7323. [NREDIR ] = SHELL_ALIGN(sizeof(struct nredir)),
  7324. [NBACKGND ] = SHELL_ALIGN(sizeof(struct nredir)),
  7325. [NSUBSHELL] = SHELL_ALIGN(sizeof(struct nredir)),
  7326. [NAND ] = SHELL_ALIGN(sizeof(struct nbinary)),
  7327. [NOR ] = SHELL_ALIGN(sizeof(struct nbinary)),
  7328. [NSEMI ] = SHELL_ALIGN(sizeof(struct nbinary)),
  7329. [NIF ] = SHELL_ALIGN(sizeof(struct nif)),
  7330. [NWHILE ] = SHELL_ALIGN(sizeof(struct nbinary)),
  7331. [NUNTIL ] = SHELL_ALIGN(sizeof(struct nbinary)),
  7332. [NFOR ] = SHELL_ALIGN(sizeof(struct nfor)),
  7333. [NCASE ] = SHELL_ALIGN(sizeof(struct ncase)),
  7334. [NCLIST ] = SHELL_ALIGN(sizeof(struct nclist)),
  7335. [NDEFUN ] = SHELL_ALIGN(sizeof(struct narg)),
  7336. [NARG ] = SHELL_ALIGN(sizeof(struct narg)),
  7337. [NTO ] = SHELL_ALIGN(sizeof(struct nfile)),
  7338. #if ENABLE_ASH_BASH_COMPAT
  7339. [NTO2 ] = SHELL_ALIGN(sizeof(struct nfile)),
  7340. #endif
  7341. [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
  7342. [NFROM ] = SHELL_ALIGN(sizeof(struct nfile)),
  7343. [NFROMTO ] = SHELL_ALIGN(sizeof(struct nfile)),
  7344. [NAPPEND ] = SHELL_ALIGN(sizeof(struct nfile)),
  7345. [NTOFD ] = SHELL_ALIGN(sizeof(struct ndup)),
  7346. [NFROMFD ] = SHELL_ALIGN(sizeof(struct ndup)),
  7347. [NHERE ] = SHELL_ALIGN(sizeof(struct nhere)),
  7348. [NXHERE ] = SHELL_ALIGN(sizeof(struct nhere)),
  7349. [NNOT ] = SHELL_ALIGN(sizeof(struct nnot)),
  7350. };
  7351. static void calcsize(union node *n);
  7352. static void
  7353. sizenodelist(struct nodelist *lp)
  7354. {
  7355. while (lp) {
  7356. funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
  7357. calcsize(lp->n);
  7358. lp = lp->next;
  7359. }
  7360. }
  7361. static void
  7362. calcsize(union node *n)
  7363. {
  7364. if (n == NULL)
  7365. return;
  7366. funcblocksize += nodesize[n->type];
  7367. switch (n->type) {
  7368. case NCMD:
  7369. calcsize(n->ncmd.redirect);
  7370. calcsize(n->ncmd.args);
  7371. calcsize(n->ncmd.assign);
  7372. break;
  7373. case NPIPE:
  7374. sizenodelist(n->npipe.cmdlist);
  7375. break;
  7376. case NREDIR:
  7377. case NBACKGND:
  7378. case NSUBSHELL:
  7379. calcsize(n->nredir.redirect);
  7380. calcsize(n->nredir.n);
  7381. break;
  7382. case NAND:
  7383. case NOR:
  7384. case NSEMI:
  7385. case NWHILE:
  7386. case NUNTIL:
  7387. calcsize(n->nbinary.ch2);
  7388. calcsize(n->nbinary.ch1);
  7389. break;
  7390. case NIF:
  7391. calcsize(n->nif.elsepart);
  7392. calcsize(n->nif.ifpart);
  7393. calcsize(n->nif.test);
  7394. break;
  7395. case NFOR:
  7396. funcstringsize += strlen(n->nfor.var) + 1;
  7397. calcsize(n->nfor.body);
  7398. calcsize(n->nfor.args);
  7399. break;
  7400. case NCASE:
  7401. calcsize(n->ncase.cases);
  7402. calcsize(n->ncase.expr);
  7403. break;
  7404. case NCLIST:
  7405. calcsize(n->nclist.body);
  7406. calcsize(n->nclist.pattern);
  7407. calcsize(n->nclist.next);
  7408. break;
  7409. case NDEFUN:
  7410. case NARG:
  7411. sizenodelist(n->narg.backquote);
  7412. funcstringsize += strlen(n->narg.text) + 1;
  7413. calcsize(n->narg.next);
  7414. break;
  7415. case NTO:
  7416. #if ENABLE_ASH_BASH_COMPAT
  7417. case NTO2:
  7418. #endif
  7419. case NCLOBBER:
  7420. case NFROM:
  7421. case NFROMTO:
  7422. case NAPPEND:
  7423. calcsize(n->nfile.fname);
  7424. calcsize(n->nfile.next);
  7425. break;
  7426. case NTOFD:
  7427. case NFROMFD:
  7428. calcsize(n->ndup.vname);
  7429. calcsize(n->ndup.next);
  7430. break;
  7431. case NHERE:
  7432. case NXHERE:
  7433. calcsize(n->nhere.doc);
  7434. calcsize(n->nhere.next);
  7435. break;
  7436. case NNOT:
  7437. calcsize(n->nnot.com);
  7438. break;
  7439. };
  7440. }
  7441. static char *
  7442. nodeckstrdup(char *s)
  7443. {
  7444. char *rtn = funcstring;
  7445. strcpy(funcstring, s);
  7446. funcstring += strlen(s) + 1;
  7447. return rtn;
  7448. }
  7449. static union node *copynode(union node *);
  7450. static struct nodelist *
  7451. copynodelist(struct nodelist *lp)
  7452. {
  7453. struct nodelist *start;
  7454. struct nodelist **lpp;
  7455. lpp = &start;
  7456. while (lp) {
  7457. *lpp = funcblock;
  7458. funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist));
  7459. (*lpp)->n = copynode(lp->n);
  7460. lp = lp->next;
  7461. lpp = &(*lpp)->next;
  7462. }
  7463. *lpp = NULL;
  7464. return start;
  7465. }
  7466. static union node *
  7467. copynode(union node *n)
  7468. {
  7469. union node *new;
  7470. if (n == NULL)
  7471. return NULL;
  7472. new = funcblock;
  7473. funcblock = (char *) funcblock + nodesize[n->type];
  7474. switch (n->type) {
  7475. case NCMD:
  7476. new->ncmd.redirect = copynode(n->ncmd.redirect);
  7477. new->ncmd.args = copynode(n->ncmd.args);
  7478. new->ncmd.assign = copynode(n->ncmd.assign);
  7479. break;
  7480. case NPIPE:
  7481. new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
  7482. new->npipe.pipe_backgnd = n->npipe.pipe_backgnd;
  7483. break;
  7484. case NREDIR:
  7485. case NBACKGND:
  7486. case NSUBSHELL:
  7487. new->nredir.redirect = copynode(n->nredir.redirect);
  7488. new->nredir.n = copynode(n->nredir.n);
  7489. break;
  7490. case NAND:
  7491. case NOR:
  7492. case NSEMI:
  7493. case NWHILE:
  7494. case NUNTIL:
  7495. new->nbinary.ch2 = copynode(n->nbinary.ch2);
  7496. new->nbinary.ch1 = copynode(n->nbinary.ch1);
  7497. break;
  7498. case NIF:
  7499. new->nif.elsepart = copynode(n->nif.elsepart);
  7500. new->nif.ifpart = copynode(n->nif.ifpart);
  7501. new->nif.test = copynode(n->nif.test);
  7502. break;
  7503. case NFOR:
  7504. new->nfor.var = nodeckstrdup(n->nfor.var);
  7505. new->nfor.body = copynode(n->nfor.body);
  7506. new->nfor.args = copynode(n->nfor.args);
  7507. break;
  7508. case NCASE:
  7509. new->ncase.cases = copynode(n->ncase.cases);
  7510. new->ncase.expr = copynode(n->ncase.expr);
  7511. break;
  7512. case NCLIST:
  7513. new->nclist.body = copynode(n->nclist.body);
  7514. new->nclist.pattern = copynode(n->nclist.pattern);
  7515. new->nclist.next = copynode(n->nclist.next);
  7516. break;
  7517. case NDEFUN:
  7518. case NARG:
  7519. new->narg.backquote = copynodelist(n->narg.backquote);
  7520. new->narg.text = nodeckstrdup(n->narg.text);
  7521. new->narg.next = copynode(n->narg.next);
  7522. break;
  7523. case NTO:
  7524. #if ENABLE_ASH_BASH_COMPAT
  7525. case NTO2:
  7526. #endif
  7527. case NCLOBBER:
  7528. case NFROM:
  7529. case NFROMTO:
  7530. case NAPPEND:
  7531. new->nfile.fname = copynode(n->nfile.fname);
  7532. new->nfile.fd = n->nfile.fd;
  7533. new->nfile.next = copynode(n->nfile.next);
  7534. break;
  7535. case NTOFD:
  7536. case NFROMFD:
  7537. new->ndup.vname = copynode(n->ndup.vname);
  7538. new->ndup.dupfd = n->ndup.dupfd;
  7539. new->ndup.fd = n->ndup.fd;
  7540. new->ndup.next = copynode(n->ndup.next);
  7541. break;
  7542. case NHERE:
  7543. case NXHERE:
  7544. new->nhere.doc = copynode(n->nhere.doc);
  7545. new->nhere.fd = n->nhere.fd;
  7546. new->nhere.next = copynode(n->nhere.next);
  7547. break;
  7548. case NNOT:
  7549. new->nnot.com = copynode(n->nnot.com);
  7550. break;
  7551. };
  7552. new->type = n->type;
  7553. return new;
  7554. }
  7555. /*
  7556. * Make a copy of a parse tree.
  7557. */
  7558. static struct funcnode *
  7559. copyfunc(union node *n)
  7560. {
  7561. struct funcnode *f;
  7562. size_t blocksize;
  7563. funcblocksize = offsetof(struct funcnode, n);
  7564. funcstringsize = 0;
  7565. calcsize(n);
  7566. blocksize = funcblocksize;
  7567. f = ckmalloc(blocksize + funcstringsize);
  7568. funcblock = (char *) f + offsetof(struct funcnode, n);
  7569. funcstring = (char *) f + blocksize;
  7570. copynode(n);
  7571. f->count = 0;
  7572. return f;
  7573. }
  7574. /*
  7575. * Define a shell function.
  7576. */
  7577. static void
  7578. defun(char *name, union node *func)
  7579. {
  7580. struct cmdentry entry;
  7581. INT_OFF;
  7582. entry.cmdtype = CMDFUNCTION;
  7583. entry.u.func = copyfunc(func);
  7584. addcmdentry(name, &entry);
  7585. INT_ON;
  7586. }
  7587. /* Reasons for skipping commands (see comment on breakcmd routine) */
  7588. #define SKIPBREAK (1 << 0)
  7589. #define SKIPCONT (1 << 1)
  7590. #define SKIPFUNC (1 << 2)
  7591. #define SKIPFILE (1 << 3)
  7592. #define SKIPEVAL (1 << 4)
  7593. static smallint evalskip; /* set to SKIPxxx if we are skipping commands */
  7594. static int skipcount; /* number of levels to skip */
  7595. static int funcnest; /* depth of function calls */
  7596. static int loopnest; /* current loop nesting level */
  7597. /* Forward decl way out to parsing code - dotrap needs it */
  7598. static int evalstring(char *s, int mask);
  7599. /* Called to execute a trap.
  7600. * Single callsite - at the end of evaltree().
  7601. * If we return non-zero, evaltree raises EXEXIT exception.
  7602. *
  7603. * Perhaps we should avoid entering new trap handlers
  7604. * while we are executing a trap handler. [is it a TODO?]
  7605. */
  7606. static int
  7607. dotrap(void)
  7608. {
  7609. uint8_t *g;
  7610. int sig;
  7611. uint8_t savestatus;
  7612. savestatus = exitstatus;
  7613. pending_sig = 0;
  7614. xbarrier();
  7615. TRACE(("dotrap entered\n"));
  7616. for (sig = 1, g = gotsig; sig < NSIG; sig++, g++) {
  7617. int want_exexit;
  7618. char *t;
  7619. if (*g == 0)
  7620. continue;
  7621. t = trap[sig];
  7622. /* non-trapped SIGINT is handled separately by raise_interrupt,
  7623. * don't upset it by resetting gotsig[SIGINT-1] */
  7624. if (sig == SIGINT && !t)
  7625. continue;
  7626. TRACE(("sig %d is active, will run handler '%s'\n", sig, t));
  7627. *g = 0;
  7628. if (!t)
  7629. continue;
  7630. want_exexit = evalstring(t, SKIPEVAL);
  7631. exitstatus = savestatus;
  7632. if (want_exexit) {
  7633. TRACE(("dotrap returns %d\n", want_exexit));
  7634. return want_exexit;
  7635. }
  7636. }
  7637. TRACE(("dotrap returns 0\n"));
  7638. return 0;
  7639. }
  7640. /* forward declarations - evaluation is fairly recursive business... */
  7641. static void evalloop(union node *, int);
  7642. static void evalfor(union node *, int);
  7643. static void evalcase(union node *, int);
  7644. static void evalsubshell(union node *, int);
  7645. static void expredir(union node *);
  7646. static void evalpipe(union node *, int);
  7647. static void evalcommand(union node *, int);
  7648. static int evalbltin(const struct builtincmd *, int, char **);
  7649. static void prehash(union node *);
  7650. /*
  7651. * Evaluate a parse tree. The value is left in the global variable
  7652. * exitstatus.
  7653. */
  7654. static void
  7655. evaltree(union node *n, int flags)
  7656. {
  7657. struct jmploc *volatile savehandler = exception_handler;
  7658. struct jmploc jmploc;
  7659. int checkexit = 0;
  7660. void (*evalfn)(union node *, int);
  7661. int status;
  7662. int int_level;
  7663. SAVE_INT(int_level);
  7664. if (n == NULL) {
  7665. TRACE(("evaltree(NULL) called\n"));
  7666. goto out1;
  7667. }
  7668. TRACE(("evaltree(%p: %d, %d) called\n", n, n->type, flags));
  7669. exception_handler = &jmploc;
  7670. {
  7671. int err = setjmp(jmploc.loc);
  7672. if (err) {
  7673. /* if it was a signal, check for trap handlers */
  7674. if (exception_type == EXSIG) {
  7675. TRACE(("exception %d (EXSIG) in evaltree, err=%d\n",
  7676. exception_type, err));
  7677. goto out;
  7678. }
  7679. /* continue on the way out */
  7680. TRACE(("exception %d in evaltree, propagating err=%d\n",
  7681. exception_type, err));
  7682. exception_handler = savehandler;
  7683. longjmp(exception_handler->loc, err);
  7684. }
  7685. }
  7686. switch (n->type) {
  7687. default:
  7688. #if DEBUG
  7689. out1fmt("Node type = %d\n", n->type);
  7690. fflush_all();
  7691. break;
  7692. #endif
  7693. case NNOT:
  7694. evaltree(n->nnot.com, EV_TESTED);
  7695. status = !exitstatus;
  7696. goto setstatus;
  7697. case NREDIR:
  7698. expredir(n->nredir.redirect);
  7699. status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
  7700. if (!status) {
  7701. evaltree(n->nredir.n, flags & EV_TESTED);
  7702. status = exitstatus;
  7703. }
  7704. popredir(/*drop:*/ 0, /*restore:*/ 0 /* not sure */);
  7705. goto setstatus;
  7706. case NCMD:
  7707. evalfn = evalcommand;
  7708. checkexit:
  7709. if (eflag && !(flags & EV_TESTED))
  7710. checkexit = ~0;
  7711. goto calleval;
  7712. case NFOR:
  7713. evalfn = evalfor;
  7714. goto calleval;
  7715. case NWHILE:
  7716. case NUNTIL:
  7717. evalfn = evalloop;
  7718. goto calleval;
  7719. case NSUBSHELL:
  7720. case NBACKGND:
  7721. evalfn = evalsubshell;
  7722. goto calleval;
  7723. case NPIPE:
  7724. evalfn = evalpipe;
  7725. goto checkexit;
  7726. case NCASE:
  7727. evalfn = evalcase;
  7728. goto calleval;
  7729. case NAND:
  7730. case NOR:
  7731. case NSEMI: {
  7732. #if NAND + 1 != NOR
  7733. #error NAND + 1 != NOR
  7734. #endif
  7735. #if NOR + 1 != NSEMI
  7736. #error NOR + 1 != NSEMI
  7737. #endif
  7738. unsigned is_or = n->type - NAND;
  7739. evaltree(
  7740. n->nbinary.ch1,
  7741. (flags | ((is_or >> 1) - 1)) & EV_TESTED
  7742. );
  7743. if (!exitstatus == is_or)
  7744. break;
  7745. if (!evalskip) {
  7746. n = n->nbinary.ch2;
  7747. evaln:
  7748. evalfn = evaltree;
  7749. calleval:
  7750. evalfn(n, flags);
  7751. break;
  7752. }
  7753. break;
  7754. }
  7755. case NIF:
  7756. evaltree(n->nif.test, EV_TESTED);
  7757. if (evalskip)
  7758. break;
  7759. if (exitstatus == 0) {
  7760. n = n->nif.ifpart;
  7761. goto evaln;
  7762. }
  7763. if (n->nif.elsepart) {
  7764. n = n->nif.elsepart;
  7765. goto evaln;
  7766. }
  7767. goto success;
  7768. case NDEFUN:
  7769. defun(n->narg.text, n->narg.next);
  7770. success:
  7771. status = 0;
  7772. setstatus:
  7773. exitstatus = status;
  7774. break;
  7775. }
  7776. out:
  7777. exception_handler = savehandler;
  7778. out1:
  7779. /* Order of checks below is important:
  7780. * signal handlers trigger before exit caused by "set -e".
  7781. */
  7782. if (pending_sig && dotrap())
  7783. goto exexit;
  7784. if (checkexit & exitstatus)
  7785. evalskip |= SKIPEVAL;
  7786. if (flags & EV_EXIT) {
  7787. exexit:
  7788. raise_exception(EXEXIT);
  7789. }
  7790. RESTORE_INT(int_level);
  7791. TRACE(("leaving evaltree (no interrupts)\n"));
  7792. }
  7793. #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
  7794. static
  7795. #endif
  7796. void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
  7797. static void
  7798. evalloop(union node *n, int flags)
  7799. {
  7800. int status;
  7801. loopnest++;
  7802. status = 0;
  7803. flags &= EV_TESTED;
  7804. for (;;) {
  7805. int i;
  7806. evaltree(n->nbinary.ch1, EV_TESTED);
  7807. if (evalskip) {
  7808. skipping:
  7809. if (evalskip == SKIPCONT && --skipcount <= 0) {
  7810. evalskip = 0;
  7811. continue;
  7812. }
  7813. if (evalskip == SKIPBREAK && --skipcount <= 0)
  7814. evalskip = 0;
  7815. break;
  7816. }
  7817. i = exitstatus;
  7818. if (n->type != NWHILE)
  7819. i = !i;
  7820. if (i != 0)
  7821. break;
  7822. evaltree(n->nbinary.ch2, flags);
  7823. status = exitstatus;
  7824. if (evalskip)
  7825. goto skipping;
  7826. }
  7827. loopnest--;
  7828. exitstatus = status;
  7829. }
  7830. static void
  7831. evalfor(union node *n, int flags)
  7832. {
  7833. struct arglist arglist;
  7834. union node *argp;
  7835. struct strlist *sp;
  7836. struct stackmark smark;
  7837. setstackmark(&smark);
  7838. arglist.list = NULL;
  7839. arglist.lastp = &arglist.list;
  7840. for (argp = n->nfor.args; argp; argp = argp->narg.next) {
  7841. expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
  7842. /* XXX */
  7843. if (evalskip)
  7844. goto out;
  7845. }
  7846. *arglist.lastp = NULL;
  7847. exitstatus = 0;
  7848. loopnest++;
  7849. flags &= EV_TESTED;
  7850. for (sp = arglist.list; sp; sp = sp->next) {
  7851. setvar2(n->nfor.var, sp->text);
  7852. evaltree(n->nfor.body, flags);
  7853. if (evalskip) {
  7854. if (evalskip == SKIPCONT && --skipcount <= 0) {
  7855. evalskip = 0;
  7856. continue;
  7857. }
  7858. if (evalskip == SKIPBREAK && --skipcount <= 0)
  7859. evalskip = 0;
  7860. break;
  7861. }
  7862. }
  7863. loopnest--;
  7864. out:
  7865. popstackmark(&smark);
  7866. }
  7867. static void
  7868. evalcase(union node *n, int flags)
  7869. {
  7870. union node *cp;
  7871. union node *patp;
  7872. struct arglist arglist;
  7873. struct stackmark smark;
  7874. setstackmark(&smark);
  7875. arglist.list = NULL;
  7876. arglist.lastp = &arglist.list;
  7877. expandarg(n->ncase.expr, &arglist, EXP_TILDE);
  7878. exitstatus = 0;
  7879. for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
  7880. for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
  7881. if (casematch(patp, arglist.list->text)) {
  7882. if (evalskip == 0) {
  7883. evaltree(cp->nclist.body, flags);
  7884. }
  7885. goto out;
  7886. }
  7887. }
  7888. }
  7889. out:
  7890. popstackmark(&smark);
  7891. }
  7892. /*
  7893. * Kick off a subshell to evaluate a tree.
  7894. */
  7895. static void
  7896. evalsubshell(union node *n, int flags)
  7897. {
  7898. struct job *jp;
  7899. int backgnd = (n->type == NBACKGND);
  7900. int status;
  7901. expredir(n->nredir.redirect);
  7902. if (!backgnd && (flags & EV_EXIT) && !may_have_traps)
  7903. goto nofork;
  7904. INT_OFF;
  7905. jp = makejob(/*n,*/ 1);
  7906. if (forkshell(jp, n, backgnd) == 0) {
  7907. /* child */
  7908. INT_ON;
  7909. flags |= EV_EXIT;
  7910. if (backgnd)
  7911. flags &= ~EV_TESTED;
  7912. nofork:
  7913. redirect(n->nredir.redirect, 0);
  7914. evaltreenr(n->nredir.n, flags);
  7915. /* never returns */
  7916. }
  7917. status = 0;
  7918. if (!backgnd)
  7919. status = waitforjob(jp);
  7920. exitstatus = status;
  7921. INT_ON;
  7922. }
  7923. /*
  7924. * Compute the names of the files in a redirection list.
  7925. */
  7926. static void fixredir(union node *, const char *, int);
  7927. static void
  7928. expredir(union node *n)
  7929. {
  7930. union node *redir;
  7931. for (redir = n; redir; redir = redir->nfile.next) {
  7932. struct arglist fn;
  7933. fn.list = NULL;
  7934. fn.lastp = &fn.list;
  7935. switch (redir->type) {
  7936. case NFROMTO:
  7937. case NFROM:
  7938. case NTO:
  7939. #if ENABLE_ASH_BASH_COMPAT
  7940. case NTO2:
  7941. #endif
  7942. case NCLOBBER:
  7943. case NAPPEND:
  7944. expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
  7945. TRACE(("expredir expanded to '%s'\n", fn.list->text));
  7946. #if ENABLE_ASH_BASH_COMPAT
  7947. store_expfname:
  7948. #endif
  7949. #if 0
  7950. // By the design of stack allocator, the loop of this kind:
  7951. // while true; do while true; do break; done </dev/null; done
  7952. // will look like a memory leak: ash plans to free expfname's
  7953. // of "/dev/null" as soon as it finishes running the loop
  7954. // (in this case, never).
  7955. // This "fix" is wrong:
  7956. if (redir->nfile.expfname)
  7957. stunalloc(redir->nfile.expfname);
  7958. // It results in corrupted state of stacked allocations.
  7959. #endif
  7960. redir->nfile.expfname = fn.list->text;
  7961. break;
  7962. case NFROMFD:
  7963. case NTOFD: /* >& */
  7964. if (redir->ndup.vname) {
  7965. expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
  7966. if (fn.list == NULL)
  7967. ash_msg_and_raise_error("redir error");
  7968. #if ENABLE_ASH_BASH_COMPAT
  7969. //FIXME: we used expandarg with different args!
  7970. if (!isdigit_str9(fn.list->text)) {
  7971. /* >&file, not >&fd */
  7972. if (redir->nfile.fd != 1) /* 123>&file - BAD */
  7973. ash_msg_and_raise_error("redir error");
  7974. redir->type = NTO2;
  7975. goto store_expfname;
  7976. }
  7977. #endif
  7978. fixredir(redir, fn.list->text, 1);
  7979. }
  7980. break;
  7981. }
  7982. }
  7983. }
  7984. /*
  7985. * Evaluate a pipeline. All the processes in the pipeline are children
  7986. * of the process creating the pipeline. (This differs from some versions
  7987. * of the shell, which make the last process in a pipeline the parent
  7988. * of all the rest.)
  7989. */
  7990. static void
  7991. evalpipe(union node *n, int flags)
  7992. {
  7993. struct job *jp;
  7994. struct nodelist *lp;
  7995. int pipelen;
  7996. int prevfd;
  7997. int pip[2];
  7998. TRACE(("evalpipe(0x%lx) called\n", (long)n));
  7999. pipelen = 0;
  8000. for (lp = n->npipe.cmdlist; lp; lp = lp->next)
  8001. pipelen++;
  8002. flags |= EV_EXIT;
  8003. INT_OFF;
  8004. jp = makejob(/*n,*/ pipelen);
  8005. prevfd = -1;
  8006. for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
  8007. prehash(lp->n);
  8008. pip[1] = -1;
  8009. if (lp->next) {
  8010. if (pipe(pip) < 0) {
  8011. close(prevfd);
  8012. ash_msg_and_raise_error("pipe call failed");
  8013. }
  8014. }
  8015. if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) {
  8016. INT_ON;
  8017. if (pip[1] >= 0) {
  8018. close(pip[0]);
  8019. }
  8020. if (prevfd > 0) {
  8021. dup2(prevfd, 0);
  8022. close(prevfd);
  8023. }
  8024. if (pip[1] > 1) {
  8025. dup2(pip[1], 1);
  8026. close(pip[1]);
  8027. }
  8028. evaltreenr(lp->n, flags);
  8029. /* never returns */
  8030. }
  8031. if (prevfd >= 0)
  8032. close(prevfd);
  8033. prevfd = pip[0];
  8034. /* Don't want to trigger debugging */
  8035. if (pip[1] != -1)
  8036. close(pip[1]);
  8037. }
  8038. if (n->npipe.pipe_backgnd == 0) {
  8039. exitstatus = waitforjob(jp);
  8040. TRACE(("evalpipe: job done exit status %d\n", exitstatus));
  8041. }
  8042. INT_ON;
  8043. }
  8044. /*
  8045. * Controls whether the shell is interactive or not.
  8046. */
  8047. static void
  8048. setinteractive(int on)
  8049. {
  8050. static smallint is_interactive;
  8051. if (++on == is_interactive)
  8052. return;
  8053. is_interactive = on;
  8054. setsignal(SIGINT);
  8055. setsignal(SIGQUIT);
  8056. setsignal(SIGTERM);
  8057. #if !ENABLE_FEATURE_SH_EXTRA_QUIET
  8058. if (is_interactive > 1) {
  8059. /* Looks like they want an interactive shell */
  8060. static smallint did_banner;
  8061. if (!did_banner) {
  8062. /* note: ash and hush share this string */
  8063. out1fmt("\n\n%s %s\n"
  8064. IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n")
  8065. "\n",
  8066. bb_banner,
  8067. "built-in shell (ash)"
  8068. );
  8069. did_banner = 1;
  8070. }
  8071. }
  8072. #endif
  8073. }
  8074. static void
  8075. optschanged(void)
  8076. {
  8077. #if DEBUG
  8078. opentrace();
  8079. #endif
  8080. setinteractive(iflag);
  8081. setjobctl(mflag);
  8082. #if ENABLE_FEATURE_EDITING_VI
  8083. if (viflag)
  8084. line_input_state->flags |= VI_MODE;
  8085. else
  8086. line_input_state->flags &= ~VI_MODE;
  8087. #else
  8088. viflag = 0; /* forcibly keep the option off */
  8089. #endif
  8090. }
  8091. static struct localvar *localvars;
  8092. /*
  8093. * Called after a function returns.
  8094. * Interrupts must be off.
  8095. */
  8096. static void
  8097. poplocalvars(void)
  8098. {
  8099. struct localvar *lvp;
  8100. struct var *vp;
  8101. while ((lvp = localvars) != NULL) {
  8102. localvars = lvp->next;
  8103. vp = lvp->vp;
  8104. TRACE(("poplocalvar %s\n", vp ? vp->var_text : "-"));
  8105. if (vp == NULL) { /* $- saved */
  8106. memcpy(optlist, lvp->text, sizeof(optlist));
  8107. free((char*)lvp->text);
  8108. optschanged();
  8109. } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
  8110. unsetvar(vp->var_text);
  8111. } else {
  8112. if (vp->var_func)
  8113. vp->var_func(var_end(lvp->text));
  8114. if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
  8115. free((char*)vp->var_text);
  8116. vp->flags = lvp->flags;
  8117. vp->var_text = lvp->text;
  8118. }
  8119. free(lvp);
  8120. }
  8121. }
  8122. static int
  8123. evalfun(struct funcnode *func, int argc, char **argv, int flags)
  8124. {
  8125. volatile struct shparam saveparam;
  8126. struct localvar *volatile savelocalvars;
  8127. struct jmploc *volatile savehandler;
  8128. struct jmploc jmploc;
  8129. int e;
  8130. saveparam = shellparam;
  8131. savelocalvars = localvars;
  8132. e = setjmp(jmploc.loc);
  8133. if (e) {
  8134. goto funcdone;
  8135. }
  8136. INT_OFF;
  8137. savehandler = exception_handler;
  8138. exception_handler = &jmploc;
  8139. localvars = NULL;
  8140. shellparam.malloced = 0;
  8141. func->count++;
  8142. funcnest++;
  8143. INT_ON;
  8144. shellparam.nparam = argc - 1;
  8145. shellparam.p = argv + 1;
  8146. #if ENABLE_ASH_GETOPTS
  8147. shellparam.optind = 1;
  8148. shellparam.optoff = -1;
  8149. #endif
  8150. evaltree(&func->n, flags & EV_TESTED);
  8151. funcdone:
  8152. INT_OFF;
  8153. funcnest--;
  8154. freefunc(func);
  8155. poplocalvars();
  8156. localvars = savelocalvars;
  8157. freeparam(&shellparam);
  8158. shellparam = saveparam;
  8159. exception_handler = savehandler;
  8160. INT_ON;
  8161. evalskip &= ~SKIPFUNC;
  8162. return e;
  8163. }
  8164. #if ENABLE_ASH_CMDCMD
  8165. static char **
  8166. parse_command_args(char **argv, const char **path)
  8167. {
  8168. char *cp, c;
  8169. for (;;) {
  8170. cp = *++argv;
  8171. if (!cp)
  8172. return 0;
  8173. if (*cp++ != '-')
  8174. break;
  8175. c = *cp++;
  8176. if (!c)
  8177. break;
  8178. if (c == '-' && !*cp) {
  8179. argv++;
  8180. break;
  8181. }
  8182. do {
  8183. switch (c) {
  8184. case 'p':
  8185. *path = bb_default_path;
  8186. break;
  8187. default:
  8188. /* run 'typecmd' for other options */
  8189. return 0;
  8190. }
  8191. c = *cp++;
  8192. } while (c);
  8193. }
  8194. return argv;
  8195. }
  8196. #endif
  8197. /*
  8198. * Make a variable a local variable. When a variable is made local, it's
  8199. * value and flags are saved in a localvar structure. The saved values
  8200. * will be restored when the shell function returns. We handle the name
  8201. * "-" as a special case.
  8202. */
  8203. static void
  8204. mklocal(char *name)
  8205. {
  8206. struct localvar *lvp;
  8207. struct var **vpp;
  8208. struct var *vp;
  8209. INT_OFF;
  8210. lvp = ckzalloc(sizeof(struct localvar));
  8211. if (LONE_DASH(name)) {
  8212. char *p;
  8213. p = ckmalloc(sizeof(optlist));
  8214. lvp->text = memcpy(p, optlist, sizeof(optlist));
  8215. vp = NULL;
  8216. } else {
  8217. char *eq;
  8218. vpp = hashvar(name);
  8219. vp = *findvar(vpp, name);
  8220. eq = strchr(name, '=');
  8221. if (vp == NULL) {
  8222. if (eq)
  8223. setvareq(name, VSTRFIXED);
  8224. else
  8225. setvar(name, NULL, VSTRFIXED);
  8226. vp = *vpp; /* the new variable */
  8227. lvp->flags = VUNSET;
  8228. } else {
  8229. lvp->text = vp->var_text;
  8230. lvp->flags = vp->flags;
  8231. vp->flags |= VSTRFIXED|VTEXTFIXED;
  8232. if (eq)
  8233. setvareq(name, 0);
  8234. else
  8235. /* "local VAR" unsets VAR: */
  8236. setvar(name, NULL, 0);
  8237. }
  8238. }
  8239. lvp->vp = vp;
  8240. lvp->next = localvars;
  8241. localvars = lvp;
  8242. INT_ON;
  8243. }
  8244. /*
  8245. * The "local" command.
  8246. */
  8247. static int FAST_FUNC
  8248. localcmd(int argc UNUSED_PARAM, char **argv)
  8249. {
  8250. char *name;
  8251. argv = argptr;
  8252. while ((name = *argv++) != NULL) {
  8253. mklocal(name);
  8254. }
  8255. return 0;
  8256. }
  8257. static int FAST_FUNC
  8258. falsecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  8259. {
  8260. return 1;
  8261. }
  8262. static int FAST_FUNC
  8263. truecmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  8264. {
  8265. return 0;
  8266. }
  8267. static int FAST_FUNC
  8268. execcmd(int argc UNUSED_PARAM, char **argv)
  8269. {
  8270. if (argv[1]) {
  8271. iflag = 0; /* exit on error */
  8272. mflag = 0;
  8273. optschanged();
  8274. shellexec(argv + 1, pathval(), 0);
  8275. }
  8276. return 0;
  8277. }
  8278. /*
  8279. * The return command.
  8280. */
  8281. static int FAST_FUNC
  8282. returncmd(int argc UNUSED_PARAM, char **argv)
  8283. {
  8284. /*
  8285. * If called outside a function, do what ksh does;
  8286. * skip the rest of the file.
  8287. */
  8288. evalskip = funcnest ? SKIPFUNC : SKIPFILE;
  8289. return argv[1] ? number(argv[1]) : exitstatus;
  8290. }
  8291. /* Forward declarations for builtintab[] */
  8292. static int breakcmd(int, char **) FAST_FUNC;
  8293. static int dotcmd(int, char **) FAST_FUNC;
  8294. static int evalcmd(int, char **) FAST_FUNC;
  8295. static int exitcmd(int, char **) FAST_FUNC;
  8296. static int exportcmd(int, char **) FAST_FUNC;
  8297. #if ENABLE_ASH_GETOPTS
  8298. static int getoptscmd(int, char **) FAST_FUNC;
  8299. #endif
  8300. #if ENABLE_ASH_HELP
  8301. static int helpcmd(int, char **) FAST_FUNC;
  8302. #endif
  8303. #if MAX_HISTORY
  8304. static int historycmd(int, char **) FAST_FUNC;
  8305. #endif
  8306. #if ENABLE_SH_MATH_SUPPORT
  8307. static int letcmd(int, char **) FAST_FUNC;
  8308. #endif
  8309. static int readcmd(int, char **) FAST_FUNC;
  8310. static int setcmd(int, char **) FAST_FUNC;
  8311. static int shiftcmd(int, char **) FAST_FUNC;
  8312. static int timescmd(int, char **) FAST_FUNC;
  8313. static int trapcmd(int, char **) FAST_FUNC;
  8314. static int umaskcmd(int, char **) FAST_FUNC;
  8315. static int unsetcmd(int, char **) FAST_FUNC;
  8316. static int ulimitcmd(int, char **) FAST_FUNC;
  8317. #define BUILTIN_NOSPEC "0"
  8318. #define BUILTIN_SPECIAL "1"
  8319. #define BUILTIN_REGULAR "2"
  8320. #define BUILTIN_SPEC_REG "3"
  8321. #define BUILTIN_ASSIGN "4"
  8322. #define BUILTIN_SPEC_ASSG "5"
  8323. #define BUILTIN_REG_ASSG "6"
  8324. #define BUILTIN_SPEC_REG_ASSG "7"
  8325. /* Stubs for calling non-FAST_FUNC's */
  8326. #if ENABLE_ASH_BUILTIN_ECHO
  8327. static int FAST_FUNC echocmd(int argc, char **argv) { return echo_main(argc, argv); }
  8328. #endif
  8329. #if ENABLE_ASH_BUILTIN_PRINTF
  8330. static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
  8331. #endif
  8332. #if ENABLE_ASH_BUILTIN_TEST
  8333. static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, argv); }
  8334. #endif
  8335. /* Keep these in proper order since it is searched via bsearch() */
  8336. static const struct builtincmd builtintab[] = {
  8337. { BUILTIN_SPEC_REG "." , dotcmd },
  8338. { BUILTIN_SPEC_REG ":" , truecmd },
  8339. #if ENABLE_ASH_BUILTIN_TEST
  8340. { BUILTIN_REGULAR "[" , testcmd },
  8341. #if ENABLE_ASH_BASH_COMPAT
  8342. { BUILTIN_REGULAR "[[" , testcmd },
  8343. #endif
  8344. #endif
  8345. #if ENABLE_ASH_ALIAS
  8346. { BUILTIN_REG_ASSG "alias" , aliascmd },
  8347. #endif
  8348. #if JOBS
  8349. { BUILTIN_REGULAR "bg" , fg_bgcmd },
  8350. #endif
  8351. { BUILTIN_SPEC_REG "break" , breakcmd },
  8352. { BUILTIN_REGULAR "cd" , cdcmd },
  8353. { BUILTIN_NOSPEC "chdir" , cdcmd },
  8354. #if ENABLE_ASH_CMDCMD
  8355. { BUILTIN_REGULAR "command" , commandcmd },
  8356. #endif
  8357. { BUILTIN_SPEC_REG "continue", breakcmd },
  8358. #if ENABLE_ASH_BUILTIN_ECHO
  8359. { BUILTIN_REGULAR "echo" , echocmd },
  8360. #endif
  8361. { BUILTIN_SPEC_REG "eval" , evalcmd },
  8362. { BUILTIN_SPEC_REG "exec" , execcmd },
  8363. { BUILTIN_SPEC_REG "exit" , exitcmd },
  8364. { BUILTIN_SPEC_REG_ASSG "export" , exportcmd },
  8365. { BUILTIN_REGULAR "false" , falsecmd },
  8366. #if JOBS
  8367. { BUILTIN_REGULAR "fg" , fg_bgcmd },
  8368. #endif
  8369. #if ENABLE_ASH_GETOPTS
  8370. { BUILTIN_REGULAR "getopts" , getoptscmd },
  8371. #endif
  8372. { BUILTIN_NOSPEC "hash" , hashcmd },
  8373. #if ENABLE_ASH_HELP
  8374. { BUILTIN_NOSPEC "help" , helpcmd },
  8375. #endif
  8376. #if MAX_HISTORY
  8377. { BUILTIN_NOSPEC "history" , historycmd },
  8378. #endif
  8379. #if JOBS
  8380. { BUILTIN_REGULAR "jobs" , jobscmd },
  8381. { BUILTIN_REGULAR "kill" , killcmd },
  8382. #endif
  8383. #if ENABLE_SH_MATH_SUPPORT
  8384. { BUILTIN_NOSPEC "let" , letcmd },
  8385. #endif
  8386. { BUILTIN_ASSIGN "local" , localcmd },
  8387. #if ENABLE_ASH_BUILTIN_PRINTF
  8388. { BUILTIN_REGULAR "printf" , printfcmd },
  8389. #endif
  8390. { BUILTIN_NOSPEC "pwd" , pwdcmd },
  8391. { BUILTIN_REGULAR "read" , readcmd },
  8392. { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
  8393. { BUILTIN_SPEC_REG "return" , returncmd },
  8394. { BUILTIN_SPEC_REG "set" , setcmd },
  8395. { BUILTIN_SPEC_REG "shift" , shiftcmd },
  8396. #if ENABLE_ASH_BASH_COMPAT
  8397. { BUILTIN_SPEC_REG "source" , dotcmd },
  8398. #endif
  8399. #if ENABLE_ASH_BUILTIN_TEST
  8400. { BUILTIN_REGULAR "test" , testcmd },
  8401. #endif
  8402. { BUILTIN_SPEC_REG "times" , timescmd },
  8403. { BUILTIN_SPEC_REG "trap" , trapcmd },
  8404. { BUILTIN_REGULAR "true" , truecmd },
  8405. { BUILTIN_NOSPEC "type" , typecmd },
  8406. { BUILTIN_NOSPEC "ulimit" , ulimitcmd },
  8407. { BUILTIN_REGULAR "umask" , umaskcmd },
  8408. #if ENABLE_ASH_ALIAS
  8409. { BUILTIN_REGULAR "unalias" , unaliascmd },
  8410. #endif
  8411. { BUILTIN_SPEC_REG "unset" , unsetcmd },
  8412. { BUILTIN_REGULAR "wait" , waitcmd },
  8413. };
  8414. /* Should match the above table! */
  8415. #define COMMANDCMD (builtintab + \
  8416. 2 + \
  8417. 1 * ENABLE_ASH_BUILTIN_TEST + \
  8418. 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
  8419. 1 * ENABLE_ASH_ALIAS + \
  8420. 1 * ENABLE_ASH_JOB_CONTROL + \
  8421. 3)
  8422. #define EXECCMD (builtintab + \
  8423. 2 + \
  8424. 1 * ENABLE_ASH_BUILTIN_TEST + \
  8425. 1 * ENABLE_ASH_BUILTIN_TEST * ENABLE_ASH_BASH_COMPAT + \
  8426. 1 * ENABLE_ASH_ALIAS + \
  8427. 1 * ENABLE_ASH_JOB_CONTROL + \
  8428. 3 + \
  8429. 1 * ENABLE_ASH_CMDCMD + \
  8430. 1 + \
  8431. ENABLE_ASH_BUILTIN_ECHO + \
  8432. 1)
  8433. /*
  8434. * Search the table of builtin commands.
  8435. */
  8436. static struct builtincmd *
  8437. find_builtin(const char *name)
  8438. {
  8439. struct builtincmd *bp;
  8440. bp = bsearch(
  8441. name, builtintab, ARRAY_SIZE(builtintab), sizeof(builtintab[0]),
  8442. pstrcmp
  8443. );
  8444. return bp;
  8445. }
  8446. /*
  8447. * Execute a simple command.
  8448. */
  8449. static int
  8450. isassignment(const char *p)
  8451. {
  8452. const char *q = endofname(p);
  8453. if (p == q)
  8454. return 0;
  8455. return *q == '=';
  8456. }
  8457. static int FAST_FUNC
  8458. bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  8459. {
  8460. /* Preserve exitstatus of a previous possible redirection
  8461. * as POSIX mandates */
  8462. return back_exitstatus;
  8463. }
  8464. static void
  8465. evalcommand(union node *cmd, int flags)
  8466. {
  8467. static const struct builtincmd null_bltin = {
  8468. "\0\0", bltincmd /* why three NULs? */
  8469. };
  8470. struct stackmark smark;
  8471. union node *argp;
  8472. struct arglist arglist;
  8473. struct arglist varlist;
  8474. char **argv;
  8475. int argc;
  8476. const struct strlist *sp;
  8477. struct cmdentry cmdentry;
  8478. struct job *jp;
  8479. char *lastarg;
  8480. const char *path;
  8481. int spclbltin;
  8482. int status;
  8483. char **nargv;
  8484. struct builtincmd *bcmd;
  8485. smallint cmd_is_exec;
  8486. smallint pseudovarflag = 0;
  8487. /* First expand the arguments. */
  8488. TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
  8489. setstackmark(&smark);
  8490. back_exitstatus = 0;
  8491. cmdentry.cmdtype = CMDBUILTIN;
  8492. cmdentry.u.cmd = &null_bltin;
  8493. varlist.lastp = &varlist.list;
  8494. *varlist.lastp = NULL;
  8495. arglist.lastp = &arglist.list;
  8496. *arglist.lastp = NULL;
  8497. argc = 0;
  8498. if (cmd->ncmd.args) {
  8499. bcmd = find_builtin(cmd->ncmd.args->narg.text);
  8500. pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
  8501. }
  8502. for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
  8503. struct strlist **spp;
  8504. spp = arglist.lastp;
  8505. if (pseudovarflag && isassignment(argp->narg.text))
  8506. expandarg(argp, &arglist, EXP_VARTILDE);
  8507. else
  8508. expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
  8509. for (sp = *spp; sp; sp = sp->next)
  8510. argc++;
  8511. }
  8512. argv = nargv = stalloc(sizeof(char *) * (argc + 1));
  8513. for (sp = arglist.list; sp; sp = sp->next) {
  8514. TRACE(("evalcommand arg: %s\n", sp->text));
  8515. *nargv++ = sp->text;
  8516. }
  8517. *nargv = NULL;
  8518. lastarg = NULL;
  8519. if (iflag && funcnest == 0 && argc > 0)
  8520. lastarg = nargv[-1];
  8521. preverrout_fd = 2;
  8522. expredir(cmd->ncmd.redirect);
  8523. status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH | REDIR_SAVEFD2);
  8524. path = vpath.var_text;
  8525. for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
  8526. struct strlist **spp;
  8527. char *p;
  8528. spp = varlist.lastp;
  8529. expandarg(argp, &varlist, EXP_VARTILDE);
  8530. /*
  8531. * Modify the command lookup path, if a PATH= assignment
  8532. * is present
  8533. */
  8534. p = (*spp)->text;
  8535. if (varcmp(p, path) == 0)
  8536. path = p;
  8537. }
  8538. /* Print the command if xflag is set. */
  8539. if (xflag) {
  8540. int n;
  8541. const char *p = " %s" + 1;
  8542. fdprintf(preverrout_fd, p, expandstr(ps4val()));
  8543. sp = varlist.list;
  8544. for (n = 0; n < 2; n++) {
  8545. while (sp) {
  8546. fdprintf(preverrout_fd, p, sp->text);
  8547. sp = sp->next;
  8548. p = " %s";
  8549. }
  8550. sp = arglist.list;
  8551. }
  8552. safe_write(preverrout_fd, "\n", 1);
  8553. }
  8554. cmd_is_exec = 0;
  8555. spclbltin = -1;
  8556. /* Now locate the command. */
  8557. if (argc) {
  8558. int cmd_flag = DO_ERR;
  8559. #if ENABLE_ASH_CMDCMD
  8560. const char *oldpath = path + 5;
  8561. #endif
  8562. path += 5;
  8563. for (;;) {
  8564. find_command(argv[0], &cmdentry, cmd_flag, path);
  8565. if (cmdentry.cmdtype == CMDUNKNOWN) {
  8566. flush_stdout_stderr();
  8567. status = 127;
  8568. goto bail;
  8569. }
  8570. /* implement bltin and command here */
  8571. if (cmdentry.cmdtype != CMDBUILTIN)
  8572. break;
  8573. if (spclbltin < 0)
  8574. spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
  8575. if (cmdentry.u.cmd == EXECCMD)
  8576. cmd_is_exec = 1;
  8577. #if ENABLE_ASH_CMDCMD
  8578. if (cmdentry.u.cmd == COMMANDCMD) {
  8579. path = oldpath;
  8580. nargv = parse_command_args(argv, &path);
  8581. if (!nargv)
  8582. break;
  8583. argc -= nargv - argv;
  8584. argv = nargv;
  8585. cmd_flag |= DO_NOFUNC;
  8586. } else
  8587. #endif
  8588. break;
  8589. }
  8590. }
  8591. if (status) {
  8592. /* We have a redirection error. */
  8593. if (spclbltin > 0)
  8594. raise_exception(EXERROR);
  8595. bail:
  8596. exitstatus = status;
  8597. goto out;
  8598. }
  8599. /* Execute the command. */
  8600. switch (cmdentry.cmdtype) {
  8601. default: {
  8602. #if ENABLE_FEATURE_SH_NOFORK
  8603. /* (1) BUG: if variables are set, we need to fork, or save/restore them
  8604. * around run_nofork_applet() call.
  8605. * (2) Should this check also be done in forkshell()?
  8606. * (perhaps it should, so that "VAR=VAL nofork" at least avoids exec...)
  8607. */
  8608. /* find_command() encodes applet_no as (-2 - applet_no) */
  8609. int applet_no = (- cmdentry.u.index - 2);
  8610. if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
  8611. listsetvar(varlist.list, VEXPORT|VSTACK);
  8612. /* run <applet>_main() */
  8613. exitstatus = run_nofork_applet(applet_no, argv);
  8614. break;
  8615. }
  8616. #endif
  8617. /* Can we avoid forking off? For example, very last command
  8618. * in a script or a subshell does not need forking,
  8619. * we can just exec it.
  8620. */
  8621. if (!(flags & EV_EXIT) || may_have_traps) {
  8622. /* No, forking off a child is necessary */
  8623. INT_OFF;
  8624. jp = makejob(/*cmd,*/ 1);
  8625. if (forkshell(jp, cmd, FORK_FG) != 0) {
  8626. /* parent */
  8627. exitstatus = waitforjob(jp);
  8628. INT_ON;
  8629. TRACE(("forked child exited with %d\n", exitstatus));
  8630. break;
  8631. }
  8632. /* child */
  8633. FORCE_INT_ON;
  8634. /* fall through to exec'ing external program */
  8635. }
  8636. listsetvar(varlist.list, VEXPORT|VSTACK);
  8637. shellexec(argv, path, cmdentry.u.index);
  8638. /* NOTREACHED */
  8639. } /* default */
  8640. case CMDBUILTIN:
  8641. cmdenviron = varlist.list;
  8642. if (cmdenviron) {
  8643. struct strlist *list = cmdenviron;
  8644. int i = VNOSET;
  8645. if (spclbltin > 0 || argc == 0) {
  8646. i = 0;
  8647. if (cmd_is_exec && argc > 1)
  8648. i = VEXPORT;
  8649. }
  8650. listsetvar(list, i);
  8651. }
  8652. /* Tight loop with builtins only:
  8653. * "while kill -0 $child; do true; done"
  8654. * will never exit even if $child died, unless we do this
  8655. * to reap the zombie and make kill detect that it's gone: */
  8656. dowait(DOWAIT_NONBLOCK, NULL);
  8657. if (evalbltin(cmdentry.u.cmd, argc, argv)) {
  8658. int exit_status;
  8659. int i = exception_type;
  8660. if (i == EXEXIT)
  8661. goto raise;
  8662. exit_status = 2;
  8663. if (i == EXINT)
  8664. exit_status = 128 + SIGINT;
  8665. if (i == EXSIG)
  8666. exit_status = 128 + pending_sig;
  8667. exitstatus = exit_status;
  8668. if (i == EXINT || spclbltin > 0) {
  8669. raise:
  8670. longjmp(exception_handler->loc, 1);
  8671. }
  8672. FORCE_INT_ON;
  8673. }
  8674. break;
  8675. case CMDFUNCTION:
  8676. listsetvar(varlist.list, 0);
  8677. /* See above for the rationale */
  8678. dowait(DOWAIT_NONBLOCK, NULL);
  8679. if (evalfun(cmdentry.u.func, argc, argv, flags))
  8680. goto raise;
  8681. break;
  8682. } /* switch */
  8683. out:
  8684. popredir(/*drop:*/ cmd_is_exec, /*restore:*/ cmd_is_exec);
  8685. if (lastarg) {
  8686. /* dsl: I think this is intended to be used to support
  8687. * '_' in 'vi' command mode during line editing...
  8688. * However I implemented that within libedit itself.
  8689. */
  8690. setvar2("_", lastarg);
  8691. }
  8692. popstackmark(&smark);
  8693. }
  8694. static int
  8695. evalbltin(const struct builtincmd *cmd, int argc, char **argv)
  8696. {
  8697. char *volatile savecmdname;
  8698. struct jmploc *volatile savehandler;
  8699. struct jmploc jmploc;
  8700. int i;
  8701. savecmdname = commandname;
  8702. i = setjmp(jmploc.loc);
  8703. if (i)
  8704. goto cmddone;
  8705. savehandler = exception_handler;
  8706. exception_handler = &jmploc;
  8707. commandname = argv[0];
  8708. argptr = argv + 1;
  8709. optptr = NULL; /* initialize nextopt */
  8710. exitstatus = (*cmd->builtin)(argc, argv);
  8711. flush_stdout_stderr();
  8712. cmddone:
  8713. exitstatus |= ferror(stdout);
  8714. clearerr(stdout);
  8715. commandname = savecmdname;
  8716. exception_handler = savehandler;
  8717. return i;
  8718. }
  8719. static int
  8720. goodname(const char *p)
  8721. {
  8722. return endofname(p)[0] == '\0';
  8723. }
  8724. /*
  8725. * Search for a command. This is called before we fork so that the
  8726. * location of the command will be available in the parent as well as
  8727. * the child. The check for "goodname" is an overly conservative
  8728. * check that the name will not be subject to expansion.
  8729. */
  8730. static void
  8731. prehash(union node *n)
  8732. {
  8733. struct cmdentry entry;
  8734. if (n->type == NCMD && n->ncmd.args && goodname(n->ncmd.args->narg.text))
  8735. find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
  8736. }
  8737. /* ============ Builtin commands
  8738. *
  8739. * Builtin commands whose functions are closely tied to evaluation
  8740. * are implemented here.
  8741. */
  8742. /*
  8743. * Handle break and continue commands. Break, continue, and return are
  8744. * all handled by setting the evalskip flag. The evaluation routines
  8745. * above all check this flag, and if it is set they start skipping
  8746. * commands rather than executing them. The variable skipcount is
  8747. * the number of loops to break/continue, or the number of function
  8748. * levels to return. (The latter is always 1.) It should probably
  8749. * be an error to break out of more loops than exist, but it isn't
  8750. * in the standard shell so we don't make it one here.
  8751. */
  8752. static int FAST_FUNC
  8753. breakcmd(int argc UNUSED_PARAM, char **argv)
  8754. {
  8755. int n = argv[1] ? number(argv[1]) : 1;
  8756. if (n <= 0)
  8757. ash_msg_and_raise_error(msg_illnum, argv[1]);
  8758. if (n > loopnest)
  8759. n = loopnest;
  8760. if (n > 0) {
  8761. evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
  8762. skipcount = n;
  8763. }
  8764. return 0;
  8765. }
  8766. /* ============ input.c
  8767. *
  8768. * This implements the input routines used by the parser.
  8769. */
  8770. enum {
  8771. INPUT_PUSH_FILE = 1,
  8772. INPUT_NOFILE_OK = 2,
  8773. };
  8774. static smallint checkkwd;
  8775. /* values of checkkwd variable */
  8776. #define CHKALIAS 0x1
  8777. #define CHKKWD 0x2
  8778. #define CHKNL 0x4
  8779. /*
  8780. * Push a string back onto the input at this current parsefile level.
  8781. * We handle aliases this way.
  8782. */
  8783. #if !ENABLE_ASH_ALIAS
  8784. #define pushstring(s, ap) pushstring(s)
  8785. #endif
  8786. static void
  8787. pushstring(char *s, struct alias *ap)
  8788. {
  8789. struct strpush *sp;
  8790. int len;
  8791. len = strlen(s);
  8792. INT_OFF;
  8793. if (g_parsefile->strpush) {
  8794. sp = ckzalloc(sizeof(*sp));
  8795. sp->prev = g_parsefile->strpush;
  8796. } else {
  8797. sp = &(g_parsefile->basestrpush);
  8798. }
  8799. g_parsefile->strpush = sp;
  8800. sp->prev_string = g_parsefile->next_to_pgetc;
  8801. sp->prev_left_in_line = g_parsefile->left_in_line;
  8802. #if ENABLE_ASH_ALIAS
  8803. sp->ap = ap;
  8804. if (ap) {
  8805. ap->flag |= ALIASINUSE;
  8806. sp->string = s;
  8807. }
  8808. #endif
  8809. g_parsefile->next_to_pgetc = s;
  8810. g_parsefile->left_in_line = len;
  8811. INT_ON;
  8812. }
  8813. static void
  8814. popstring(void)
  8815. {
  8816. struct strpush *sp = g_parsefile->strpush;
  8817. INT_OFF;
  8818. #if ENABLE_ASH_ALIAS
  8819. if (sp->ap) {
  8820. if (g_parsefile->next_to_pgetc[-1] == ' '
  8821. || g_parsefile->next_to_pgetc[-1] == '\t'
  8822. ) {
  8823. checkkwd |= CHKALIAS;
  8824. }
  8825. if (sp->string != sp->ap->val) {
  8826. free(sp->string);
  8827. }
  8828. sp->ap->flag &= ~ALIASINUSE;
  8829. if (sp->ap->flag & ALIASDEAD) {
  8830. unalias(sp->ap->name);
  8831. }
  8832. }
  8833. #endif
  8834. g_parsefile->next_to_pgetc = sp->prev_string;
  8835. g_parsefile->left_in_line = sp->prev_left_in_line;
  8836. g_parsefile->strpush = sp->prev;
  8837. if (sp != &(g_parsefile->basestrpush))
  8838. free(sp);
  8839. INT_ON;
  8840. }
  8841. //FIXME: BASH_COMPAT with "...&" does TWO pungetc():
  8842. //it peeks whether it is &>, and then pushes back both chars.
  8843. //This function needs to save last *next_to_pgetc to buf[0]
  8844. //to make two pungetc() reliable. Currently,
  8845. // pgetc (out of buf: does preadfd), pgetc, pungetc, pungetc won't work...
  8846. static int
  8847. preadfd(void)
  8848. {
  8849. int nr;
  8850. char *buf = g_parsefile->buf;
  8851. g_parsefile->next_to_pgetc = buf;
  8852. #if ENABLE_FEATURE_EDITING
  8853. retry:
  8854. if (!iflag || g_parsefile->pf_fd != STDIN_FILENO)
  8855. nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1, /*loop_on_EINTR:*/ 1);
  8856. else {
  8857. int timeout = -1;
  8858. # if ENABLE_ASH_IDLE_TIMEOUT
  8859. if (iflag) {
  8860. const char *tmout_var = lookupvar("TMOUT");
  8861. if (tmout_var) {
  8862. timeout = atoi(tmout_var) * 1000;
  8863. if (timeout <= 0)
  8864. timeout = -1;
  8865. }
  8866. }
  8867. # endif
  8868. # if ENABLE_FEATURE_TAB_COMPLETION
  8869. line_input_state->path_lookup = pathval();
  8870. # endif
  8871. reinit_unicode_for_ash();
  8872. nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
  8873. if (nr == 0) {
  8874. /* Ctrl+C pressed */
  8875. if (trap[SIGINT]) {
  8876. buf[0] = '\n';
  8877. buf[1] = '\0';
  8878. raise(SIGINT);
  8879. return 1;
  8880. }
  8881. goto retry;
  8882. }
  8883. if (nr < 0) {
  8884. if (errno == 0) {
  8885. /* Ctrl+D pressed */
  8886. nr = 0;
  8887. }
  8888. # if ENABLE_ASH_IDLE_TIMEOUT
  8889. else if (errno == EAGAIN && timeout > 0) {
  8890. printf("\007timed out waiting for input: auto-logout\n");
  8891. exitshell();
  8892. }
  8893. # endif
  8894. }
  8895. }
  8896. #else
  8897. nr = nonblock_immune_read(g_parsefile->pf_fd, buf, IBUFSIZ - 1, /*loop_on_EINTR:*/ 1);
  8898. #endif
  8899. #if 0 /* disabled: nonblock_immune_read() handles this problem */
  8900. if (nr < 0) {
  8901. if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
  8902. int flags = fcntl(0, F_GETFL);
  8903. if (flags >= 0 && (flags & O_NONBLOCK)) {
  8904. flags &= ~O_NONBLOCK;
  8905. if (fcntl(0, F_SETFL, flags) >= 0) {
  8906. out2str("sh: turning off NDELAY mode\n");
  8907. goto retry;
  8908. }
  8909. }
  8910. }
  8911. }
  8912. #endif
  8913. return nr;
  8914. }
  8915. /*
  8916. * Refill the input buffer and return the next input character:
  8917. *
  8918. * 1) If a string was pushed back on the input, pop it;
  8919. * 2) If an EOF was pushed back (g_parsefile->left_in_line < -BIGNUM)
  8920. * or we are reading from a string so we can't refill the buffer,
  8921. * return EOF.
  8922. * 3) If there is more stuff in this buffer, use it else call read to fill it.
  8923. * 4) Process input up to the next newline, deleting nul characters.
  8924. */
  8925. //#define pgetc_debug(...) bb_error_msg(__VA_ARGS__)
  8926. #define pgetc_debug(...) ((void)0)
  8927. static int
  8928. preadbuffer(void)
  8929. {
  8930. char *q;
  8931. int more;
  8932. while (g_parsefile->strpush) {
  8933. #if ENABLE_ASH_ALIAS
  8934. if (g_parsefile->left_in_line == -1
  8935. && g_parsefile->strpush->ap
  8936. && g_parsefile->next_to_pgetc[-1] != ' '
  8937. && g_parsefile->next_to_pgetc[-1] != '\t'
  8938. ) {
  8939. pgetc_debug("preadbuffer PEOA");
  8940. return PEOA;
  8941. }
  8942. #endif
  8943. popstring();
  8944. /* try "pgetc" now: */
  8945. pgetc_debug("preadbuffer internal pgetc at %d:%p'%s'",
  8946. g_parsefile->left_in_line,
  8947. g_parsefile->next_to_pgetc,
  8948. g_parsefile->next_to_pgetc);
  8949. if (--g_parsefile->left_in_line >= 0)
  8950. return (unsigned char)(*g_parsefile->next_to_pgetc++);
  8951. }
  8952. /* on both branches above g_parsefile->left_in_line < 0.
  8953. * "pgetc" needs refilling.
  8954. */
  8955. /* -90 is our -BIGNUM. Below we use -99 to mark "EOF on read",
  8956. * pungetc() may increment it a few times.
  8957. * Assuming it won't increment it to less than -90.
  8958. */
  8959. if (g_parsefile->left_in_line < -90 || g_parsefile->buf == NULL) {
  8960. pgetc_debug("preadbuffer PEOF1");
  8961. /* even in failure keep left_in_line and next_to_pgetc
  8962. * in lock step, for correct multi-layer pungetc.
  8963. * left_in_line was decremented before preadbuffer(),
  8964. * must inc next_to_pgetc: */
  8965. g_parsefile->next_to_pgetc++;
  8966. return PEOF;
  8967. }
  8968. more = g_parsefile->left_in_buffer;
  8969. if (more <= 0) {
  8970. flush_stdout_stderr();
  8971. again:
  8972. more = preadfd();
  8973. if (more <= 0) {
  8974. /* don't try reading again */
  8975. g_parsefile->left_in_line = -99;
  8976. pgetc_debug("preadbuffer PEOF2");
  8977. g_parsefile->next_to_pgetc++;
  8978. return PEOF;
  8979. }
  8980. }
  8981. /* Find out where's the end of line.
  8982. * Set g_parsefile->left_in_line
  8983. * and g_parsefile->left_in_buffer acordingly.
  8984. * NUL chars are deleted.
  8985. */
  8986. q = g_parsefile->next_to_pgetc;
  8987. for (;;) {
  8988. char c;
  8989. more--;
  8990. c = *q;
  8991. if (c == '\0') {
  8992. memmove(q, q + 1, more);
  8993. } else {
  8994. q++;
  8995. if (c == '\n') {
  8996. g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
  8997. break;
  8998. }
  8999. }
  9000. if (more <= 0) {
  9001. g_parsefile->left_in_line = q - g_parsefile->next_to_pgetc - 1;
  9002. if (g_parsefile->left_in_line < 0)
  9003. goto again;
  9004. break;
  9005. }
  9006. }
  9007. g_parsefile->left_in_buffer = more;
  9008. if (vflag) {
  9009. char save = *q;
  9010. *q = '\0';
  9011. out2str(g_parsefile->next_to_pgetc);
  9012. *q = save;
  9013. }
  9014. pgetc_debug("preadbuffer at %d:%p'%s'",
  9015. g_parsefile->left_in_line,
  9016. g_parsefile->next_to_pgetc,
  9017. g_parsefile->next_to_pgetc);
  9018. return (unsigned char)*g_parsefile->next_to_pgetc++;
  9019. }
  9020. #define pgetc_as_macro() \
  9021. (--g_parsefile->left_in_line >= 0 \
  9022. ? (unsigned char)*g_parsefile->next_to_pgetc++ \
  9023. : preadbuffer() \
  9024. )
  9025. static int
  9026. pgetc(void)
  9027. {
  9028. pgetc_debug("pgetc_fast at %d:%p'%s'",
  9029. g_parsefile->left_in_line,
  9030. g_parsefile->next_to_pgetc,
  9031. g_parsefile->next_to_pgetc);
  9032. return pgetc_as_macro();
  9033. }
  9034. #if ENABLE_ASH_OPTIMIZE_FOR_SIZE
  9035. # define pgetc_fast() pgetc()
  9036. #else
  9037. # define pgetc_fast() pgetc_as_macro()
  9038. #endif
  9039. #if ENABLE_ASH_ALIAS
  9040. static int
  9041. pgetc_without_PEOA(void)
  9042. {
  9043. int c;
  9044. do {
  9045. pgetc_debug("pgetc_fast at %d:%p'%s'",
  9046. g_parsefile->left_in_line,
  9047. g_parsefile->next_to_pgetc,
  9048. g_parsefile->next_to_pgetc);
  9049. c = pgetc_fast();
  9050. } while (c == PEOA);
  9051. return c;
  9052. }
  9053. #else
  9054. # define pgetc_without_PEOA() pgetc()
  9055. #endif
  9056. /*
  9057. * Read a line from the script.
  9058. */
  9059. static char *
  9060. pfgets(char *line, int len)
  9061. {
  9062. char *p = line;
  9063. int nleft = len;
  9064. int c;
  9065. while (--nleft > 0) {
  9066. c = pgetc_without_PEOA();
  9067. if (c == PEOF) {
  9068. if (p == line)
  9069. return NULL;
  9070. break;
  9071. }
  9072. *p++ = c;
  9073. if (c == '\n')
  9074. break;
  9075. }
  9076. *p = '\0';
  9077. return line;
  9078. }
  9079. /*
  9080. * Undo the last call to pgetc. Only one character may be pushed back.
  9081. * PEOF may be pushed back.
  9082. */
  9083. static void
  9084. pungetc(void)
  9085. {
  9086. g_parsefile->left_in_line++;
  9087. g_parsefile->next_to_pgetc--;
  9088. pgetc_debug("pushed back to %d:%p'%s'",
  9089. g_parsefile->left_in_line,
  9090. g_parsefile->next_to_pgetc,
  9091. g_parsefile->next_to_pgetc);
  9092. }
  9093. /*
  9094. * To handle the "." command, a stack of input files is used. Pushfile
  9095. * adds a new entry to the stack and popfile restores the previous level.
  9096. */
  9097. static void
  9098. pushfile(void)
  9099. {
  9100. struct parsefile *pf;
  9101. pf = ckzalloc(sizeof(*pf));
  9102. pf->prev = g_parsefile;
  9103. pf->pf_fd = -1;
  9104. /*pf->strpush = NULL; - ckzalloc did it */
  9105. /*pf->basestrpush.prev = NULL;*/
  9106. g_parsefile = pf;
  9107. }
  9108. static void
  9109. popfile(void)
  9110. {
  9111. struct parsefile *pf = g_parsefile;
  9112. INT_OFF;
  9113. if (pf->pf_fd >= 0)
  9114. close(pf->pf_fd);
  9115. free(pf->buf);
  9116. while (pf->strpush)
  9117. popstring();
  9118. g_parsefile = pf->prev;
  9119. free(pf);
  9120. INT_ON;
  9121. }
  9122. /*
  9123. * Return to top level.
  9124. */
  9125. static void
  9126. popallfiles(void)
  9127. {
  9128. while (g_parsefile != &basepf)
  9129. popfile();
  9130. }
  9131. /*
  9132. * Close the file(s) that the shell is reading commands from. Called
  9133. * after a fork is done.
  9134. */
  9135. static void
  9136. closescript(void)
  9137. {
  9138. popallfiles();
  9139. if (g_parsefile->pf_fd > 0) {
  9140. close(g_parsefile->pf_fd);
  9141. g_parsefile->pf_fd = 0;
  9142. }
  9143. }
  9144. /*
  9145. * Like setinputfile, but takes an open file descriptor. Call this with
  9146. * interrupts off.
  9147. */
  9148. static void
  9149. setinputfd(int fd, int push)
  9150. {
  9151. close_on_exec_on(fd);
  9152. if (push) {
  9153. pushfile();
  9154. g_parsefile->buf = NULL;
  9155. }
  9156. g_parsefile->pf_fd = fd;
  9157. if (g_parsefile->buf == NULL)
  9158. g_parsefile->buf = ckmalloc(IBUFSIZ);
  9159. g_parsefile->left_in_buffer = 0;
  9160. g_parsefile->left_in_line = 0;
  9161. g_parsefile->linno = 1;
  9162. }
  9163. /*
  9164. * Set the input to take input from a file. If push is set, push the
  9165. * old input onto the stack first.
  9166. */
  9167. static int
  9168. setinputfile(const char *fname, int flags)
  9169. {
  9170. int fd;
  9171. int fd2;
  9172. INT_OFF;
  9173. fd = open(fname, O_RDONLY);
  9174. if (fd < 0) {
  9175. if (flags & INPUT_NOFILE_OK)
  9176. goto out;
  9177. ash_msg_and_raise_error("can't open '%s'", fname);
  9178. }
  9179. if (fd < 10) {
  9180. fd2 = copyfd(fd, 10);
  9181. close(fd);
  9182. if (fd2 < 0)
  9183. ash_msg_and_raise_error("out of file descriptors");
  9184. fd = fd2;
  9185. }
  9186. setinputfd(fd, flags & INPUT_PUSH_FILE);
  9187. out:
  9188. INT_ON;
  9189. return fd;
  9190. }
  9191. /*
  9192. * Like setinputfile, but takes input from a string.
  9193. */
  9194. static void
  9195. setinputstring(char *string)
  9196. {
  9197. INT_OFF;
  9198. pushfile();
  9199. g_parsefile->next_to_pgetc = string;
  9200. g_parsefile->left_in_line = strlen(string);
  9201. g_parsefile->buf = NULL;
  9202. g_parsefile->linno = 1;
  9203. INT_ON;
  9204. }
  9205. /* ============ mail.c
  9206. *
  9207. * Routines to check for mail.
  9208. */
  9209. #if ENABLE_ASH_MAIL
  9210. #define MAXMBOXES 10
  9211. /* times of mailboxes */
  9212. static time_t mailtime[MAXMBOXES];
  9213. /* Set if MAIL or MAILPATH is changed. */
  9214. static smallint mail_var_path_changed;
  9215. /*
  9216. * Print appropriate message(s) if mail has arrived.
  9217. * If mail_var_path_changed is set,
  9218. * then the value of MAIL has mail_var_path_changed,
  9219. * so we just update the values.
  9220. */
  9221. static void
  9222. chkmail(void)
  9223. {
  9224. const char *mpath;
  9225. char *p;
  9226. char *q;
  9227. time_t *mtp;
  9228. struct stackmark smark;
  9229. struct stat statb;
  9230. setstackmark(&smark);
  9231. mpath = mpathset() ? mpathval() : mailval();
  9232. for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
  9233. p = path_advance(&mpath, nullstr);
  9234. if (p == NULL)
  9235. break;
  9236. if (*p == '\0')
  9237. continue;
  9238. for (q = p; *q; q++)
  9239. continue;
  9240. #if DEBUG
  9241. if (q[-1] != '/')
  9242. abort();
  9243. #endif
  9244. q[-1] = '\0'; /* delete trailing '/' */
  9245. if (stat(p, &statb) < 0) {
  9246. *mtp = 0;
  9247. continue;
  9248. }
  9249. if (!mail_var_path_changed && statb.st_mtime != *mtp) {
  9250. fprintf(
  9251. stderr, "%s\n",
  9252. pathopt ? pathopt : "you have mail"
  9253. );
  9254. }
  9255. *mtp = statb.st_mtime;
  9256. }
  9257. mail_var_path_changed = 0;
  9258. popstackmark(&smark);
  9259. }
  9260. static void FAST_FUNC
  9261. changemail(const char *val UNUSED_PARAM)
  9262. {
  9263. mail_var_path_changed = 1;
  9264. }
  9265. #endif /* ASH_MAIL */
  9266. /* ============ ??? */
  9267. /*
  9268. * Set the shell parameters.
  9269. */
  9270. static void
  9271. setparam(char **argv)
  9272. {
  9273. char **newparam;
  9274. char **ap;
  9275. int nparam;
  9276. for (nparam = 0; argv[nparam]; nparam++)
  9277. continue;
  9278. ap = newparam = ckmalloc((nparam + 1) * sizeof(*ap));
  9279. while (*argv) {
  9280. *ap++ = ckstrdup(*argv++);
  9281. }
  9282. *ap = NULL;
  9283. freeparam(&shellparam);
  9284. shellparam.malloced = 1;
  9285. shellparam.nparam = nparam;
  9286. shellparam.p = newparam;
  9287. #if ENABLE_ASH_GETOPTS
  9288. shellparam.optind = 1;
  9289. shellparam.optoff = -1;
  9290. #endif
  9291. }
  9292. /*
  9293. * Process shell options. The global variable argptr contains a pointer
  9294. * to the argument list; we advance it past the options.
  9295. *
  9296. * SUSv3 section 2.8.1 "Consequences of Shell Errors" says:
  9297. * For a non-interactive shell, an error condition encountered
  9298. * by a special built-in ... shall cause the shell to write a diagnostic message
  9299. * to standard error and exit as shown in the following table:
  9300. * Error Special Built-In
  9301. * ...
  9302. * Utility syntax error (option or operand error) Shall exit
  9303. * ...
  9304. * However, in bug 1142 (http://busybox.net/bugs/view.php?id=1142)
  9305. * we see that bash does not do that (set "finishes" with error code 1 instead,
  9306. * and shell continues), and people rely on this behavior!
  9307. * Testcase:
  9308. * set -o barfoo 2>/dev/null
  9309. * echo $?
  9310. *
  9311. * Oh well. Let's mimic that.
  9312. */
  9313. static int
  9314. plus_minus_o(char *name, int val)
  9315. {
  9316. int i;
  9317. if (name) {
  9318. for (i = 0; i < NOPTS; i++) {
  9319. if (strcmp(name, optnames(i)) == 0) {
  9320. optlist[i] = val;
  9321. return 0;
  9322. }
  9323. }
  9324. ash_msg("illegal option %co %s", val ? '-' : '+', name);
  9325. return 1;
  9326. }
  9327. for (i = 0; i < NOPTS; i++) {
  9328. if (val) {
  9329. out1fmt("%-16s%s\n", optnames(i), optlist[i] ? "on" : "off");
  9330. } else {
  9331. out1fmt("set %co %s\n", optlist[i] ? '-' : '+', optnames(i));
  9332. }
  9333. }
  9334. return 0;
  9335. }
  9336. static void
  9337. setoption(int flag, int val)
  9338. {
  9339. int i;
  9340. for (i = 0; i < NOPTS; i++) {
  9341. if (optletters(i) == flag) {
  9342. optlist[i] = val;
  9343. return;
  9344. }
  9345. }
  9346. ash_msg_and_raise_error("illegal option %c%c", val ? '-' : '+', flag);
  9347. /* NOTREACHED */
  9348. }
  9349. static int
  9350. options(int cmdline)
  9351. {
  9352. char *p;
  9353. int val;
  9354. int c;
  9355. if (cmdline)
  9356. minusc = NULL;
  9357. while ((p = *argptr) != NULL) {
  9358. c = *p++;
  9359. if (c != '-' && c != '+')
  9360. break;
  9361. argptr++;
  9362. val = 0; /* val = 0 if c == '+' */
  9363. if (c == '-') {
  9364. val = 1;
  9365. if (p[0] == '\0' || LONE_DASH(p)) {
  9366. if (!cmdline) {
  9367. /* "-" means turn off -x and -v */
  9368. if (p[0] == '\0')
  9369. xflag = vflag = 0;
  9370. /* "--" means reset params */
  9371. else if (*argptr == NULL)
  9372. setparam(argptr);
  9373. }
  9374. break; /* "-" or "--" terminates options */
  9375. }
  9376. }
  9377. /* first char was + or - */
  9378. while ((c = *p++) != '\0') {
  9379. /* bash 3.2 indeed handles -c CMD and +c CMD the same */
  9380. if (c == 'c' && cmdline) {
  9381. minusc = p; /* command is after shell args */
  9382. } else if (c == 'o') {
  9383. if (plus_minus_o(*argptr, val)) {
  9384. /* it already printed err message */
  9385. return 1; /* error */
  9386. }
  9387. if (*argptr)
  9388. argptr++;
  9389. } else if (cmdline && (c == 'l')) { /* -l or +l == --login */
  9390. isloginsh = 1;
  9391. /* bash does not accept +-login, we also won't */
  9392. } else if (cmdline && val && (c == '-')) { /* long options */
  9393. if (strcmp(p, "login") == 0)
  9394. isloginsh = 1;
  9395. break;
  9396. } else {
  9397. setoption(c, val);
  9398. }
  9399. }
  9400. }
  9401. return 0;
  9402. }
  9403. /*
  9404. * The shift builtin command.
  9405. */
  9406. static int FAST_FUNC
  9407. shiftcmd(int argc UNUSED_PARAM, char **argv)
  9408. {
  9409. int n;
  9410. char **ap1, **ap2;
  9411. n = 1;
  9412. if (argv[1])
  9413. n = number(argv[1]);
  9414. if (n > shellparam.nparam)
  9415. n = 0; /* bash compat, was = shellparam.nparam; */
  9416. INT_OFF;
  9417. shellparam.nparam -= n;
  9418. for (ap1 = shellparam.p; --n >= 0; ap1++) {
  9419. if (shellparam.malloced)
  9420. free(*ap1);
  9421. }
  9422. ap2 = shellparam.p;
  9423. while ((*ap2++ = *ap1++) != NULL)
  9424. continue;
  9425. #if ENABLE_ASH_GETOPTS
  9426. shellparam.optind = 1;
  9427. shellparam.optoff = -1;
  9428. #endif
  9429. INT_ON;
  9430. return 0;
  9431. }
  9432. /*
  9433. * POSIX requires that 'set' (but not export or readonly) output the
  9434. * variables in lexicographic order - by the locale's collating order (sigh).
  9435. * Maybe we could keep them in an ordered balanced binary tree
  9436. * instead of hashed lists.
  9437. * For now just roll 'em through qsort for printing...
  9438. */
  9439. static int
  9440. showvars(const char *sep_prefix, int on, int off)
  9441. {
  9442. const char *sep;
  9443. char **ep, **epend;
  9444. ep = listvars(on, off, &epend);
  9445. qsort(ep, epend - ep, sizeof(char *), vpcmp);
  9446. sep = *sep_prefix ? " " : sep_prefix;
  9447. for (; ep < epend; ep++) {
  9448. const char *p;
  9449. const char *q;
  9450. p = strchrnul(*ep, '=');
  9451. q = nullstr;
  9452. if (*p)
  9453. q = single_quote(++p);
  9454. out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
  9455. }
  9456. return 0;
  9457. }
  9458. /*
  9459. * The set command builtin.
  9460. */
  9461. static int FAST_FUNC
  9462. setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  9463. {
  9464. int retval;
  9465. if (!argv[1])
  9466. return showvars(nullstr, 0, VUNSET);
  9467. INT_OFF;
  9468. retval = options(/*cmdline:*/ 0);
  9469. if (retval == 0) { /* if no parse error... */
  9470. optschanged();
  9471. if (*argptr != NULL) {
  9472. setparam(argptr);
  9473. }
  9474. }
  9475. INT_ON;
  9476. return retval;
  9477. }
  9478. #if ENABLE_ASH_RANDOM_SUPPORT
  9479. static void FAST_FUNC
  9480. change_random(const char *value)
  9481. {
  9482. uint32_t t;
  9483. if (value == NULL) {
  9484. /* "get", generate */
  9485. t = next_random(&random_gen);
  9486. /* set without recursion */
  9487. setvar(vrandom.var_text, utoa(t), VNOFUNC);
  9488. vrandom.flags &= ~VNOFUNC;
  9489. } else {
  9490. /* set/reset */
  9491. t = strtoul(value, NULL, 10);
  9492. INIT_RANDOM_T(&random_gen, (t ? t : 1), t);
  9493. }
  9494. }
  9495. #endif
  9496. #if ENABLE_ASH_GETOPTS
  9497. static int
  9498. getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
  9499. {
  9500. char *p, *q;
  9501. char c = '?';
  9502. int done = 0;
  9503. int err = 0;
  9504. char s[12];
  9505. char **optnext;
  9506. if (*param_optind < 1)
  9507. return 1;
  9508. optnext = optfirst + *param_optind - 1;
  9509. if (*param_optind <= 1 || *optoff < 0 || (int)strlen(optnext[-1]) < *optoff)
  9510. p = NULL;
  9511. else
  9512. p = optnext[-1] + *optoff;
  9513. if (p == NULL || *p == '\0') {
  9514. /* Current word is done, advance */
  9515. p = *optnext;
  9516. if (p == NULL || *p != '-' || *++p == '\0') {
  9517. atend:
  9518. p = NULL;
  9519. done = 1;
  9520. goto out;
  9521. }
  9522. optnext++;
  9523. if (LONE_DASH(p)) /* check for "--" */
  9524. goto atend;
  9525. }
  9526. c = *p++;
  9527. for (q = optstr; *q != c;) {
  9528. if (*q == '\0') {
  9529. if (optstr[0] == ':') {
  9530. s[0] = c;
  9531. s[1] = '\0';
  9532. err |= setvarsafe("OPTARG", s, 0);
  9533. } else {
  9534. fprintf(stderr, "Illegal option -%c\n", c);
  9535. unsetvar("OPTARG");
  9536. }
  9537. c = '?';
  9538. goto out;
  9539. }
  9540. if (*++q == ':')
  9541. q++;
  9542. }
  9543. if (*++q == ':') {
  9544. if (*p == '\0' && (p = *optnext) == NULL) {
  9545. if (optstr[0] == ':') {
  9546. s[0] = c;
  9547. s[1] = '\0';
  9548. err |= setvarsafe("OPTARG", s, 0);
  9549. c = ':';
  9550. } else {
  9551. fprintf(stderr, "No arg for -%c option\n", c);
  9552. unsetvar("OPTARG");
  9553. c = '?';
  9554. }
  9555. goto out;
  9556. }
  9557. if (p == *optnext)
  9558. optnext++;
  9559. err |= setvarsafe("OPTARG", p, 0);
  9560. p = NULL;
  9561. } else
  9562. err |= setvarsafe("OPTARG", nullstr, 0);
  9563. out:
  9564. *optoff = p ? p - *(optnext - 1) : -1;
  9565. *param_optind = optnext - optfirst + 1;
  9566. fmtstr(s, sizeof(s), "%d", *param_optind);
  9567. err |= setvarsafe("OPTIND", s, VNOFUNC);
  9568. s[0] = c;
  9569. s[1] = '\0';
  9570. err |= setvarsafe(optvar, s, 0);
  9571. if (err) {
  9572. *param_optind = 1;
  9573. *optoff = -1;
  9574. flush_stdout_stderr();
  9575. raise_exception(EXERROR);
  9576. }
  9577. return done;
  9578. }
  9579. /*
  9580. * The getopts builtin. Shellparam.optnext points to the next argument
  9581. * to be processed. Shellparam.optptr points to the next character to
  9582. * be processed in the current argument. If shellparam.optnext is NULL,
  9583. * then it's the first time getopts has been called.
  9584. */
  9585. static int FAST_FUNC
  9586. getoptscmd(int argc, char **argv)
  9587. {
  9588. char **optbase;
  9589. if (argc < 3)
  9590. ash_msg_and_raise_error("usage: getopts optstring var [arg]");
  9591. if (argc == 3) {
  9592. optbase = shellparam.p;
  9593. if (shellparam.optind > shellparam.nparam + 1) {
  9594. shellparam.optind = 1;
  9595. shellparam.optoff = -1;
  9596. }
  9597. } else {
  9598. optbase = &argv[3];
  9599. if (shellparam.optind > argc - 2) {
  9600. shellparam.optind = 1;
  9601. shellparam.optoff = -1;
  9602. }
  9603. }
  9604. return getopts(argv[1], argv[2], optbase, &shellparam.optind,
  9605. &shellparam.optoff);
  9606. }
  9607. #endif /* ASH_GETOPTS */
  9608. /* ============ Shell parser */
  9609. struct heredoc {
  9610. struct heredoc *next; /* next here document in list */
  9611. union node *here; /* redirection node */
  9612. char *eofmark; /* string indicating end of input */
  9613. smallint striptabs; /* if set, strip leading tabs */
  9614. };
  9615. static smallint tokpushback; /* last token pushed back */
  9616. static smallint parsebackquote; /* nonzero if we are inside backquotes */
  9617. static smallint quoteflag; /* set if (part of) last token was quoted */
  9618. static token_id_t lasttoken; /* last token read (integer id Txxx) */
  9619. static struct heredoc *heredoclist; /* list of here documents to read */
  9620. static char *wordtext; /* text of last word returned by readtoken */
  9621. static struct nodelist *backquotelist;
  9622. static union node *redirnode;
  9623. static struct heredoc *heredoc;
  9624. static const char *
  9625. tokname(char *buf, int tok)
  9626. {
  9627. if (tok < TSEMI)
  9628. return tokname_array[tok] + 1;
  9629. sprintf(buf, "\"%s\"", tokname_array[tok] + 1);
  9630. return buf;
  9631. }
  9632. /* raise_error_unexpected_syntax:
  9633. * Called when an unexpected token is read during the parse. The argument
  9634. * is the token that is expected, or -1 if more than one type of token can
  9635. * occur at this point.
  9636. */
  9637. static void raise_error_unexpected_syntax(int) NORETURN;
  9638. static void
  9639. raise_error_unexpected_syntax(int token)
  9640. {
  9641. char msg[64];
  9642. char buf[16];
  9643. int l;
  9644. l = sprintf(msg, "unexpected %s", tokname(buf, lasttoken));
  9645. if (token >= 0)
  9646. sprintf(msg + l, " (expecting %s)", tokname(buf, token));
  9647. raise_error_syntax(msg);
  9648. /* NOTREACHED */
  9649. }
  9650. #define EOFMARKLEN 79
  9651. /* parsing is heavily cross-recursive, need these forward decls */
  9652. static union node *andor(void);
  9653. static union node *pipeline(void);
  9654. static union node *parse_command(void);
  9655. static void parseheredoc(void);
  9656. static char peektoken(void);
  9657. static int readtoken(void);
  9658. static union node *
  9659. list(int nlflag)
  9660. {
  9661. union node *n1, *n2, *n3;
  9662. int tok;
  9663. checkkwd = CHKNL | CHKKWD | CHKALIAS;
  9664. if (nlflag == 2 && peektoken())
  9665. return NULL;
  9666. n1 = NULL;
  9667. for (;;) {
  9668. n2 = andor();
  9669. tok = readtoken();
  9670. if (tok == TBACKGND) {
  9671. if (n2->type == NPIPE) {
  9672. n2->npipe.pipe_backgnd = 1;
  9673. } else {
  9674. if (n2->type != NREDIR) {
  9675. n3 = stzalloc(sizeof(struct nredir));
  9676. n3->nredir.n = n2;
  9677. /*n3->nredir.redirect = NULL; - stzalloc did it */
  9678. n2 = n3;
  9679. }
  9680. n2->type = NBACKGND;
  9681. }
  9682. }
  9683. if (n1 == NULL) {
  9684. n1 = n2;
  9685. } else {
  9686. n3 = stzalloc(sizeof(struct nbinary));
  9687. n3->type = NSEMI;
  9688. n3->nbinary.ch1 = n1;
  9689. n3->nbinary.ch2 = n2;
  9690. n1 = n3;
  9691. }
  9692. switch (tok) {
  9693. case TBACKGND:
  9694. case TSEMI:
  9695. tok = readtoken();
  9696. /* fall through */
  9697. case TNL:
  9698. if (tok == TNL) {
  9699. parseheredoc();
  9700. if (nlflag == 1)
  9701. return n1;
  9702. } else {
  9703. tokpushback = 1;
  9704. }
  9705. checkkwd = CHKNL | CHKKWD | CHKALIAS;
  9706. if (peektoken())
  9707. return n1;
  9708. break;
  9709. case TEOF:
  9710. if (heredoclist)
  9711. parseheredoc();
  9712. else
  9713. pungetc(); /* push back EOF on input */
  9714. return n1;
  9715. default:
  9716. if (nlflag == 1)
  9717. raise_error_unexpected_syntax(-1);
  9718. tokpushback = 1;
  9719. return n1;
  9720. }
  9721. }
  9722. }
  9723. static union node *
  9724. andor(void)
  9725. {
  9726. union node *n1, *n2, *n3;
  9727. int t;
  9728. n1 = pipeline();
  9729. for (;;) {
  9730. t = readtoken();
  9731. if (t == TAND) {
  9732. t = NAND;
  9733. } else if (t == TOR) {
  9734. t = NOR;
  9735. } else {
  9736. tokpushback = 1;
  9737. return n1;
  9738. }
  9739. checkkwd = CHKNL | CHKKWD | CHKALIAS;
  9740. n2 = pipeline();
  9741. n3 = stzalloc(sizeof(struct nbinary));
  9742. n3->type = t;
  9743. n3->nbinary.ch1 = n1;
  9744. n3->nbinary.ch2 = n2;
  9745. n1 = n3;
  9746. }
  9747. }
  9748. static union node *
  9749. pipeline(void)
  9750. {
  9751. union node *n1, *n2, *pipenode;
  9752. struct nodelist *lp, *prev;
  9753. int negate;
  9754. negate = 0;
  9755. TRACE(("pipeline: entered\n"));
  9756. if (readtoken() == TNOT) {
  9757. negate = !negate;
  9758. checkkwd = CHKKWD | CHKALIAS;
  9759. } else
  9760. tokpushback = 1;
  9761. n1 = parse_command();
  9762. if (readtoken() == TPIPE) {
  9763. pipenode = stzalloc(sizeof(struct npipe));
  9764. pipenode->type = NPIPE;
  9765. /*pipenode->npipe.pipe_backgnd = 0; - stzalloc did it */
  9766. lp = stzalloc(sizeof(struct nodelist));
  9767. pipenode->npipe.cmdlist = lp;
  9768. lp->n = n1;
  9769. do {
  9770. prev = lp;
  9771. lp = stzalloc(sizeof(struct nodelist));
  9772. checkkwd = CHKNL | CHKKWD | CHKALIAS;
  9773. lp->n = parse_command();
  9774. prev->next = lp;
  9775. } while (readtoken() == TPIPE);
  9776. lp->next = NULL;
  9777. n1 = pipenode;
  9778. }
  9779. tokpushback = 1;
  9780. if (negate) {
  9781. n2 = stzalloc(sizeof(struct nnot));
  9782. n2->type = NNOT;
  9783. n2->nnot.com = n1;
  9784. return n2;
  9785. }
  9786. return n1;
  9787. }
  9788. static union node *
  9789. makename(void)
  9790. {
  9791. union node *n;
  9792. n = stzalloc(sizeof(struct narg));
  9793. n->type = NARG;
  9794. /*n->narg.next = NULL; - stzalloc did it */
  9795. n->narg.text = wordtext;
  9796. n->narg.backquote = backquotelist;
  9797. return n;
  9798. }
  9799. static void
  9800. fixredir(union node *n, const char *text, int err)
  9801. {
  9802. int fd;
  9803. TRACE(("Fix redir %s %d\n", text, err));
  9804. if (!err)
  9805. n->ndup.vname = NULL;
  9806. fd = bb_strtou(text, NULL, 10);
  9807. if (!errno && fd >= 0)
  9808. n->ndup.dupfd = fd;
  9809. else if (LONE_DASH(text))
  9810. n->ndup.dupfd = -1;
  9811. else {
  9812. if (err)
  9813. raise_error_syntax("bad fd number");
  9814. n->ndup.vname = makename();
  9815. }
  9816. }
  9817. /*
  9818. * Returns true if the text contains nothing to expand (no dollar signs
  9819. * or backquotes).
  9820. */
  9821. static int
  9822. noexpand(const char *text)
  9823. {
  9824. unsigned char c;
  9825. while ((c = *text++) != '\0') {
  9826. if (c == CTLQUOTEMARK)
  9827. continue;
  9828. if (c == CTLESC)
  9829. text++;
  9830. else if (SIT(c, BASESYNTAX) == CCTL)
  9831. return 0;
  9832. }
  9833. return 1;
  9834. }
  9835. static void
  9836. parsefname(void)
  9837. {
  9838. union node *n = redirnode;
  9839. if (readtoken() != TWORD)
  9840. raise_error_unexpected_syntax(-1);
  9841. if (n->type == NHERE) {
  9842. struct heredoc *here = heredoc;
  9843. struct heredoc *p;
  9844. int i;
  9845. if (quoteflag == 0)
  9846. n->type = NXHERE;
  9847. TRACE(("Here document %d\n", n->type));
  9848. if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
  9849. raise_error_syntax("illegal eof marker for << redirection");
  9850. rmescapes(wordtext, 0);
  9851. here->eofmark = wordtext;
  9852. here->next = NULL;
  9853. if (heredoclist == NULL)
  9854. heredoclist = here;
  9855. else {
  9856. for (p = heredoclist; p->next; p = p->next)
  9857. continue;
  9858. p->next = here;
  9859. }
  9860. } else if (n->type == NTOFD || n->type == NFROMFD) {
  9861. fixredir(n, wordtext, 0);
  9862. } else {
  9863. n->nfile.fname = makename();
  9864. }
  9865. }
  9866. static union node *
  9867. simplecmd(void)
  9868. {
  9869. union node *args, **app;
  9870. union node *n = NULL;
  9871. union node *vars, **vpp;
  9872. union node **rpp, *redir;
  9873. int savecheckkwd;
  9874. #if ENABLE_ASH_BASH_COMPAT
  9875. smallint double_brackets_flag = 0;
  9876. #endif
  9877. args = NULL;
  9878. app = &args;
  9879. vars = NULL;
  9880. vpp = &vars;
  9881. redir = NULL;
  9882. rpp = &redir;
  9883. savecheckkwd = CHKALIAS;
  9884. for (;;) {
  9885. int t;
  9886. checkkwd = savecheckkwd;
  9887. t = readtoken();
  9888. switch (t) {
  9889. #if ENABLE_ASH_BASH_COMPAT
  9890. case TAND: /* "&&" */
  9891. case TOR: /* "||" */
  9892. if (!double_brackets_flag) {
  9893. tokpushback = 1;
  9894. goto out;
  9895. }
  9896. wordtext = (char *) (t == TAND ? "-a" : "-o");
  9897. #endif
  9898. case TWORD:
  9899. n = stzalloc(sizeof(struct narg));
  9900. n->type = NARG;
  9901. /*n->narg.next = NULL; - stzalloc did it */
  9902. n->narg.text = wordtext;
  9903. #if ENABLE_ASH_BASH_COMPAT
  9904. if (strcmp("[[", wordtext) == 0)
  9905. double_brackets_flag = 1;
  9906. else if (strcmp("]]", wordtext) == 0)
  9907. double_brackets_flag = 0;
  9908. #endif
  9909. n->narg.backquote = backquotelist;
  9910. if (savecheckkwd && isassignment(wordtext)) {
  9911. *vpp = n;
  9912. vpp = &n->narg.next;
  9913. } else {
  9914. *app = n;
  9915. app = &n->narg.next;
  9916. savecheckkwd = 0;
  9917. }
  9918. break;
  9919. case TREDIR:
  9920. *rpp = n = redirnode;
  9921. rpp = &n->nfile.next;
  9922. parsefname(); /* read name of redirection file */
  9923. break;
  9924. case TLP:
  9925. if (args && app == &args->narg.next
  9926. && !vars && !redir
  9927. ) {
  9928. struct builtincmd *bcmd;
  9929. const char *name;
  9930. /* We have a function */
  9931. if (readtoken() != TRP)
  9932. raise_error_unexpected_syntax(TRP);
  9933. name = n->narg.text;
  9934. if (!goodname(name)
  9935. || ((bcmd = find_builtin(name)) && IS_BUILTIN_SPECIAL(bcmd))
  9936. ) {
  9937. raise_error_syntax("bad function name");
  9938. }
  9939. n->type = NDEFUN;
  9940. checkkwd = CHKNL | CHKKWD | CHKALIAS;
  9941. n->narg.next = parse_command();
  9942. return n;
  9943. }
  9944. /* fall through */
  9945. default:
  9946. tokpushback = 1;
  9947. goto out;
  9948. }
  9949. }
  9950. out:
  9951. *app = NULL;
  9952. *vpp = NULL;
  9953. *rpp = NULL;
  9954. n = stzalloc(sizeof(struct ncmd));
  9955. n->type = NCMD;
  9956. n->ncmd.args = args;
  9957. n->ncmd.assign = vars;
  9958. n->ncmd.redirect = redir;
  9959. return n;
  9960. }
  9961. static union node *
  9962. parse_command(void)
  9963. {
  9964. union node *n1, *n2;
  9965. union node *ap, **app;
  9966. union node *cp, **cpp;
  9967. union node *redir, **rpp;
  9968. union node **rpp2;
  9969. int t;
  9970. redir = NULL;
  9971. rpp2 = &redir;
  9972. switch (readtoken()) {
  9973. default:
  9974. raise_error_unexpected_syntax(-1);
  9975. /* NOTREACHED */
  9976. case TIF:
  9977. n1 = stzalloc(sizeof(struct nif));
  9978. n1->type = NIF;
  9979. n1->nif.test = list(0);
  9980. if (readtoken() != TTHEN)
  9981. raise_error_unexpected_syntax(TTHEN);
  9982. n1->nif.ifpart = list(0);
  9983. n2 = n1;
  9984. while (readtoken() == TELIF) {
  9985. n2->nif.elsepart = stzalloc(sizeof(struct nif));
  9986. n2 = n2->nif.elsepart;
  9987. n2->type = NIF;
  9988. n2->nif.test = list(0);
  9989. if (readtoken() != TTHEN)
  9990. raise_error_unexpected_syntax(TTHEN);
  9991. n2->nif.ifpart = list(0);
  9992. }
  9993. if (lasttoken == TELSE)
  9994. n2->nif.elsepart = list(0);
  9995. else {
  9996. n2->nif.elsepart = NULL;
  9997. tokpushback = 1;
  9998. }
  9999. t = TFI;
  10000. break;
  10001. case TWHILE:
  10002. case TUNTIL: {
  10003. int got;
  10004. n1 = stzalloc(sizeof(struct nbinary));
  10005. n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
  10006. n1->nbinary.ch1 = list(0);
  10007. got = readtoken();
  10008. if (got != TDO) {
  10009. TRACE(("expecting DO got '%s' %s\n", tokname_array[got] + 1,
  10010. got == TWORD ? wordtext : ""));
  10011. raise_error_unexpected_syntax(TDO);
  10012. }
  10013. n1->nbinary.ch2 = list(0);
  10014. t = TDONE;
  10015. break;
  10016. }
  10017. case TFOR:
  10018. if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
  10019. raise_error_syntax("bad for loop variable");
  10020. n1 = stzalloc(sizeof(struct nfor));
  10021. n1->type = NFOR;
  10022. n1->nfor.var = wordtext;
  10023. checkkwd = CHKKWD | CHKALIAS;
  10024. if (readtoken() == TIN) {
  10025. app = &ap;
  10026. while (readtoken() == TWORD) {
  10027. n2 = stzalloc(sizeof(struct narg));
  10028. n2->type = NARG;
  10029. /*n2->narg.next = NULL; - stzalloc did it */
  10030. n2->narg.text = wordtext;
  10031. n2->narg.backquote = backquotelist;
  10032. *app = n2;
  10033. app = &n2->narg.next;
  10034. }
  10035. *app = NULL;
  10036. n1->nfor.args = ap;
  10037. if (lasttoken != TNL && lasttoken != TSEMI)
  10038. raise_error_unexpected_syntax(-1);
  10039. } else {
  10040. n2 = stzalloc(sizeof(struct narg));
  10041. n2->type = NARG;
  10042. /*n2->narg.next = NULL; - stzalloc did it */
  10043. n2->narg.text = (char *)dolatstr;
  10044. /*n2->narg.backquote = NULL;*/
  10045. n1->nfor.args = n2;
  10046. /*
  10047. * Newline or semicolon here is optional (but note
  10048. * that the original Bourne shell only allowed NL).
  10049. */
  10050. if (lasttoken != TNL && lasttoken != TSEMI)
  10051. tokpushback = 1;
  10052. }
  10053. checkkwd = CHKNL | CHKKWD | CHKALIAS;
  10054. if (readtoken() != TDO)
  10055. raise_error_unexpected_syntax(TDO);
  10056. n1->nfor.body = list(0);
  10057. t = TDONE;
  10058. break;
  10059. case TCASE:
  10060. n1 = stzalloc(sizeof(struct ncase));
  10061. n1->type = NCASE;
  10062. if (readtoken() != TWORD)
  10063. raise_error_unexpected_syntax(TWORD);
  10064. n1->ncase.expr = n2 = stzalloc(sizeof(struct narg));
  10065. n2->type = NARG;
  10066. /*n2->narg.next = NULL; - stzalloc did it */
  10067. n2->narg.text = wordtext;
  10068. n2->narg.backquote = backquotelist;
  10069. do {
  10070. checkkwd = CHKKWD | CHKALIAS;
  10071. } while (readtoken() == TNL);
  10072. if (lasttoken != TIN)
  10073. raise_error_unexpected_syntax(TIN);
  10074. cpp = &n1->ncase.cases;
  10075. next_case:
  10076. checkkwd = CHKNL | CHKKWD;
  10077. t = readtoken();
  10078. while (t != TESAC) {
  10079. if (lasttoken == TLP)
  10080. readtoken();
  10081. *cpp = cp = stzalloc(sizeof(struct nclist));
  10082. cp->type = NCLIST;
  10083. app = &cp->nclist.pattern;
  10084. for (;;) {
  10085. *app = ap = stzalloc(sizeof(struct narg));
  10086. ap->type = NARG;
  10087. /*ap->narg.next = NULL; - stzalloc did it */
  10088. ap->narg.text = wordtext;
  10089. ap->narg.backquote = backquotelist;
  10090. if (readtoken() != TPIPE)
  10091. break;
  10092. app = &ap->narg.next;
  10093. readtoken();
  10094. }
  10095. //ap->narg.next = NULL;
  10096. if (lasttoken != TRP)
  10097. raise_error_unexpected_syntax(TRP);
  10098. cp->nclist.body = list(2);
  10099. cpp = &cp->nclist.next;
  10100. checkkwd = CHKNL | CHKKWD;
  10101. t = readtoken();
  10102. if (t != TESAC) {
  10103. if (t != TENDCASE)
  10104. raise_error_unexpected_syntax(TENDCASE);
  10105. goto next_case;
  10106. }
  10107. }
  10108. *cpp = NULL;
  10109. goto redir;
  10110. case TLP:
  10111. n1 = stzalloc(sizeof(struct nredir));
  10112. n1->type = NSUBSHELL;
  10113. n1->nredir.n = list(0);
  10114. /*n1->nredir.redirect = NULL; - stzalloc did it */
  10115. t = TRP;
  10116. break;
  10117. case TBEGIN:
  10118. n1 = list(0);
  10119. t = TEND;
  10120. break;
  10121. case TWORD:
  10122. case TREDIR:
  10123. tokpushback = 1;
  10124. return simplecmd();
  10125. }
  10126. if (readtoken() != t)
  10127. raise_error_unexpected_syntax(t);
  10128. redir:
  10129. /* Now check for redirection which may follow command */
  10130. checkkwd = CHKKWD | CHKALIAS;
  10131. rpp = rpp2;
  10132. while (readtoken() == TREDIR) {
  10133. *rpp = n2 = redirnode;
  10134. rpp = &n2->nfile.next;
  10135. parsefname();
  10136. }
  10137. tokpushback = 1;
  10138. *rpp = NULL;
  10139. if (redir) {
  10140. if (n1->type != NSUBSHELL) {
  10141. n2 = stzalloc(sizeof(struct nredir));
  10142. n2->type = NREDIR;
  10143. n2->nredir.n = n1;
  10144. n1 = n2;
  10145. }
  10146. n1->nredir.redirect = redir;
  10147. }
  10148. return n1;
  10149. }
  10150. #if ENABLE_ASH_BASH_COMPAT
  10151. static int decode_dollar_squote(void)
  10152. {
  10153. static const char C_escapes[] ALIGN1 = "nrbtfav""x\\01234567";
  10154. int c, cnt;
  10155. char *p;
  10156. char buf[4];
  10157. c = pgetc();
  10158. p = strchr(C_escapes, c);
  10159. if (p) {
  10160. buf[0] = c;
  10161. p = buf;
  10162. cnt = 3;
  10163. if ((unsigned char)(c - '0') <= 7) { /* \ooo */
  10164. do {
  10165. c = pgetc();
  10166. *++p = c;
  10167. } while ((unsigned char)(c - '0') <= 7 && --cnt);
  10168. pungetc();
  10169. } else if (c == 'x') { /* \xHH */
  10170. do {
  10171. c = pgetc();
  10172. *++p = c;
  10173. } while (isxdigit(c) && --cnt);
  10174. pungetc();
  10175. if (cnt == 3) { /* \x but next char is "bad" */
  10176. c = 'x';
  10177. goto unrecognized;
  10178. }
  10179. } else { /* simple seq like \\ or \t */
  10180. p++;
  10181. }
  10182. *p = '\0';
  10183. p = buf;
  10184. c = bb_process_escape_sequence((void*)&p);
  10185. } else { /* unrecognized "\z": print both chars unless ' or " */
  10186. if (c != '\'' && c != '"') {
  10187. unrecognized:
  10188. c |= 0x100; /* "please encode \, then me" */
  10189. }
  10190. }
  10191. return c;
  10192. }
  10193. #endif
  10194. /*
  10195. * If eofmark is NULL, read a word or a redirection symbol. If eofmark
  10196. * is not NULL, read a here document. In the latter case, eofmark is the
  10197. * word which marks the end of the document and striptabs is true if
  10198. * leading tabs should be stripped from the document. The argument c
  10199. * is the first character of the input token or document.
  10200. *
  10201. * Because C does not have internal subroutines, I have simulated them
  10202. * using goto's to implement the subroutine linkage. The following macros
  10203. * will run code that appears at the end of readtoken1.
  10204. */
  10205. #define CHECKEND() {goto checkend; checkend_return:;}
  10206. #define PARSEREDIR() {goto parseredir; parseredir_return:;}
  10207. #define PARSESUB() {goto parsesub; parsesub_return:;}
  10208. #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
  10209. #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
  10210. #define PARSEARITH() {goto parsearith; parsearith_return:;}
  10211. static int
  10212. readtoken1(int c, int syntax, char *eofmark, int striptabs)
  10213. {
  10214. /* NB: syntax parameter fits into smallint */
  10215. /* c parameter is an unsigned char or PEOF or PEOA */
  10216. char *out;
  10217. int len;
  10218. char line[EOFMARKLEN + 1];
  10219. struct nodelist *bqlist;
  10220. smallint quotef;
  10221. smallint dblquote;
  10222. smallint oldstyle;
  10223. smallint prevsyntax; /* syntax before arithmetic */
  10224. #if ENABLE_ASH_EXPAND_PRMT
  10225. smallint pssyntax; /* we are expanding a prompt string */
  10226. #endif
  10227. int varnest; /* levels of variables expansion */
  10228. int arinest; /* levels of arithmetic expansion */
  10229. int parenlevel; /* levels of parens in arithmetic */
  10230. int dqvarnest; /* levels of variables expansion within double quotes */
  10231. IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;)
  10232. #if __GNUC__
  10233. /* Avoid longjmp clobbering */
  10234. (void) &out;
  10235. (void) &quotef;
  10236. (void) &dblquote;
  10237. (void) &varnest;
  10238. (void) &arinest;
  10239. (void) &parenlevel;
  10240. (void) &dqvarnest;
  10241. (void) &oldstyle;
  10242. (void) &prevsyntax;
  10243. (void) &syntax;
  10244. #endif
  10245. startlinno = g_parsefile->linno;
  10246. bqlist = NULL;
  10247. quotef = 0;
  10248. prevsyntax = 0;
  10249. #if ENABLE_ASH_EXPAND_PRMT
  10250. pssyntax = (syntax == PSSYNTAX);
  10251. if (pssyntax)
  10252. syntax = DQSYNTAX;
  10253. #endif
  10254. dblquote = (syntax == DQSYNTAX);
  10255. varnest = 0;
  10256. arinest = 0;
  10257. parenlevel = 0;
  10258. dqvarnest = 0;
  10259. STARTSTACKSTR(out);
  10260. loop:
  10261. /* For each line, until end of word */
  10262. CHECKEND(); /* set c to PEOF if at end of here document */
  10263. for (;;) { /* until end of line or end of word */
  10264. CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
  10265. switch (SIT(c, syntax)) {
  10266. case CNL: /* '\n' */
  10267. if (syntax == BASESYNTAX)
  10268. goto endword; /* exit outer loop */
  10269. USTPUTC(c, out);
  10270. g_parsefile->linno++;
  10271. setprompt_if(doprompt, 2);
  10272. c = pgetc();
  10273. goto loop; /* continue outer loop */
  10274. case CWORD:
  10275. USTPUTC(c, out);
  10276. break;
  10277. case CCTL:
  10278. if (eofmark == NULL || dblquote)
  10279. USTPUTC(CTLESC, out);
  10280. #if ENABLE_ASH_BASH_COMPAT
  10281. if (c == '\\' && bash_dollar_squote) {
  10282. c = decode_dollar_squote();
  10283. if (c & 0x100) {
  10284. USTPUTC('\\', out);
  10285. c = (unsigned char)c;
  10286. }
  10287. }
  10288. #endif
  10289. USTPUTC(c, out);
  10290. break;
  10291. case CBACK: /* backslash */
  10292. c = pgetc_without_PEOA();
  10293. if (c == PEOF) {
  10294. USTPUTC(CTLESC, out);
  10295. USTPUTC('\\', out);
  10296. pungetc();
  10297. } else if (c == '\n') {
  10298. setprompt_if(doprompt, 2);
  10299. } else {
  10300. #if ENABLE_ASH_EXPAND_PRMT
  10301. if (c == '$' && pssyntax) {
  10302. USTPUTC(CTLESC, out);
  10303. USTPUTC('\\', out);
  10304. }
  10305. #endif
  10306. /* Backslash is retained if we are in "str" and next char isn't special */
  10307. if (dblquote
  10308. && c != '\\'
  10309. && c != '`'
  10310. && c != '$'
  10311. && (c != '"' || eofmark != NULL)
  10312. ) {
  10313. USTPUTC(CTLESC, out);
  10314. USTPUTC('\\', out);
  10315. }
  10316. if (SIT(c, SQSYNTAX) == CCTL)
  10317. USTPUTC(CTLESC, out);
  10318. USTPUTC(c, out);
  10319. quotef = 1;
  10320. }
  10321. break;
  10322. case CSQUOTE:
  10323. syntax = SQSYNTAX;
  10324. quotemark:
  10325. if (eofmark == NULL) {
  10326. USTPUTC(CTLQUOTEMARK, out);
  10327. }
  10328. break;
  10329. case CDQUOTE:
  10330. syntax = DQSYNTAX;
  10331. dblquote = 1;
  10332. goto quotemark;
  10333. case CENDQUOTE:
  10334. IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;)
  10335. if (eofmark != NULL && arinest == 0
  10336. && varnest == 0
  10337. ) {
  10338. USTPUTC(c, out);
  10339. } else {
  10340. if (dqvarnest == 0) {
  10341. syntax = BASESYNTAX;
  10342. dblquote = 0;
  10343. }
  10344. quotef = 1;
  10345. goto quotemark;
  10346. }
  10347. break;
  10348. case CVAR: /* '$' */
  10349. PARSESUB(); /* parse substitution */
  10350. break;
  10351. case CENDVAR: /* '}' */
  10352. if (varnest > 0) {
  10353. varnest--;
  10354. if (dqvarnest > 0) {
  10355. dqvarnest--;
  10356. }
  10357. c = CTLENDVAR;
  10358. }
  10359. USTPUTC(c, out);
  10360. break;
  10361. #if ENABLE_SH_MATH_SUPPORT
  10362. case CLP: /* '(' in arithmetic */
  10363. parenlevel++;
  10364. USTPUTC(c, out);
  10365. break;
  10366. case CRP: /* ')' in arithmetic */
  10367. if (parenlevel > 0) {
  10368. parenlevel--;
  10369. } else {
  10370. if (pgetc() == ')') {
  10371. if (--arinest == 0) {
  10372. syntax = prevsyntax;
  10373. dblquote = (syntax == DQSYNTAX);
  10374. c = CTLENDARI;
  10375. }
  10376. } else {
  10377. /*
  10378. * unbalanced parens
  10379. * (don't 2nd guess - no error)
  10380. */
  10381. pungetc();
  10382. }
  10383. }
  10384. USTPUTC(c, out);
  10385. break;
  10386. #endif
  10387. case CBQUOTE: /* '`' */
  10388. PARSEBACKQOLD();
  10389. break;
  10390. case CENDFILE:
  10391. goto endword; /* exit outer loop */
  10392. case CIGN:
  10393. break;
  10394. default:
  10395. if (varnest == 0) {
  10396. #if ENABLE_ASH_BASH_COMPAT
  10397. if (c == '&') {
  10398. if (pgetc() == '>')
  10399. c = 0x100 + '>'; /* flag &> */
  10400. pungetc();
  10401. }
  10402. #endif
  10403. goto endword; /* exit outer loop */
  10404. }
  10405. IF_ASH_ALIAS(if (c != PEOA))
  10406. USTPUTC(c, out);
  10407. }
  10408. c = pgetc_fast();
  10409. } /* for (;;) */
  10410. endword:
  10411. #if ENABLE_SH_MATH_SUPPORT
  10412. if (syntax == ARISYNTAX)
  10413. raise_error_syntax("missing '))'");
  10414. #endif
  10415. if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
  10416. raise_error_syntax("unterminated quoted string");
  10417. if (varnest != 0) {
  10418. startlinno = g_parsefile->linno;
  10419. /* { */
  10420. raise_error_syntax("missing '}'");
  10421. }
  10422. USTPUTC('\0', out);
  10423. len = out - (char *)stackblock();
  10424. out = stackblock();
  10425. if (eofmark == NULL) {
  10426. if ((c == '>' || c == '<' IF_ASH_BASH_COMPAT( || c == 0x100 + '>'))
  10427. && quotef == 0
  10428. ) {
  10429. if (isdigit_str9(out)) {
  10430. PARSEREDIR(); /* passed as params: out, c */
  10431. lasttoken = TREDIR;
  10432. return lasttoken;
  10433. }
  10434. /* else: non-number X seen, interpret it
  10435. * as "NNNX>file" = "NNNX >file" */
  10436. }
  10437. pungetc();
  10438. }
  10439. quoteflag = quotef;
  10440. backquotelist = bqlist;
  10441. grabstackblock(len);
  10442. wordtext = out;
  10443. lasttoken = TWORD;
  10444. return lasttoken;
  10445. /* end of readtoken routine */
  10446. /*
  10447. * Check to see whether we are at the end of the here document. When this
  10448. * is called, c is set to the first character of the next input line. If
  10449. * we are at the end of the here document, this routine sets the c to PEOF.
  10450. */
  10451. checkend: {
  10452. if (eofmark) {
  10453. #if ENABLE_ASH_ALIAS
  10454. if (c == PEOA)
  10455. c = pgetc_without_PEOA();
  10456. #endif
  10457. if (striptabs) {
  10458. while (c == '\t') {
  10459. c = pgetc_without_PEOA();
  10460. }
  10461. }
  10462. if (c == *eofmark) {
  10463. if (pfgets(line, sizeof(line)) != NULL) {
  10464. char *p, *q;
  10465. p = line;
  10466. for (q = eofmark + 1; *q && *p == *q; p++, q++)
  10467. continue;
  10468. if (*p == '\n' && *q == '\0') {
  10469. c = PEOF;
  10470. g_parsefile->linno++;
  10471. needprompt = doprompt;
  10472. } else {
  10473. pushstring(line, NULL);
  10474. }
  10475. }
  10476. }
  10477. }
  10478. goto checkend_return;
  10479. }
  10480. /*
  10481. * Parse a redirection operator. The variable "out" points to a string
  10482. * specifying the fd to be redirected. The variable "c" contains the
  10483. * first character of the redirection operator.
  10484. */
  10485. parseredir: {
  10486. /* out is already checked to be a valid number or "" */
  10487. int fd = (*out == '\0' ? -1 : atoi(out));
  10488. union node *np;
  10489. np = stzalloc(sizeof(struct nfile));
  10490. if (c == '>') {
  10491. np->nfile.fd = 1;
  10492. c = pgetc();
  10493. if (c == '>')
  10494. np->type = NAPPEND;
  10495. else if (c == '|')
  10496. np->type = NCLOBBER;
  10497. else if (c == '&')
  10498. np->type = NTOFD;
  10499. /* it also can be NTO2 (>&file), but we can't figure it out yet */
  10500. else {
  10501. np->type = NTO;
  10502. pungetc();
  10503. }
  10504. }
  10505. #if ENABLE_ASH_BASH_COMPAT
  10506. else if (c == 0x100 + '>') { /* this flags &> redirection */
  10507. np->nfile.fd = 1;
  10508. pgetc(); /* this is '>', no need to check */
  10509. np->type = NTO2;
  10510. }
  10511. #endif
  10512. else { /* c == '<' */
  10513. /*np->nfile.fd = 0; - stzalloc did it */
  10514. c = pgetc();
  10515. switch (c) {
  10516. case '<':
  10517. if (sizeof(struct nfile) != sizeof(struct nhere)) {
  10518. np = stzalloc(sizeof(struct nhere));
  10519. /*np->nfile.fd = 0; - stzalloc did it */
  10520. }
  10521. np->type = NHERE;
  10522. heredoc = stzalloc(sizeof(struct heredoc));
  10523. heredoc->here = np;
  10524. c = pgetc();
  10525. if (c == '-') {
  10526. heredoc->striptabs = 1;
  10527. } else {
  10528. /*heredoc->striptabs = 0; - stzalloc did it */
  10529. pungetc();
  10530. }
  10531. break;
  10532. case '&':
  10533. np->type = NFROMFD;
  10534. break;
  10535. case '>':
  10536. np->type = NFROMTO;
  10537. break;
  10538. default:
  10539. np->type = NFROM;
  10540. pungetc();
  10541. break;
  10542. }
  10543. }
  10544. if (fd >= 0)
  10545. np->nfile.fd = fd;
  10546. redirnode = np;
  10547. goto parseredir_return;
  10548. }
  10549. /*
  10550. * Parse a substitution. At this point, we have read the dollar sign
  10551. * and nothing else.
  10552. */
  10553. /* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
  10554. * (assuming ascii char codes, as the original implementation did) */
  10555. #define is_special(c) \
  10556. (((unsigned)(c) - 33 < 32) \
  10557. && ((0xc1ff920dU >> ((unsigned)(c) - 33)) & 1))
  10558. parsesub: {
  10559. unsigned char subtype;
  10560. int typeloc;
  10561. int flags;
  10562. c = pgetc();
  10563. if (c > 255 /* PEOA or PEOF */
  10564. || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
  10565. ) {
  10566. #if ENABLE_ASH_BASH_COMPAT
  10567. if (c == '\'')
  10568. bash_dollar_squote = 1;
  10569. else
  10570. #endif
  10571. USTPUTC('$', out);
  10572. pungetc();
  10573. } else if (c == '(') {
  10574. /* $(command) or $((arith)) */
  10575. if (pgetc() == '(') {
  10576. #if ENABLE_SH_MATH_SUPPORT
  10577. PARSEARITH();
  10578. #else
  10579. raise_error_syntax("you disabled math support for $((arith)) syntax");
  10580. #endif
  10581. } else {
  10582. pungetc();
  10583. PARSEBACKQNEW();
  10584. }
  10585. } else {
  10586. /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
  10587. USTPUTC(CTLVAR, out);
  10588. typeloc = out - (char *)stackblock();
  10589. USTPUTC(VSNORMAL, out);
  10590. subtype = VSNORMAL;
  10591. if (c == '{') {
  10592. c = pgetc();
  10593. if (c == '#') {
  10594. c = pgetc();
  10595. if (c == '}')
  10596. c = '#'; /* ${#} - same as $# */
  10597. else
  10598. subtype = VSLENGTH; /* ${#VAR} */
  10599. } else {
  10600. subtype = 0;
  10601. }
  10602. }
  10603. if (c <= 255 /* not PEOA or PEOF */ && is_name(c)) {
  10604. /* $[{[#]]NAME[}] */
  10605. do {
  10606. STPUTC(c, out);
  10607. c = pgetc();
  10608. } while (c <= 255 /* not PEOA or PEOF */ && is_in_name(c));
  10609. } else if (isdigit(c)) {
  10610. /* $[{[#]]NUM[}] */
  10611. do {
  10612. STPUTC(c, out);
  10613. c = pgetc();
  10614. } while (isdigit(c));
  10615. } else if (is_special(c)) {
  10616. /* $[{[#]]<specialchar>[}] */
  10617. USTPUTC(c, out);
  10618. c = pgetc();
  10619. } else {
  10620. badsub:
  10621. raise_error_syntax("bad substitution");
  10622. }
  10623. if (c != '}' && subtype == VSLENGTH) {
  10624. /* ${#VAR didn't end with } */
  10625. goto badsub;
  10626. }
  10627. STPUTC('=', out);
  10628. flags = 0;
  10629. if (subtype == 0) {
  10630. /* ${VAR...} but not $VAR or ${#VAR} */
  10631. /* c == first char after VAR */
  10632. switch (c) {
  10633. case ':':
  10634. c = pgetc();
  10635. #if ENABLE_ASH_BASH_COMPAT
  10636. if (c == ':' || c == '$' || isdigit(c)) {
  10637. //TODO: support more general format ${v:EXPR:EXPR},
  10638. // where EXPR follows $(()) rules
  10639. subtype = VSSUBSTR;
  10640. pungetc();
  10641. break; /* "goto do_pungetc" is bigger (!) */
  10642. }
  10643. #endif
  10644. flags = VSNUL;
  10645. /*FALLTHROUGH*/
  10646. default: {
  10647. static const char types[] ALIGN1 = "}-+?=";
  10648. const char *p = strchr(types, c);
  10649. if (p == NULL)
  10650. goto badsub;
  10651. subtype = p - types + VSNORMAL;
  10652. break;
  10653. }
  10654. case '%':
  10655. case '#': {
  10656. int cc = c;
  10657. subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
  10658. c = pgetc();
  10659. if (c != cc)
  10660. goto do_pungetc;
  10661. subtype++;
  10662. break;
  10663. }
  10664. #if ENABLE_ASH_BASH_COMPAT
  10665. case '/':
  10666. /* ${v/[/]pattern/repl} */
  10667. //TODO: encode pattern and repl separately.
  10668. // Currently ${v/$var_with_slash/repl} is horribly broken
  10669. subtype = VSREPLACE;
  10670. c = pgetc();
  10671. if (c != '/')
  10672. goto do_pungetc;
  10673. subtype++; /* VSREPLACEALL */
  10674. break;
  10675. #endif
  10676. }
  10677. } else {
  10678. do_pungetc:
  10679. pungetc();
  10680. }
  10681. if (dblquote || arinest)
  10682. flags |= VSQUOTE;
  10683. ((unsigned char *)stackblock())[typeloc] = subtype | flags;
  10684. if (subtype != VSNORMAL) {
  10685. varnest++;
  10686. if (dblquote || arinest) {
  10687. dqvarnest++;
  10688. }
  10689. }
  10690. }
  10691. goto parsesub_return;
  10692. }
  10693. /*
  10694. * Called to parse command substitutions. Newstyle is set if the command
  10695. * is enclosed inside $(...); nlpp is a pointer to the head of the linked
  10696. * list of commands (passed by reference), and savelen is the number of
  10697. * characters on the top of the stack which must be preserved.
  10698. */
  10699. parsebackq: {
  10700. struct nodelist **nlpp;
  10701. smallint savepbq;
  10702. union node *n;
  10703. char *volatile str;
  10704. struct jmploc jmploc;
  10705. struct jmploc *volatile savehandler;
  10706. size_t savelen;
  10707. smallint saveprompt = 0;
  10708. #ifdef __GNUC__
  10709. (void) &saveprompt;
  10710. #endif
  10711. savepbq = parsebackquote;
  10712. if (setjmp(jmploc.loc)) {
  10713. free(str);
  10714. parsebackquote = 0;
  10715. exception_handler = savehandler;
  10716. longjmp(exception_handler->loc, 1);
  10717. }
  10718. INT_OFF;
  10719. str = NULL;
  10720. savelen = out - (char *)stackblock();
  10721. if (savelen > 0) {
  10722. str = ckmalloc(savelen);
  10723. memcpy(str, stackblock(), savelen);
  10724. }
  10725. savehandler = exception_handler;
  10726. exception_handler = &jmploc;
  10727. INT_ON;
  10728. if (oldstyle) {
  10729. /* We must read until the closing backquote, giving special
  10730. * treatment to some slashes, and then push the string and
  10731. * reread it as input, interpreting it normally.
  10732. */
  10733. char *pout;
  10734. size_t psavelen;
  10735. char *pstr;
  10736. STARTSTACKSTR(pout);
  10737. for (;;) {
  10738. int pc;
  10739. setprompt_if(needprompt, 2);
  10740. pc = pgetc();
  10741. switch (pc) {
  10742. case '`':
  10743. goto done;
  10744. case '\\':
  10745. pc = pgetc();
  10746. if (pc == '\n') {
  10747. g_parsefile->linno++;
  10748. setprompt_if(doprompt, 2);
  10749. /*
  10750. * If eating a newline, avoid putting
  10751. * the newline into the new character
  10752. * stream (via the STPUTC after the
  10753. * switch).
  10754. */
  10755. continue;
  10756. }
  10757. if (pc != '\\' && pc != '`' && pc != '$'
  10758. && (!dblquote || pc != '"')
  10759. ) {
  10760. STPUTC('\\', pout);
  10761. }
  10762. if (pc <= 255 /* not PEOA or PEOF */) {
  10763. break;
  10764. }
  10765. /* fall through */
  10766. case PEOF:
  10767. IF_ASH_ALIAS(case PEOA:)
  10768. startlinno = g_parsefile->linno;
  10769. raise_error_syntax("EOF in backquote substitution");
  10770. case '\n':
  10771. g_parsefile->linno++;
  10772. needprompt = doprompt;
  10773. break;
  10774. default:
  10775. break;
  10776. }
  10777. STPUTC(pc, pout);
  10778. }
  10779. done:
  10780. STPUTC('\0', pout);
  10781. psavelen = pout - (char *)stackblock();
  10782. if (psavelen > 0) {
  10783. pstr = grabstackstr(pout);
  10784. setinputstring(pstr);
  10785. }
  10786. }
  10787. nlpp = &bqlist;
  10788. while (*nlpp)
  10789. nlpp = &(*nlpp)->next;
  10790. *nlpp = stzalloc(sizeof(**nlpp));
  10791. /* (*nlpp)->next = NULL; - stzalloc did it */
  10792. parsebackquote = oldstyle;
  10793. if (oldstyle) {
  10794. saveprompt = doprompt;
  10795. doprompt = 0;
  10796. }
  10797. n = list(2);
  10798. if (oldstyle)
  10799. doprompt = saveprompt;
  10800. else if (readtoken() != TRP)
  10801. raise_error_unexpected_syntax(TRP);
  10802. (*nlpp)->n = n;
  10803. if (oldstyle) {
  10804. /*
  10805. * Start reading from old file again, ignoring any pushed back
  10806. * tokens left from the backquote parsing
  10807. */
  10808. popfile();
  10809. tokpushback = 0;
  10810. }
  10811. while (stackblocksize() <= savelen)
  10812. growstackblock();
  10813. STARTSTACKSTR(out);
  10814. if (str) {
  10815. memcpy(out, str, savelen);
  10816. STADJUST(savelen, out);
  10817. INT_OFF;
  10818. free(str);
  10819. str = NULL;
  10820. INT_ON;
  10821. }
  10822. parsebackquote = savepbq;
  10823. exception_handler = savehandler;
  10824. if (arinest || dblquote)
  10825. USTPUTC(CTLBACKQ | CTLQUOTE, out);
  10826. else
  10827. USTPUTC(CTLBACKQ, out);
  10828. if (oldstyle)
  10829. goto parsebackq_oldreturn;
  10830. goto parsebackq_newreturn;
  10831. }
  10832. #if ENABLE_SH_MATH_SUPPORT
  10833. /*
  10834. * Parse an arithmetic expansion (indicate start of one and set state)
  10835. */
  10836. parsearith: {
  10837. if (++arinest == 1) {
  10838. prevsyntax = syntax;
  10839. syntax = ARISYNTAX;
  10840. USTPUTC(CTLARI, out);
  10841. if (dblquote)
  10842. USTPUTC('"', out);
  10843. else
  10844. USTPUTC(' ', out);
  10845. } else {
  10846. /*
  10847. * we collapse embedded arithmetic expansion to
  10848. * parenthesis, which should be equivalent
  10849. */
  10850. USTPUTC('(', out);
  10851. }
  10852. goto parsearith_return;
  10853. }
  10854. #endif
  10855. } /* end of readtoken */
  10856. /*
  10857. * Read the next input token.
  10858. * If the token is a word, we set backquotelist to the list of cmds in
  10859. * backquotes. We set quoteflag to true if any part of the word was
  10860. * quoted.
  10861. * If the token is TREDIR, then we set redirnode to a structure containing
  10862. * the redirection.
  10863. * In all cases, the variable startlinno is set to the number of the line
  10864. * on which the token starts.
  10865. *
  10866. * [Change comment: here documents and internal procedures]
  10867. * [Readtoken shouldn't have any arguments. Perhaps we should make the
  10868. * word parsing code into a separate routine. In this case, readtoken
  10869. * doesn't need to have any internal procedures, but parseword does.
  10870. * We could also make parseoperator in essence the main routine, and
  10871. * have parseword (readtoken1?) handle both words and redirection.]
  10872. */
  10873. #define NEW_xxreadtoken
  10874. #ifdef NEW_xxreadtoken
  10875. /* singles must be first! */
  10876. static const char xxreadtoken_chars[7] ALIGN1 = {
  10877. '\n', '(', ')', /* singles */
  10878. '&', '|', ';', /* doubles */
  10879. 0
  10880. };
  10881. #define xxreadtoken_singles 3
  10882. #define xxreadtoken_doubles 3
  10883. static const char xxreadtoken_tokens[] ALIGN1 = {
  10884. TNL, TLP, TRP, /* only single occurrence allowed */
  10885. TBACKGND, TPIPE, TSEMI, /* if single occurrence */
  10886. TEOF, /* corresponds to trailing nul */
  10887. TAND, TOR, TENDCASE /* if double occurrence */
  10888. };
  10889. static int
  10890. xxreadtoken(void)
  10891. {
  10892. int c;
  10893. if (tokpushback) {
  10894. tokpushback = 0;
  10895. return lasttoken;
  10896. }
  10897. setprompt_if(needprompt, 2);
  10898. startlinno = g_parsefile->linno;
  10899. for (;;) { /* until token or start of word found */
  10900. c = pgetc_fast();
  10901. if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
  10902. continue;
  10903. if (c == '#') {
  10904. while ((c = pgetc()) != '\n' && c != PEOF)
  10905. continue;
  10906. pungetc();
  10907. } else if (c == '\\') {
  10908. if (pgetc() != '\n') {
  10909. pungetc();
  10910. break; /* return readtoken1(...) */
  10911. }
  10912. startlinno = ++g_parsefile->linno;
  10913. setprompt_if(doprompt, 2);
  10914. } else {
  10915. const char *p;
  10916. p = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
  10917. if (c != PEOF) {
  10918. if (c == '\n') {
  10919. g_parsefile->linno++;
  10920. needprompt = doprompt;
  10921. }
  10922. p = strchr(xxreadtoken_chars, c);
  10923. if (p == NULL)
  10924. break; /* return readtoken1(...) */
  10925. if ((int)(p - xxreadtoken_chars) >= xxreadtoken_singles) {
  10926. int cc = pgetc();
  10927. if (cc == c) { /* double occurrence? */
  10928. p += xxreadtoken_doubles + 1;
  10929. } else {
  10930. pungetc();
  10931. #if ENABLE_ASH_BASH_COMPAT
  10932. if (c == '&' && cc == '>') /* &> */
  10933. break; /* return readtoken1(...) */
  10934. #endif
  10935. }
  10936. }
  10937. }
  10938. lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
  10939. return lasttoken;
  10940. }
  10941. } /* for (;;) */
  10942. return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
  10943. }
  10944. #else /* old xxreadtoken */
  10945. #define RETURN(token) return lasttoken = token
  10946. static int
  10947. xxreadtoken(void)
  10948. {
  10949. int c;
  10950. if (tokpushback) {
  10951. tokpushback = 0;
  10952. return lasttoken;
  10953. }
  10954. setprompt_if(needprompt, 2);
  10955. startlinno = g_parsefile->linno;
  10956. for (;;) { /* until token or start of word found */
  10957. c = pgetc_fast();
  10958. switch (c) {
  10959. case ' ': case '\t':
  10960. IF_ASH_ALIAS(case PEOA:)
  10961. continue;
  10962. case '#':
  10963. while ((c = pgetc()) != '\n' && c != PEOF)
  10964. continue;
  10965. pungetc();
  10966. continue;
  10967. case '\\':
  10968. if (pgetc() == '\n') {
  10969. startlinno = ++g_parsefile->linno;
  10970. setprompt_if(doprompt, 2);
  10971. continue;
  10972. }
  10973. pungetc();
  10974. goto breakloop;
  10975. case '\n':
  10976. g_parsefile->linno++;
  10977. needprompt = doprompt;
  10978. RETURN(TNL);
  10979. case PEOF:
  10980. RETURN(TEOF);
  10981. case '&':
  10982. if (pgetc() == '&')
  10983. RETURN(TAND);
  10984. pungetc();
  10985. RETURN(TBACKGND);
  10986. case '|':
  10987. if (pgetc() == '|')
  10988. RETURN(TOR);
  10989. pungetc();
  10990. RETURN(TPIPE);
  10991. case ';':
  10992. if (pgetc() == ';')
  10993. RETURN(TENDCASE);
  10994. pungetc();
  10995. RETURN(TSEMI);
  10996. case '(':
  10997. RETURN(TLP);
  10998. case ')':
  10999. RETURN(TRP);
  11000. default:
  11001. goto breakloop;
  11002. }
  11003. }
  11004. breakloop:
  11005. return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
  11006. #undef RETURN
  11007. }
  11008. #endif /* old xxreadtoken */
  11009. static int
  11010. readtoken(void)
  11011. {
  11012. int t;
  11013. #if DEBUG
  11014. smallint alreadyseen = tokpushback;
  11015. #endif
  11016. #if ENABLE_ASH_ALIAS
  11017. top:
  11018. #endif
  11019. t = xxreadtoken();
  11020. /*
  11021. * eat newlines
  11022. */
  11023. if (checkkwd & CHKNL) {
  11024. while (t == TNL) {
  11025. parseheredoc();
  11026. t = xxreadtoken();
  11027. }
  11028. }
  11029. if (t != TWORD || quoteflag) {
  11030. goto out;
  11031. }
  11032. /*
  11033. * check for keywords
  11034. */
  11035. if (checkkwd & CHKKWD) {
  11036. const char *const *pp;
  11037. pp = findkwd(wordtext);
  11038. if (pp) {
  11039. lasttoken = t = pp - tokname_array;
  11040. TRACE(("keyword '%s' recognized\n", tokname_array[t] + 1));
  11041. goto out;
  11042. }
  11043. }
  11044. if (checkkwd & CHKALIAS) {
  11045. #if ENABLE_ASH_ALIAS
  11046. struct alias *ap;
  11047. ap = lookupalias(wordtext, 1);
  11048. if (ap != NULL) {
  11049. if (*ap->val) {
  11050. pushstring(ap->val, ap);
  11051. }
  11052. goto top;
  11053. }
  11054. #endif
  11055. }
  11056. out:
  11057. checkkwd = 0;
  11058. #if DEBUG
  11059. if (!alreadyseen)
  11060. TRACE(("token '%s' %s\n", tokname_array[t] + 1, t == TWORD ? wordtext : ""));
  11061. else
  11062. TRACE(("reread token '%s' %s\n", tokname_array[t] + 1, t == TWORD ? wordtext : ""));
  11063. #endif
  11064. return t;
  11065. }
  11066. static char
  11067. peektoken(void)
  11068. {
  11069. int t;
  11070. t = readtoken();
  11071. tokpushback = 1;
  11072. return tokname_array[t][0];
  11073. }
  11074. /*
  11075. * Read and parse a command. Returns NODE_EOF on end of file.
  11076. * (NULL is a valid parse tree indicating a blank line.)
  11077. */
  11078. static union node *
  11079. parsecmd(int interact)
  11080. {
  11081. int t;
  11082. tokpushback = 0;
  11083. doprompt = interact;
  11084. setprompt_if(doprompt, doprompt);
  11085. needprompt = 0;
  11086. t = readtoken();
  11087. if (t == TEOF)
  11088. return NODE_EOF;
  11089. if (t == TNL)
  11090. return NULL;
  11091. tokpushback = 1;
  11092. return list(1);
  11093. }
  11094. /*
  11095. * Input any here documents.
  11096. */
  11097. static void
  11098. parseheredoc(void)
  11099. {
  11100. struct heredoc *here;
  11101. union node *n;
  11102. here = heredoclist;
  11103. heredoclist = NULL;
  11104. while (here) {
  11105. setprompt_if(needprompt, 2);
  11106. readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
  11107. here->eofmark, here->striptabs);
  11108. n = stzalloc(sizeof(struct narg));
  11109. n->narg.type = NARG;
  11110. /*n->narg.next = NULL; - stzalloc did it */
  11111. n->narg.text = wordtext;
  11112. n->narg.backquote = backquotelist;
  11113. here->here->nhere.doc = n;
  11114. here = here->next;
  11115. }
  11116. }
  11117. /*
  11118. * called by editline -- any expansions to the prompt should be added here.
  11119. */
  11120. #if ENABLE_ASH_EXPAND_PRMT
  11121. static const char *
  11122. expandstr(const char *ps)
  11123. {
  11124. union node n;
  11125. /* XXX Fix (char *) cast. It _is_ a bug. ps is variable's value,
  11126. * and token processing _can_ alter it (delete NULs etc). */
  11127. setinputstring((char *)ps);
  11128. readtoken1(pgetc(), PSSYNTAX, nullstr, 0);
  11129. popfile();
  11130. n.narg.type = NARG;
  11131. n.narg.next = NULL;
  11132. n.narg.text = wordtext;
  11133. n.narg.backquote = backquotelist;
  11134. expandarg(&n, NULL, 0);
  11135. return stackblock();
  11136. }
  11137. #endif
  11138. /*
  11139. * Execute a command or commands contained in a string.
  11140. */
  11141. static int
  11142. evalstring(char *s, int mask)
  11143. {
  11144. union node *n;
  11145. struct stackmark smark;
  11146. int skip;
  11147. setinputstring(s);
  11148. setstackmark(&smark);
  11149. skip = 0;
  11150. while ((n = parsecmd(0)) != NODE_EOF) {
  11151. evaltree(n, 0);
  11152. popstackmark(&smark);
  11153. skip = evalskip;
  11154. if (skip)
  11155. break;
  11156. }
  11157. popfile();
  11158. skip &= mask;
  11159. evalskip = skip;
  11160. return skip;
  11161. }
  11162. /*
  11163. * The eval command.
  11164. */
  11165. static int FAST_FUNC
  11166. evalcmd(int argc UNUSED_PARAM, char **argv)
  11167. {
  11168. char *p;
  11169. char *concat;
  11170. if (argv[1]) {
  11171. p = argv[1];
  11172. argv += 2;
  11173. if (argv[0]) {
  11174. STARTSTACKSTR(concat);
  11175. for (;;) {
  11176. concat = stack_putstr(p, concat);
  11177. p = *argv++;
  11178. if (p == NULL)
  11179. break;
  11180. STPUTC(' ', concat);
  11181. }
  11182. STPUTC('\0', concat);
  11183. p = grabstackstr(concat);
  11184. }
  11185. evalstring(p, ~SKIPEVAL);
  11186. }
  11187. return exitstatus;
  11188. }
  11189. /*
  11190. * Read and execute commands.
  11191. * "Top" is nonzero for the top level command loop;
  11192. * it turns on prompting if the shell is interactive.
  11193. */
  11194. static int
  11195. cmdloop(int top)
  11196. {
  11197. union node *n;
  11198. struct stackmark smark;
  11199. int inter;
  11200. int numeof = 0;
  11201. TRACE(("cmdloop(%d) called\n", top));
  11202. for (;;) {
  11203. int skip;
  11204. setstackmark(&smark);
  11205. #if JOBS
  11206. if (doing_jobctl)
  11207. showjobs(stderr, SHOW_CHANGED);
  11208. #endif
  11209. inter = 0;
  11210. if (iflag && top) {
  11211. inter++;
  11212. chkmail();
  11213. }
  11214. n = parsecmd(inter);
  11215. #if DEBUG
  11216. if (DEBUG > 2 && debug && (n != NODE_EOF))
  11217. showtree(n);
  11218. #endif
  11219. if (n == NODE_EOF) {
  11220. if (!top || numeof >= 50)
  11221. break;
  11222. if (!stoppedjobs()) {
  11223. if (!Iflag)
  11224. break;
  11225. out2str("\nUse \"exit\" to leave shell.\n");
  11226. }
  11227. numeof++;
  11228. } else if (nflag == 0) {
  11229. /* job_warning can only be 2,1,0. Here 2->1, 1/0->0 */
  11230. job_warning >>= 1;
  11231. numeof = 0;
  11232. evaltree(n, 0);
  11233. }
  11234. popstackmark(&smark);
  11235. skip = evalskip;
  11236. if (skip) {
  11237. evalskip = 0;
  11238. return skip & SKIPEVAL;
  11239. }
  11240. }
  11241. return 0;
  11242. }
  11243. /*
  11244. * Take commands from a file. To be compatible we should do a path
  11245. * search for the file, which is necessary to find sub-commands.
  11246. */
  11247. static char *
  11248. find_dot_file(char *name)
  11249. {
  11250. char *fullname;
  11251. const char *path = pathval();
  11252. struct stat statb;
  11253. /* don't try this for absolute or relative paths */
  11254. if (strchr(name, '/'))
  11255. return name;
  11256. /* IIRC standards do not say whether . is to be searched.
  11257. * And it is even smaller this way, making it unconditional for now:
  11258. */
  11259. if (1) { /* ENABLE_ASH_BASH_COMPAT */
  11260. fullname = name;
  11261. goto try_cur_dir;
  11262. }
  11263. while ((fullname = path_advance(&path, name)) != NULL) {
  11264. try_cur_dir:
  11265. if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
  11266. /*
  11267. * Don't bother freeing here, since it will
  11268. * be freed by the caller.
  11269. */
  11270. return fullname;
  11271. }
  11272. if (fullname != name)
  11273. stunalloc(fullname);
  11274. }
  11275. /* not found in the PATH */
  11276. ash_msg_and_raise_error("%s: not found", name);
  11277. /* NOTREACHED */
  11278. }
  11279. static int FAST_FUNC
  11280. dotcmd(int argc, char **argv)
  11281. {
  11282. char *fullname;
  11283. struct strlist *sp;
  11284. volatile struct shparam saveparam;
  11285. for (sp = cmdenviron; sp; sp = sp->next)
  11286. setvareq(ckstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
  11287. if (!argv[1]) {
  11288. /* bash says: "bash: .: filename argument required" */
  11289. return 2; /* bash compat */
  11290. }
  11291. /* "false; . empty_file; echo $?" should print 0, not 1: */
  11292. exitstatus = 0;
  11293. /* This aborts if file isn't found, which is POSIXly correct.
  11294. * bash returns exitcode 1 instead.
  11295. */
  11296. fullname = find_dot_file(argv[1]);
  11297. argv += 2;
  11298. argc -= 2;
  11299. if (argc) { /* argc > 0, argv[0] != NULL */
  11300. saveparam = shellparam;
  11301. shellparam.malloced = 0;
  11302. shellparam.nparam = argc;
  11303. shellparam.p = argv;
  11304. };
  11305. /* This aborts if file can't be opened, which is POSIXly correct.
  11306. * bash returns exitcode 1 instead.
  11307. */
  11308. setinputfile(fullname, INPUT_PUSH_FILE);
  11309. commandname = fullname;
  11310. cmdloop(0);
  11311. popfile();
  11312. if (argc) {
  11313. freeparam(&shellparam);
  11314. shellparam = saveparam;
  11315. };
  11316. return exitstatus;
  11317. }
  11318. static int FAST_FUNC
  11319. exitcmd(int argc UNUSED_PARAM, char **argv)
  11320. {
  11321. if (stoppedjobs())
  11322. return 0;
  11323. if (argv[1])
  11324. exitstatus = number(argv[1]);
  11325. raise_exception(EXEXIT);
  11326. /* NOTREACHED */
  11327. }
  11328. /*
  11329. * Read a file containing shell functions.
  11330. */
  11331. static void
  11332. readcmdfile(char *name)
  11333. {
  11334. setinputfile(name, INPUT_PUSH_FILE);
  11335. cmdloop(0);
  11336. popfile();
  11337. }
  11338. /* ============ find_command inplementation */
  11339. /*
  11340. * Resolve a command name. If you change this routine, you may have to
  11341. * change the shellexec routine as well.
  11342. */
  11343. static void
  11344. find_command(char *name, struct cmdentry *entry, int act, const char *path)
  11345. {
  11346. struct tblentry *cmdp;
  11347. int idx;
  11348. int prev;
  11349. char *fullname;
  11350. struct stat statb;
  11351. int e;
  11352. int updatetbl;
  11353. struct builtincmd *bcmd;
  11354. /* If name contains a slash, don't use PATH or hash table */
  11355. if (strchr(name, '/') != NULL) {
  11356. entry->u.index = -1;
  11357. if (act & DO_ABS) {
  11358. while (stat(name, &statb) < 0) {
  11359. #ifdef SYSV
  11360. if (errno == EINTR)
  11361. continue;
  11362. #endif
  11363. entry->cmdtype = CMDUNKNOWN;
  11364. return;
  11365. }
  11366. }
  11367. entry->cmdtype = CMDNORMAL;
  11368. return;
  11369. }
  11370. /* #if ENABLE_FEATURE_SH_STANDALONE... moved after builtin check */
  11371. updatetbl = (path == pathval());
  11372. if (!updatetbl) {
  11373. act |= DO_ALTPATH;
  11374. if (strstr(path, "%builtin") != NULL)
  11375. act |= DO_ALTBLTIN;
  11376. }
  11377. /* If name is in the table, check answer will be ok */
  11378. cmdp = cmdlookup(name, 0);
  11379. if (cmdp != NULL) {
  11380. int bit;
  11381. switch (cmdp->cmdtype) {
  11382. default:
  11383. #if DEBUG
  11384. abort();
  11385. #endif
  11386. case CMDNORMAL:
  11387. bit = DO_ALTPATH;
  11388. break;
  11389. case CMDFUNCTION:
  11390. bit = DO_NOFUNC;
  11391. break;
  11392. case CMDBUILTIN:
  11393. bit = DO_ALTBLTIN;
  11394. break;
  11395. }
  11396. if (act & bit) {
  11397. updatetbl = 0;
  11398. cmdp = NULL;
  11399. } else if (cmdp->rehash == 0)
  11400. /* if not invalidated by cd, we're done */
  11401. goto success;
  11402. }
  11403. /* If %builtin not in path, check for builtin next */
  11404. bcmd = find_builtin(name);
  11405. if (bcmd) {
  11406. if (IS_BUILTIN_REGULAR(bcmd))
  11407. goto builtin_success;
  11408. if (act & DO_ALTPATH) {
  11409. if (!(act & DO_ALTBLTIN))
  11410. goto builtin_success;
  11411. } else if (builtinloc <= 0) {
  11412. goto builtin_success;
  11413. }
  11414. }
  11415. #if ENABLE_FEATURE_SH_STANDALONE
  11416. {
  11417. int applet_no = find_applet_by_name(name);
  11418. if (applet_no >= 0) {
  11419. entry->cmdtype = CMDNORMAL;
  11420. entry->u.index = -2 - applet_no;
  11421. return;
  11422. }
  11423. }
  11424. #endif
  11425. /* We have to search path. */
  11426. prev = -1; /* where to start */
  11427. if (cmdp && cmdp->rehash) { /* doing a rehash */
  11428. if (cmdp->cmdtype == CMDBUILTIN)
  11429. prev = builtinloc;
  11430. else
  11431. prev = cmdp->param.index;
  11432. }
  11433. e = ENOENT;
  11434. idx = -1;
  11435. loop:
  11436. while ((fullname = path_advance(&path, name)) != NULL) {
  11437. stunalloc(fullname);
  11438. /* NB: code below will still use fullname
  11439. * despite it being "unallocated" */
  11440. idx++;
  11441. if (pathopt) {
  11442. if (prefix(pathopt, "builtin")) {
  11443. if (bcmd)
  11444. goto builtin_success;
  11445. continue;
  11446. }
  11447. if ((act & DO_NOFUNC)
  11448. || !prefix(pathopt, "func")
  11449. ) { /* ignore unimplemented options */
  11450. continue;
  11451. }
  11452. }
  11453. /* if rehash, don't redo absolute path names */
  11454. if (fullname[0] == '/' && idx <= prev) {
  11455. if (idx < prev)
  11456. continue;
  11457. TRACE(("searchexec \"%s\": no change\n", name));
  11458. goto success;
  11459. }
  11460. while (stat(fullname, &statb) < 0) {
  11461. #ifdef SYSV
  11462. if (errno == EINTR)
  11463. continue;
  11464. #endif
  11465. if (errno != ENOENT && errno != ENOTDIR)
  11466. e = errno;
  11467. goto loop;
  11468. }
  11469. e = EACCES; /* if we fail, this will be the error */
  11470. if (!S_ISREG(statb.st_mode))
  11471. continue;
  11472. if (pathopt) { /* this is a %func directory */
  11473. stalloc(strlen(fullname) + 1);
  11474. /* NB: stalloc will return space pointed by fullname
  11475. * (because we don't have any intervening allocations
  11476. * between stunalloc above and this stalloc) */
  11477. readcmdfile(fullname);
  11478. cmdp = cmdlookup(name, 0);
  11479. if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION)
  11480. ash_msg_and_raise_error("%s not defined in %s", name, fullname);
  11481. stunalloc(fullname);
  11482. goto success;
  11483. }
  11484. TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
  11485. if (!updatetbl) {
  11486. entry->cmdtype = CMDNORMAL;
  11487. entry->u.index = idx;
  11488. return;
  11489. }
  11490. INT_OFF;
  11491. cmdp = cmdlookup(name, 1);
  11492. cmdp->cmdtype = CMDNORMAL;
  11493. cmdp->param.index = idx;
  11494. INT_ON;
  11495. goto success;
  11496. }
  11497. /* We failed. If there was an entry for this command, delete it */
  11498. if (cmdp && updatetbl)
  11499. delete_cmd_entry();
  11500. if (act & DO_ERR)
  11501. ash_msg("%s: %s", name, errmsg(e, "not found"));
  11502. entry->cmdtype = CMDUNKNOWN;
  11503. return;
  11504. builtin_success:
  11505. if (!updatetbl) {
  11506. entry->cmdtype = CMDBUILTIN;
  11507. entry->u.cmd = bcmd;
  11508. return;
  11509. }
  11510. INT_OFF;
  11511. cmdp = cmdlookup(name, 1);
  11512. cmdp->cmdtype = CMDBUILTIN;
  11513. cmdp->param.cmd = bcmd;
  11514. INT_ON;
  11515. success:
  11516. cmdp->rehash = 0;
  11517. entry->cmdtype = cmdp->cmdtype;
  11518. entry->u = cmdp->param;
  11519. }
  11520. /* ============ trap.c */
  11521. /*
  11522. * The trap builtin.
  11523. */
  11524. static int FAST_FUNC
  11525. trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  11526. {
  11527. char *action;
  11528. char **ap;
  11529. int signo, exitcode;
  11530. nextopt(nullstr);
  11531. ap = argptr;
  11532. if (!*ap) {
  11533. for (signo = 0; signo < NSIG; signo++) {
  11534. char *tr = trap_ptr[signo];
  11535. if (tr) {
  11536. /* note: bash adds "SIG", but only if invoked
  11537. * as "bash". If called as "sh", or if set -o posix,
  11538. * then it prints short signal names.
  11539. * We are printing short names: */
  11540. out1fmt("trap -- %s %s\n",
  11541. single_quote(tr),
  11542. get_signame(signo));
  11543. /* trap_ptr != trap only if we are in special-cased `trap` code.
  11544. * In this case, we will exit very soon, no need to free(). */
  11545. /* if (trap_ptr != trap && tp[0]) */
  11546. /* free(tr); */
  11547. }
  11548. }
  11549. /*
  11550. if (trap_ptr != trap) {
  11551. free(trap_ptr);
  11552. trap_ptr = trap;
  11553. }
  11554. */
  11555. return 0;
  11556. }
  11557. action = NULL;
  11558. if (ap[1])
  11559. action = *ap++;
  11560. exitcode = 0;
  11561. while (*ap) {
  11562. signo = get_signum(*ap);
  11563. if (signo < 0) {
  11564. /* Mimic bash message exactly */
  11565. ash_msg("%s: invalid signal specification", *ap);
  11566. exitcode = 1;
  11567. goto next;
  11568. }
  11569. INT_OFF;
  11570. if (action) {
  11571. if (LONE_DASH(action))
  11572. action = NULL;
  11573. else
  11574. action = ckstrdup(action);
  11575. }
  11576. free(trap[signo]);
  11577. if (action)
  11578. may_have_traps = 1;
  11579. trap[signo] = action;
  11580. if (signo != 0)
  11581. setsignal(signo);
  11582. INT_ON;
  11583. next:
  11584. ap++;
  11585. }
  11586. return exitcode;
  11587. }
  11588. /* ============ Builtins */
  11589. #if ENABLE_ASH_HELP
  11590. static int FAST_FUNC
  11591. helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  11592. {
  11593. unsigned col;
  11594. unsigned i;
  11595. out1fmt(
  11596. "Built-in commands:\n"
  11597. "------------------\n");
  11598. for (col = 0, i = 0; i < ARRAY_SIZE(builtintab); i++) {
  11599. col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
  11600. builtintab[i].name + 1);
  11601. if (col > 60) {
  11602. out1fmt("\n");
  11603. col = 0;
  11604. }
  11605. }
  11606. # if ENABLE_FEATURE_SH_STANDALONE
  11607. {
  11608. const char *a = applet_names;
  11609. while (*a) {
  11610. col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
  11611. if (col > 60) {
  11612. out1fmt("\n");
  11613. col = 0;
  11614. }
  11615. a += strlen(a) + 1;
  11616. }
  11617. }
  11618. # endif
  11619. out1fmt("\n\n");
  11620. return EXIT_SUCCESS;
  11621. }
  11622. #endif
  11623. #if MAX_HISTORY
  11624. static int FAST_FUNC
  11625. historycmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  11626. {
  11627. show_history(line_input_state);
  11628. return EXIT_SUCCESS;
  11629. }
  11630. #endif
  11631. /*
  11632. * The export and readonly commands.
  11633. */
  11634. static int FAST_FUNC
  11635. exportcmd(int argc UNUSED_PARAM, char **argv)
  11636. {
  11637. struct var *vp;
  11638. char *name;
  11639. const char *p;
  11640. char **aptr;
  11641. char opt;
  11642. int flag;
  11643. int flag_off;
  11644. /* "readonly" in bash accepts, but ignores -n.
  11645. * We do the same: it saves a conditional in nextopt's param.
  11646. */
  11647. flag_off = 0;
  11648. while ((opt = nextopt("np")) != '\0') {
  11649. if (opt == 'n')
  11650. flag_off = VEXPORT;
  11651. }
  11652. flag = VEXPORT;
  11653. if (argv[0][0] == 'r') {
  11654. flag = VREADONLY;
  11655. flag_off = 0; /* readonly ignores -n */
  11656. }
  11657. flag_off = ~flag_off;
  11658. /*if (opt_p_not_specified) - bash doesnt check this. Try "export -p NAME" */
  11659. {
  11660. aptr = argptr;
  11661. name = *aptr;
  11662. if (name) {
  11663. do {
  11664. p = strchr(name, '=');
  11665. if (p != NULL) {
  11666. p++;
  11667. } else {
  11668. vp = *findvar(hashvar(name), name);
  11669. if (vp) {
  11670. vp->flags = ((vp->flags | flag) & flag_off);
  11671. continue;
  11672. }
  11673. }
  11674. setvar(name, p, (flag & flag_off));
  11675. } while ((name = *++aptr) != NULL);
  11676. return 0;
  11677. }
  11678. }
  11679. /* No arguments. Show the list of exported or readonly vars.
  11680. * -n is ignored.
  11681. */
  11682. showvars(argv[0], flag, 0);
  11683. return 0;
  11684. }
  11685. /*
  11686. * Delete a function if it exists.
  11687. */
  11688. static void
  11689. unsetfunc(const char *name)
  11690. {
  11691. struct tblentry *cmdp;
  11692. cmdp = cmdlookup(name, 0);
  11693. if (cmdp != NULL && cmdp->cmdtype == CMDFUNCTION)
  11694. delete_cmd_entry();
  11695. }
  11696. /*
  11697. * The unset builtin command. We unset the function before we unset the
  11698. * variable to allow a function to be unset when there is a readonly variable
  11699. * with the same name.
  11700. */
  11701. static int FAST_FUNC
  11702. unsetcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  11703. {
  11704. char **ap;
  11705. int i;
  11706. int flag = 0;
  11707. int ret = 0;
  11708. while ((i = nextopt("vf")) != 0) {
  11709. flag = i;
  11710. }
  11711. for (ap = argptr; *ap; ap++) {
  11712. if (flag != 'f') {
  11713. i = unsetvar(*ap);
  11714. ret |= i;
  11715. if (!(i & 2))
  11716. continue;
  11717. }
  11718. if (flag != 'v')
  11719. unsetfunc(*ap);
  11720. }
  11721. return ret & 1;
  11722. }
  11723. static const unsigned char timescmd_str[] ALIGN1 = {
  11724. ' ', offsetof(struct tms, tms_utime),
  11725. '\n', offsetof(struct tms, tms_stime),
  11726. ' ', offsetof(struct tms, tms_cutime),
  11727. '\n', offsetof(struct tms, tms_cstime),
  11728. 0
  11729. };
  11730. static int FAST_FUNC
  11731. timescmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  11732. {
  11733. unsigned long clk_tck, s, t;
  11734. const unsigned char *p;
  11735. struct tms buf;
  11736. clk_tck = bb_clk_tck();
  11737. times(&buf);
  11738. p = timescmd_str;
  11739. do {
  11740. t = *(clock_t *)(((char *) &buf) + p[1]);
  11741. s = t / clk_tck;
  11742. t = t % clk_tck;
  11743. out1fmt("%lum%lu.%03lus%c",
  11744. s / 60, s % 60,
  11745. (t * 1000) / clk_tck,
  11746. p[0]);
  11747. p += 2;
  11748. } while (*p);
  11749. return 0;
  11750. }
  11751. #if ENABLE_SH_MATH_SUPPORT
  11752. /*
  11753. * The let builtin. Partially stolen from GNU Bash, the Bourne Again SHell.
  11754. * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
  11755. *
  11756. * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
  11757. */
  11758. static int FAST_FUNC
  11759. letcmd(int argc UNUSED_PARAM, char **argv)
  11760. {
  11761. arith_t i;
  11762. argv++;
  11763. if (!*argv)
  11764. ash_msg_and_raise_error("expression expected");
  11765. do {
  11766. i = ash_arith(*argv);
  11767. } while (*++argv);
  11768. return !i;
  11769. }
  11770. #endif
  11771. /*
  11772. * The read builtin. Options:
  11773. * -r Do not interpret '\' specially
  11774. * -s Turn off echo (tty only)
  11775. * -n NCHARS Read NCHARS max
  11776. * -p PROMPT Display PROMPT on stderr (if input is from tty)
  11777. * -t SECONDS Timeout after SECONDS (tty or pipe only)
  11778. * -u FD Read from given FD instead of fd 0
  11779. * This uses unbuffered input, which may be avoidable in some cases.
  11780. * TODO: bash also has:
  11781. * -a ARRAY Read into array[0],[1],etc
  11782. * -d DELIM End on DELIM char, not newline
  11783. * -e Use line editing (tty only)
  11784. */
  11785. static int FAST_FUNC
  11786. readcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  11787. {
  11788. char *opt_n = NULL;
  11789. char *opt_p = NULL;
  11790. char *opt_t = NULL;
  11791. char *opt_u = NULL;
  11792. int read_flags = 0;
  11793. const char *r;
  11794. int i;
  11795. while ((i = nextopt("p:u:rt:n:s")) != '\0') {
  11796. switch (i) {
  11797. case 'p':
  11798. opt_p = optionarg;
  11799. break;
  11800. case 'n':
  11801. opt_n = optionarg;
  11802. break;
  11803. case 's':
  11804. read_flags |= BUILTIN_READ_SILENT;
  11805. break;
  11806. case 't':
  11807. opt_t = optionarg;
  11808. break;
  11809. case 'r':
  11810. read_flags |= BUILTIN_READ_RAW;
  11811. break;
  11812. case 'u':
  11813. opt_u = optionarg;
  11814. break;
  11815. default:
  11816. break;
  11817. }
  11818. }
  11819. /* "read -s" needs to save/restore termios, can't allow ^C
  11820. * to jump out of it.
  11821. */
  11822. INT_OFF;
  11823. r = shell_builtin_read(setvar2,
  11824. argptr,
  11825. bltinlookup("IFS"), /* can be NULL */
  11826. read_flags,
  11827. opt_n,
  11828. opt_p,
  11829. opt_t,
  11830. opt_u
  11831. );
  11832. INT_ON;
  11833. if ((uintptr_t)r > 1)
  11834. ash_msg_and_raise_error(r);
  11835. return (uintptr_t)r;
  11836. }
  11837. static int FAST_FUNC
  11838. umaskcmd(int argc UNUSED_PARAM, char **argv)
  11839. {
  11840. static const char permuser[3] ALIGN1 = "ugo";
  11841. static const char permmode[3] ALIGN1 = "rwx";
  11842. static const short permmask[] ALIGN2 = {
  11843. S_IRUSR, S_IWUSR, S_IXUSR,
  11844. S_IRGRP, S_IWGRP, S_IXGRP,
  11845. S_IROTH, S_IWOTH, S_IXOTH
  11846. };
  11847. /* TODO: use bb_parse_mode() instead */
  11848. char *ap;
  11849. mode_t mask;
  11850. int i;
  11851. int symbolic_mode = 0;
  11852. while (nextopt("S") != '\0') {
  11853. symbolic_mode = 1;
  11854. }
  11855. INT_OFF;
  11856. mask = umask(0);
  11857. umask(mask);
  11858. INT_ON;
  11859. ap = *argptr;
  11860. if (ap == NULL) {
  11861. if (symbolic_mode) {
  11862. char buf[18];
  11863. char *p = buf;
  11864. for (i = 0; i < 3; i++) {
  11865. int j;
  11866. *p++ = permuser[i];
  11867. *p++ = '=';
  11868. for (j = 0; j < 3; j++) {
  11869. if ((mask & permmask[3 * i + j]) == 0) {
  11870. *p++ = permmode[j];
  11871. }
  11872. }
  11873. *p++ = ',';
  11874. }
  11875. *--p = 0;
  11876. puts(buf);
  11877. } else {
  11878. out1fmt("%.4o\n", mask);
  11879. }
  11880. } else {
  11881. if (isdigit((unsigned char) *ap)) {
  11882. mask = 0;
  11883. do {
  11884. if (*ap >= '8' || *ap < '0')
  11885. ash_msg_and_raise_error(msg_illnum, argv[1]);
  11886. mask = (mask << 3) + (*ap - '0');
  11887. } while (*++ap != '\0');
  11888. umask(mask);
  11889. } else {
  11890. mask = ~mask & 0777;
  11891. if (!bb_parse_mode(ap, &mask)) {
  11892. ash_msg_and_raise_error("illegal mode: %s", ap);
  11893. }
  11894. umask(~mask & 0777);
  11895. }
  11896. }
  11897. return 0;
  11898. }
  11899. static int FAST_FUNC
  11900. ulimitcmd(int argc UNUSED_PARAM, char **argv)
  11901. {
  11902. return shell_builtin_ulimit(argv);
  11903. }
  11904. /* ============ main() and helpers */
  11905. /*
  11906. * Called to exit the shell.
  11907. */
  11908. static void
  11909. exitshell(void)
  11910. {
  11911. struct jmploc loc;
  11912. char *p;
  11913. int status;
  11914. #if ENABLE_FEATURE_EDITING_SAVE_ON_EXIT
  11915. save_history(line_input_state);
  11916. #endif
  11917. status = exitstatus;
  11918. TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
  11919. if (setjmp(loc.loc)) {
  11920. if (exception_type == EXEXIT)
  11921. /* dash bug: it just does _exit(exitstatus) here
  11922. * but we have to do setjobctl(0) first!
  11923. * (bug is still not fixed in dash-0.5.3 - if you run dash
  11924. * under Midnight Commander, on exit from dash MC is backgrounded) */
  11925. status = exitstatus;
  11926. goto out;
  11927. }
  11928. exception_handler = &loc;
  11929. p = trap[0];
  11930. if (p) {
  11931. trap[0] = NULL;
  11932. evalstring(p, 0);
  11933. free(p);
  11934. }
  11935. flush_stdout_stderr();
  11936. out:
  11937. setjobctl(0);
  11938. _exit(status);
  11939. /* NOTREACHED */
  11940. }
  11941. static void
  11942. init(void)
  11943. {
  11944. /* from input.c: */
  11945. /* we will never free this */
  11946. basepf.next_to_pgetc = basepf.buf = ckmalloc(IBUFSIZ);
  11947. /* from trap.c: */
  11948. signal(SIGCHLD, SIG_DFL);
  11949. /* bash re-enables SIGHUP which is SIG_IGNed on entry.
  11950. * Try: "trap '' HUP; bash; echo RET" and type "kill -HUP $$"
  11951. */
  11952. signal(SIGHUP, SIG_DFL);
  11953. /* from var.c: */
  11954. {
  11955. char **envp;
  11956. const char *p;
  11957. struct stat st1, st2;
  11958. initvar();
  11959. for (envp = environ; envp && *envp; envp++) {
  11960. if (strchr(*envp, '=')) {
  11961. setvareq(*envp, VEXPORT|VTEXTFIXED);
  11962. }
  11963. }
  11964. setvar2("PPID", utoa(getppid()));
  11965. #if ENABLE_ASH_BASH_COMPAT
  11966. p = lookupvar("SHLVL");
  11967. setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
  11968. if (!lookupvar("HOSTNAME")) {
  11969. struct utsname uts;
  11970. uname(&uts);
  11971. setvar2("HOSTNAME", uts.nodename);
  11972. }
  11973. #endif
  11974. p = lookupvar("PWD");
  11975. if (p) {
  11976. if (*p != '/' || stat(p, &st1) || stat(".", &st2)
  11977. || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
  11978. ) {
  11979. p = '\0';
  11980. }
  11981. }
  11982. setpwd(p, 0);
  11983. }
  11984. }
  11985. //usage:#define ash_trivial_usage
  11986. //usage: "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
  11987. //usage:#define ash_full_usage "\n\n"
  11988. //usage: "Unix shell interpreter"
  11989. //usage:#if ENABLE_FEATURE_SH_IS_ASH
  11990. //usage:# define sh_trivial_usage ash_trivial_usage
  11991. //usage:# define sh_full_usage ash_full_usage
  11992. //usage:#endif
  11993. //usage:#if ENABLE_FEATURE_BASH_IS_ASH
  11994. //usage:# define bash_trivial_usage ash_trivial_usage
  11995. //usage:# define bash_full_usage ash_full_usage
  11996. //usage:#endif
  11997. /*
  11998. * Process the shell command line arguments.
  11999. */
  12000. static void
  12001. procargs(char **argv)
  12002. {
  12003. int i;
  12004. const char *xminusc;
  12005. char **xargv;
  12006. xargv = argv;
  12007. arg0 = xargv[0];
  12008. /* if (xargv[0]) - mmm, this is always true! */
  12009. xargv++;
  12010. for (i = 0; i < NOPTS; i++)
  12011. optlist[i] = 2;
  12012. argptr = xargv;
  12013. if (options(/*cmdline:*/ 1)) {
  12014. /* it already printed err message */
  12015. raise_exception(EXERROR);
  12016. }
  12017. xargv = argptr;
  12018. xminusc = minusc;
  12019. if (*xargv == NULL) {
  12020. if (xminusc)
  12021. ash_msg_and_raise_error(bb_msg_requires_arg, "-c");
  12022. sflag = 1;
  12023. }
  12024. if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
  12025. iflag = 1;
  12026. if (mflag == 2)
  12027. mflag = iflag;
  12028. for (i = 0; i < NOPTS; i++)
  12029. if (optlist[i] == 2)
  12030. optlist[i] = 0;
  12031. #if DEBUG == 2
  12032. debug = 1;
  12033. #endif
  12034. /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
  12035. if (xminusc) {
  12036. minusc = *xargv++;
  12037. if (*xargv)
  12038. goto setarg0;
  12039. } else if (!sflag) {
  12040. setinputfile(*xargv, 0);
  12041. setarg0:
  12042. arg0 = *xargv++;
  12043. commandname = arg0;
  12044. }
  12045. shellparam.p = xargv;
  12046. #if ENABLE_ASH_GETOPTS
  12047. shellparam.optind = 1;
  12048. shellparam.optoff = -1;
  12049. #endif
  12050. /* assert(shellparam.malloced == 0 && shellparam.nparam == 0); */
  12051. while (*xargv) {
  12052. shellparam.nparam++;
  12053. xargv++;
  12054. }
  12055. optschanged();
  12056. }
  12057. /*
  12058. * Read /etc/profile or .profile.
  12059. */
  12060. static void
  12061. read_profile(const char *name)
  12062. {
  12063. int skip;
  12064. if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
  12065. return;
  12066. skip = cmdloop(0);
  12067. popfile();
  12068. if (skip)
  12069. exitshell();
  12070. }
  12071. /*
  12072. * This routine is called when an error or an interrupt occurs in an
  12073. * interactive shell and control is returned to the main command loop.
  12074. */
  12075. static void
  12076. reset(void)
  12077. {
  12078. /* from eval.c: */
  12079. evalskip = 0;
  12080. loopnest = 0;
  12081. /* from input.c: */
  12082. g_parsefile->left_in_buffer = 0;
  12083. g_parsefile->left_in_line = 0; /* clear input buffer */
  12084. popallfiles();
  12085. /* from parser.c: */
  12086. tokpushback = 0;
  12087. checkkwd = 0;
  12088. /* from redir.c: */
  12089. clearredir(/*drop:*/ 0);
  12090. }
  12091. #if PROFILE
  12092. static short profile_buf[16384];
  12093. extern int etext();
  12094. #endif
  12095. /*
  12096. * Main routine. We initialize things, parse the arguments, execute
  12097. * profiles if we're a login shell, and then call cmdloop to execute
  12098. * commands. The setjmp call sets up the location to jump to when an
  12099. * exception occurs. When an exception occurs the variable "state"
  12100. * is used to figure out how far we had gotten.
  12101. */
  12102. int ash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  12103. int ash_main(int argc UNUSED_PARAM, char **argv)
  12104. {
  12105. const char *shinit;
  12106. volatile smallint state;
  12107. struct jmploc jmploc;
  12108. struct stackmark smark;
  12109. /* Initialize global data */
  12110. INIT_G_misc();
  12111. INIT_G_memstack();
  12112. INIT_G_var();
  12113. #if ENABLE_ASH_ALIAS
  12114. INIT_G_alias();
  12115. #endif
  12116. INIT_G_cmdtable();
  12117. #if PROFILE
  12118. monitor(4, etext, profile_buf, sizeof(profile_buf), 50);
  12119. #endif
  12120. #if ENABLE_FEATURE_EDITING
  12121. line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
  12122. #endif
  12123. state = 0;
  12124. if (setjmp(jmploc.loc)) {
  12125. smallint e;
  12126. smallint s;
  12127. reset();
  12128. e = exception_type;
  12129. if (e == EXERROR)
  12130. exitstatus = 2;
  12131. s = state;
  12132. if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) {
  12133. exitshell();
  12134. }
  12135. if (e == EXINT) {
  12136. outcslow('\n', stderr);
  12137. }
  12138. popstackmark(&smark);
  12139. FORCE_INT_ON; /* enable interrupts */
  12140. if (s == 1)
  12141. goto state1;
  12142. if (s == 2)
  12143. goto state2;
  12144. if (s == 3)
  12145. goto state3;
  12146. goto state4;
  12147. }
  12148. exception_handler = &jmploc;
  12149. #if DEBUG
  12150. opentrace();
  12151. TRACE(("Shell args: "));
  12152. trace_puts_args(argv);
  12153. #endif
  12154. rootpid = getpid();
  12155. init();
  12156. setstackmark(&smark);
  12157. procargs(argv);
  12158. if (argv[0] && argv[0][0] == '-')
  12159. isloginsh = 1;
  12160. if (isloginsh) {
  12161. const char *hp;
  12162. state = 1;
  12163. read_profile("/etc/profile");
  12164. state1:
  12165. state = 2;
  12166. hp = lookupvar("HOME");
  12167. if (hp) {
  12168. hp = concat_path_file(hp, ".profile");
  12169. read_profile(hp);
  12170. free((char*)hp);
  12171. }
  12172. }
  12173. state2:
  12174. state = 3;
  12175. if (
  12176. #ifndef linux
  12177. getuid() == geteuid() && getgid() == getegid() &&
  12178. #endif
  12179. iflag
  12180. ) {
  12181. shinit = lookupvar("ENV");
  12182. if (shinit != NULL && *shinit != '\0') {
  12183. read_profile(shinit);
  12184. }
  12185. }
  12186. state3:
  12187. state = 4;
  12188. if (minusc) {
  12189. /* evalstring pushes parsefile stack.
  12190. * Ensure we don't falsely claim that 0 (stdin)
  12191. * is one of stacked source fds.
  12192. * Testcase: ash -c 'exec 1>&0' must not complain. */
  12193. // if (!sflag) g_parsefile->pf_fd = -1;
  12194. // ^^ not necessary since now we special-case fd 0
  12195. // in is_hidden_fd() to not be considered "hidden fd"
  12196. evalstring(minusc, 0);
  12197. }
  12198. if (sflag || minusc == NULL) {
  12199. #if MAX_HISTORY > 0 && ENABLE_FEATURE_EDITING_SAVEHISTORY
  12200. if (iflag) {
  12201. const char *hp = lookupvar("HISTFILE");
  12202. if (!hp) {
  12203. hp = lookupvar("HOME");
  12204. if (hp) {
  12205. hp = concat_path_file(hp, ".ash_history");
  12206. setvar2("HISTFILE", hp);
  12207. free((char*)hp);
  12208. hp = lookupvar("HISTFILE");
  12209. }
  12210. }
  12211. if (hp)
  12212. line_input_state->hist_file = hp;
  12213. # if ENABLE_FEATURE_SH_HISTFILESIZE
  12214. hp = lookupvar("HISTFILESIZE");
  12215. line_input_state->max_history = size_from_HISTFILESIZE(hp);
  12216. # endif
  12217. }
  12218. #endif
  12219. state4: /* XXX ??? - why isn't this before the "if" statement */
  12220. cmdloop(1);
  12221. }
  12222. #if PROFILE
  12223. monitor(0);
  12224. #endif
  12225. #ifdef GPROF
  12226. {
  12227. extern void _mcleanup(void);
  12228. _mcleanup();
  12229. }
  12230. #endif
  12231. TRACE(("End of main reached\n"));
  12232. exitshell();
  12233. /* NOTREACHED */
  12234. }
  12235. /*-
  12236. * Copyright (c) 1989, 1991, 1993, 1994
  12237. * The Regents of the University of California. All rights reserved.
  12238. *
  12239. * This code is derived from software contributed to Berkeley by
  12240. * Kenneth Almquist.
  12241. *
  12242. * Redistribution and use in source and binary forms, with or without
  12243. * modification, are permitted provided that the following conditions
  12244. * are met:
  12245. * 1. Redistributions of source code must retain the above copyright
  12246. * notice, this list of conditions and the following disclaimer.
  12247. * 2. Redistributions in binary form must reproduce the above copyright
  12248. * notice, this list of conditions and the following disclaimer in the
  12249. * documentation and/or other materials provided with the distribution.
  12250. * 3. Neither the name of the University nor the names of its contributors
  12251. * may be used to endorse or promote products derived from this software
  12252. * without specific prior written permission.
  12253. *
  12254. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  12255. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  12256. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  12257. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  12258. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  12259. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  12260. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  12261. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  12262. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  12263. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  12264. * SUCH DAMAGE.
  12265. */