3
0

ash.c 282 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * ash shell port for busybox
  4. *
  5. * Copyright (c) 1989, 1991, 1993, 1994
  6. * The Regents of the University of California. All rights reserved.
  7. *
  8. * Copyright (c) 1997-2003 Herbert Xu <herbert@debian.org>
  9. * was re-ported from NetBSD and debianized.
  10. *
  11. *
  12. * This code is derived from software contributed to Berkeley by
  13. * Kenneth Almquist.
  14. *
  15. * This program is free software; you can redistribute it and/or modify
  16. * it under the terms of the GNU General Public License as published by
  17. * the Free Software Foundation; either version 2 of the License, or
  18. * (at your option) any later version.
  19. *
  20. * This program is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  23. * General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this program; if not, write to the Free Software
  27. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  28. *
  29. * Original BSD copyright notice is retained at the end of this file.
  30. */
  31. /*
  32. * rewrite arith.y to micro stack based cryptic algorithm by
  33. * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
  34. *
  35. * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
  36. * dynamic variables.
  37. *
  38. * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2004 to be
  39. * used in busybox and size optimizations,
  40. * rewrote arith (see notes to this), added locale support,
  41. * rewrote dynamic variables.
  42. *
  43. */
  44. /*
  45. * The follow should be set to reflect the type of system you have:
  46. * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
  47. * define SYSV if you are running under System V.
  48. * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
  49. * define DEBUG=2 to compile in and turn on debugging.
  50. *
  51. * When debugging is on, debugging info will be written to ./trace and
  52. * a quit signal will generate a core dump.
  53. */
  54. #define IFS_BROKEN
  55. #define PROFILE 0
  56. #ifdef DEBUG
  57. #define _GNU_SOURCE
  58. #endif
  59. #include <sys/types.h>
  60. #include <sys/cdefs.h>
  61. #include <sys/ioctl.h>
  62. #include <sys/param.h>
  63. #include <sys/resource.h>
  64. #include <sys/stat.h>
  65. #include <sys/time.h>
  66. #include <sys/wait.h>
  67. #include <stdio.h>
  68. #include <stdlib.h>
  69. #include <string.h>
  70. #include <unistd.h>
  71. #include <stdarg.h>
  72. #include <stddef.h>
  73. #include <assert.h>
  74. #include <ctype.h>
  75. #include <dirent.h>
  76. #include <errno.h>
  77. #include <fcntl.h>
  78. #include <limits.h>
  79. #include <paths.h>
  80. #include <setjmp.h>
  81. #include <signal.h>
  82. #include <stdint.h>
  83. #include <sysexits.h>
  84. #include <time.h>
  85. #include <fnmatch.h>
  86. #include "busybox.h"
  87. #include "pwd_.h"
  88. #ifdef CONFIG_ASH_JOB_CONTROL
  89. #define JOBS 1
  90. #else
  91. #undef JOBS
  92. #endif
  93. #if JOBS
  94. #include <termios.h>
  95. #endif
  96. #include "cmdedit.h"
  97. #ifdef __GLIBC__
  98. /* glibc sucks */
  99. static int *dash_errno;
  100. #undef errno
  101. #define errno (*dash_errno)
  102. #endif
  103. #if defined(__uClinux__)
  104. #error "Do not even bother, ash will not run on uClinux"
  105. #endif
  106. #ifdef DEBUG
  107. #define _DIAGASSERT(assert_expr) assert(assert_expr)
  108. #else
  109. #define _DIAGASSERT(assert_expr)
  110. #endif
  111. #ifdef CONFIG_ASH_ALIAS
  112. /* $NetBSD: alias.h,v 1.5 2002/11/24 22:35:38 christos Exp $ */
  113. #define ALIASINUSE 1
  114. #define ALIASDEAD 2
  115. struct alias {
  116. struct alias *next;
  117. char *name;
  118. char *val;
  119. int flag;
  120. };
  121. static struct alias *lookupalias(const char *, int);
  122. static int aliascmd(int, char **);
  123. static int unaliascmd(int, char **);
  124. static void rmaliases(void);
  125. static int unalias(const char *);
  126. static void printalias(const struct alias *);
  127. #endif
  128. /* $NetBSD: cd.h,v 1.3 2002/11/24 22:35:39 christos Exp $ */
  129. static void setpwd(const char *, int);
  130. /* $NetBSD: error.h,v 1.15 2002/11/24 22:35:39 christos Exp $ */
  131. /*
  132. * Types of operations (passed to the errmsg routine).
  133. */
  134. static const char not_found_msg[] = "%s: not found";
  135. #define E_OPEN "No such file" /* opening a file */
  136. #define E_CREAT "Directory nonexistent" /* creating a file */
  137. #define E_EXEC not_found_msg+4 /* executing a program */
  138. /*
  139. * We enclose jmp_buf in a structure so that we can declare pointers to
  140. * jump locations. The global variable handler contains the location to
  141. * jump to when an exception occurs, and the global variable exception
  142. * contains a code identifying the exception. To implement nested
  143. * exception handlers, the user should save the value of handler on entry
  144. * to an inner scope, set handler to point to a jmploc structure for the
  145. * inner scope, and restore handler on exit from the scope.
  146. */
  147. struct jmploc {
  148. jmp_buf loc;
  149. };
  150. static struct jmploc *handler;
  151. static int exception;
  152. static volatile int suppressint;
  153. static volatile sig_atomic_t intpending;
  154. static int exerrno; /* Last exec error, error for EXEXEC */
  155. /* exceptions */
  156. #define EXINT 0 /* SIGINT received */
  157. #define EXERROR 1 /* a generic error */
  158. #define EXSHELLPROC 2 /* execute a shell procedure */
  159. #define EXEXEC 3 /* command execution failed */
  160. #define EXEXIT 4 /* exit the shell */
  161. #define EXSIG 5 /* trapped signal in wait(1) */
  162. /* do we generate EXSIG events */
  163. static int exsig;
  164. /* last pending signal */
  165. static volatile sig_atomic_t pendingsigs;
  166. /*
  167. * These macros allow the user to suspend the handling of interrupt signals
  168. * over a period of time. This is similar to SIGHOLD to or sigblock, but
  169. * much more efficient and portable. (But hacking the kernel is so much
  170. * more fun than worrying about efficiency and portability. :-))
  171. */
  172. #define xbarrier() ({ __asm__ __volatile__ ("": : :"memory"); })
  173. #define INTOFF \
  174. ({ \
  175. suppressint++; \
  176. xbarrier(); \
  177. 0; \
  178. })
  179. #define SAVEINT(v) ((v) = suppressint)
  180. #define RESTOREINT(v) \
  181. ({ \
  182. xbarrier(); \
  183. if ((suppressint = (v)) == 0 && intpending) onint(); \
  184. 0; \
  185. })
  186. #define EXSIGON() \
  187. ({ \
  188. exsig++; \
  189. xbarrier(); \
  190. if (pendingsigs) \
  191. exraise(EXSIG); \
  192. 0; \
  193. })
  194. /* EXSIG is turned off by evalbltin(). */
  195. static void exraise(int) __attribute__((__noreturn__));
  196. static void onint(void) __attribute__((__noreturn__));
  197. static void error(const char *, ...) __attribute__((__noreturn__));
  198. static void exerror(int, const char *, ...) __attribute__((__noreturn__));
  199. static void sh_warnx(const char *, ...);
  200. #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
  201. static void
  202. inton(void) {
  203. if (--suppressint == 0 && intpending) {
  204. onint();
  205. }
  206. }
  207. #define INTON inton()
  208. static void forceinton(void)
  209. {
  210. suppressint = 0;
  211. if (intpending)
  212. onint();
  213. }
  214. #define FORCEINTON forceinton()
  215. #else
  216. #define INTON \
  217. ({ \
  218. xbarrier(); \
  219. if (--suppressint == 0 && intpending) onint(); \
  220. 0; \
  221. })
  222. #define FORCEINTON \
  223. ({ \
  224. xbarrier(); \
  225. suppressint = 0; \
  226. if (intpending) onint(); \
  227. 0; \
  228. })
  229. #endif /* CONFIG_ASH_OPTIMIZE_FOR_SIZE */
  230. /*
  231. * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
  232. * so we use _setjmp instead.
  233. */
  234. #if defined(BSD) && !defined(__SVR4) && !defined(__GLIBC__)
  235. #define setjmp(jmploc) _setjmp(jmploc)
  236. #define longjmp(jmploc, val) _longjmp(jmploc, val)
  237. #endif
  238. /* $NetBSD: expand.h,v 1.13 2002/11/24 22:35:40 christos Exp $ */
  239. struct strlist {
  240. struct strlist *next;
  241. char *text;
  242. };
  243. struct arglist {
  244. struct strlist *list;
  245. struct strlist **lastp;
  246. };
  247. /*
  248. * expandarg() flags
  249. */
  250. #define EXP_FULL 0x1 /* perform word splitting & file globbing */
  251. #define EXP_TILDE 0x2 /* do normal tilde expansion */
  252. #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
  253. #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
  254. #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
  255. #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
  256. #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
  257. #define EXP_WORD 0x80 /* expand word in parameter expansion */
  258. #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
  259. union node;
  260. static void expandarg(union node *, struct arglist *, int);
  261. #define rmescapes(p) _rmescapes((p), 0)
  262. static char *_rmescapes(char *, int);
  263. static int casematch(union node *, char *);
  264. #ifdef CONFIG_ASH_MATH_SUPPORT
  265. static void expari(int);
  266. #endif
  267. /* $NetBSD: eval.h,v 1.13 2002/11/24 22:35:39 christos Exp $ */
  268. static char *commandname; /* currently executing command */
  269. static struct strlist *cmdenviron; /* environment for builtin command */
  270. static int exitstatus; /* exit status of last command */
  271. static int back_exitstatus; /* exit status of backquoted command */
  272. struct backcmd { /* result of evalbackcmd */
  273. int fd; /* file descriptor to read from */
  274. char *buf; /* buffer */
  275. int nleft; /* number of chars in buffer */
  276. struct job *jp; /* job structure for command */
  277. };
  278. /*
  279. * This file was generated by the mknodes program.
  280. */
  281. #define NCMD 0
  282. #define NPIPE 1
  283. #define NREDIR 2
  284. #define NBACKGND 3
  285. #define NSUBSHELL 4
  286. #define NAND 5
  287. #define NOR 6
  288. #define NSEMI 7
  289. #define NIF 8
  290. #define NWHILE 9
  291. #define NUNTIL 10
  292. #define NFOR 11
  293. #define NCASE 12
  294. #define NCLIST 13
  295. #define NDEFUN 14
  296. #define NARG 15
  297. #define NTO 16
  298. #define NCLOBBER 17
  299. #define NFROM 18
  300. #define NFROMTO 19
  301. #define NAPPEND 20
  302. #define NTOFD 21
  303. #define NFROMFD 22
  304. #define NHERE 23
  305. #define NXHERE 24
  306. #define NNOT 25
  307. struct ncmd {
  308. int type;
  309. union node *assign;
  310. union node *args;
  311. union node *redirect;
  312. };
  313. struct npipe {
  314. int type;
  315. int backgnd;
  316. struct nodelist *cmdlist;
  317. };
  318. struct nredir {
  319. int type;
  320. union node *n;
  321. union node *redirect;
  322. };
  323. struct nbinary {
  324. int type;
  325. union node *ch1;
  326. union node *ch2;
  327. };
  328. struct nif {
  329. int type;
  330. union node *test;
  331. union node *ifpart;
  332. union node *elsepart;
  333. };
  334. struct nfor {
  335. int type;
  336. union node *args;
  337. union node *body;
  338. char *var;
  339. };
  340. struct ncase {
  341. int type;
  342. union node *expr;
  343. union node *cases;
  344. };
  345. struct nclist {
  346. int type;
  347. union node *next;
  348. union node *pattern;
  349. union node *body;
  350. };
  351. struct narg {
  352. int type;
  353. union node *next;
  354. char *text;
  355. struct nodelist *backquote;
  356. };
  357. struct nfile {
  358. int type;
  359. union node *next;
  360. int fd;
  361. union node *fname;
  362. char *expfname;
  363. };
  364. struct ndup {
  365. int type;
  366. union node *next;
  367. int fd;
  368. int dupfd;
  369. union node *vname;
  370. };
  371. struct nhere {
  372. int type;
  373. union node *next;
  374. int fd;
  375. union node *doc;
  376. };
  377. struct nnot {
  378. int type;
  379. union node *com;
  380. };
  381. union node {
  382. int type;
  383. struct ncmd ncmd;
  384. struct npipe npipe;
  385. struct nredir nredir;
  386. struct nbinary nbinary;
  387. struct nif nif;
  388. struct nfor nfor;
  389. struct ncase ncase;
  390. struct nclist nclist;
  391. struct narg narg;
  392. struct nfile nfile;
  393. struct ndup ndup;
  394. struct nhere nhere;
  395. struct nnot nnot;
  396. };
  397. struct nodelist {
  398. struct nodelist *next;
  399. union node *n;
  400. };
  401. struct funcnode {
  402. int count;
  403. union node n;
  404. };
  405. static void freefunc(struct funcnode *);
  406. /* $NetBSD: parser.h,v 1.15 2002/11/24 22:35:42 christos Exp $ */
  407. /* control characters in argument strings */
  408. #define CTL_FIRST '\201' /* first 'special' character */
  409. #define CTLESC '\201' /* escape next character */
  410. #define CTLVAR '\202' /* variable defn */
  411. #define CTLENDVAR '\203'
  412. #define CTLBACKQ '\204'
  413. #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
  414. /* CTLBACKQ | CTLQUOTE == '\205' */
  415. #define CTLARI '\206' /* arithmetic expression */
  416. #define CTLENDARI '\207'
  417. #define CTLQUOTEMARK '\210'
  418. #define CTL_LAST '\210' /* last 'special' character */
  419. /* variable substitution byte (follows CTLVAR) */
  420. #define VSTYPE 0x0f /* type of variable substitution */
  421. #define VSNUL 0x10 /* colon--treat the empty string as unset */
  422. #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
  423. /* values of VSTYPE field */
  424. #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
  425. #define VSMINUS 0x2 /* ${var-text} */
  426. #define VSPLUS 0x3 /* ${var+text} */
  427. #define VSQUESTION 0x4 /* ${var?message} */
  428. #define VSASSIGN 0x5 /* ${var=text} */
  429. #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
  430. #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
  431. #define VSTRIMLEFT 0x8 /* ${var#pattern} */
  432. #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
  433. #define VSLENGTH 0xa /* ${#var} */
  434. /* values of checkkwd variable */
  435. #define CHKALIAS 0x1
  436. #define CHKKWD 0x2
  437. #define CHKNL 0x4
  438. #define IBUFSIZ (BUFSIZ + 1)
  439. /*
  440. * NEOF is returned by parsecmd when it encounters an end of file. It
  441. * must be distinct from NULL, so we use the address of a variable that
  442. * happens to be handy.
  443. */
  444. static int plinno = 1; /* input line number */
  445. /* number of characters left in input buffer */
  446. static int parsenleft; /* copy of parsefile->nleft */
  447. static int parselleft; /* copy of parsefile->lleft */
  448. /* next character in input buffer */
  449. static char *parsenextc; /* copy of parsefile->nextc */
  450. struct strpush {
  451. struct strpush *prev; /* preceding string on stack */
  452. char *prevstring;
  453. int prevnleft;
  454. #ifdef CONFIG_ASH_ALIAS
  455. struct alias *ap; /* if push was associated with an alias */
  456. #endif
  457. char *string; /* remember the string since it may change */
  458. };
  459. struct parsefile {
  460. struct parsefile *prev; /* preceding file on stack */
  461. int linno; /* current line */
  462. int fd; /* file descriptor (or -1 if string) */
  463. int nleft; /* number of chars left in this line */
  464. int lleft; /* number of chars left in this buffer */
  465. char *nextc; /* next char in buffer */
  466. char *buf; /* input buffer */
  467. struct strpush *strpush; /* for pushing strings at this level */
  468. struct strpush basestrpush; /* so pushing one is fast */
  469. };
  470. static struct parsefile basepf; /* top level input file */
  471. static char basebuf[IBUFSIZ]; /* buffer for top level input file */
  472. static struct parsefile *parsefile = &basepf; /* current input file */
  473. static int tokpushback; /* last token pushed back */
  474. #define NEOF ((union node *)&tokpushback)
  475. static int parsebackquote; /* nonzero if we are inside backquotes */
  476. static int doprompt; /* if set, prompt the user */
  477. static int needprompt; /* true if interactive and at start of line */
  478. static int lasttoken; /* last token read */
  479. static char *wordtext; /* text of last word returned by readtoken */
  480. static int checkkwd;
  481. static struct nodelist *backquotelist;
  482. static union node *redirnode;
  483. static struct heredoc *heredoc;
  484. static int quoteflag; /* set if (part of) last token was quoted */
  485. static int startlinno; /* line # where last token started */
  486. static union node *parsecmd(int);
  487. static void fixredir(union node *, const char *, int);
  488. static const char *const *findkwd(const char *);
  489. static char *endofname(const char *);
  490. /* $NetBSD: shell.h,v 1.16 2003/01/22 20:36:04 dsl Exp $ */
  491. typedef void *pointer;
  492. static char nullstr[1]; /* zero length string */
  493. static const char spcstr[] = " ";
  494. static const char snlfmt[] = "%s\n";
  495. static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
  496. static const char illnum[] = "Illegal number: %s";
  497. static const char homestr[] = "HOME";
  498. #ifdef DEBUG
  499. #define TRACE(param) trace param
  500. #define TRACEV(param) tracev param
  501. #else
  502. #define TRACE(param)
  503. #define TRACEV(param)
  504. #endif
  505. #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
  506. #define __builtin_expect(x, expected_value) (x)
  507. #endif
  508. #define xlikely(x) __builtin_expect((x),1)
  509. #define TEOF 0
  510. #define TNL 1
  511. #define TREDIR 2
  512. #define TWORD 3
  513. #define TSEMI 4
  514. #define TBACKGND 5
  515. #define TAND 6
  516. #define TOR 7
  517. #define TPIPE 8
  518. #define TLP 9
  519. #define TRP 10
  520. #define TENDCASE 11
  521. #define TENDBQUOTE 12
  522. #define TNOT 13
  523. #define TCASE 14
  524. #define TDO 15
  525. #define TDONE 16
  526. #define TELIF 17
  527. #define TELSE 18
  528. #define TESAC 19
  529. #define TFI 20
  530. #define TFOR 21
  531. #define TIF 22
  532. #define TIN 23
  533. #define TTHEN 24
  534. #define TUNTIL 25
  535. #define TWHILE 26
  536. #define TBEGIN 27
  537. #define TEND 28
  538. /* first char is indicating which tokens mark the end of a list */
  539. static const char *const tokname_array[] = {
  540. "\1end of file",
  541. "\0newline",
  542. "\0redirection",
  543. "\0word",
  544. "\0;",
  545. "\0&",
  546. "\0&&",
  547. "\0||",
  548. "\0|",
  549. "\0(",
  550. "\1)",
  551. "\1;;",
  552. "\1`",
  553. #define KWDOFFSET 13
  554. /* the following are keywords */
  555. "\0!",
  556. "\0case",
  557. "\1do",
  558. "\1done",
  559. "\1elif",
  560. "\1else",
  561. "\1esac",
  562. "\1fi",
  563. "\0for",
  564. "\0if",
  565. "\0in",
  566. "\1then",
  567. "\0until",
  568. "\0while",
  569. "\0{",
  570. "\1}",
  571. };
  572. static const char *tokname(int tok)
  573. {
  574. static char buf[16];
  575. if (tok >= TSEMI)
  576. buf[0] = '"';
  577. sprintf(buf + (tok >= TSEMI), "%s%c",
  578. tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
  579. return buf;
  580. }
  581. /* $NetBSD: machdep.h,v 1.10 2002/10/07 14:26:08 christos Exp $ */
  582. /*
  583. * Most machines require the value returned from malloc to be aligned
  584. * in some way. The following macro will get this right on many machines.
  585. */
  586. #define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
  587. /*
  588. * It appears that grabstackstr() will barf with such alignments
  589. * because stalloc() will return a string allocated in a new stackblock.
  590. */
  591. #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
  592. /*
  593. * This file was generated by the mksyntax program.
  594. */
  595. /* Syntax classes */
  596. #define CWORD 0 /* character is nothing special */
  597. #define CNL 1 /* newline character */
  598. #define CBACK 2 /* a backslash character */
  599. #define CSQUOTE 3 /* single quote */
  600. #define CDQUOTE 4 /* double quote */
  601. #define CENDQUOTE 5 /* a terminating quote */
  602. #define CBQUOTE 6 /* backwards single quote */
  603. #define CVAR 7 /* a dollar sign */
  604. #define CENDVAR 8 /* a '}' character */
  605. #define CLP 9 /* a left paren in arithmetic */
  606. #define CRP 10 /* a right paren in arithmetic */
  607. #define CENDFILE 11 /* end of file */
  608. #define CCTL 12 /* like CWORD, except it must be escaped */
  609. #define CSPCL 13 /* these terminate a word */
  610. #define CIGN 14 /* character should be ignored */
  611. #ifdef CONFIG_ASH_ALIAS
  612. #define SYNBASE 130
  613. #define PEOF -130
  614. #define PEOA -129
  615. #define PEOA_OR_PEOF PEOA
  616. #else
  617. #define SYNBASE 129
  618. #define PEOF -129
  619. #define PEOA_OR_PEOF PEOF
  620. #endif
  621. #define is_digit(c) ((unsigned)((c) - '0') <= 9)
  622. #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
  623. #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
  624. /*
  625. * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
  626. * (assuming ascii char codes, as the original implementation did)
  627. */
  628. #define is_special(c) \
  629. ( (((unsigned int)c) - 33 < 32) \
  630. && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
  631. #define digit_val(c) ((c) - '0')
  632. /*
  633. * This file was generated by the mksyntax program.
  634. */
  635. #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
  636. #define USE_SIT_FUNCTION
  637. #endif
  638. /* number syntax index */
  639. #define BASESYNTAX 0 /* not in quotes */
  640. #define DQSYNTAX 1 /* in double quotes */
  641. #define SQSYNTAX 2 /* in single quotes */
  642. #define ARISYNTAX 3 /* in arithmetic */
  643. #ifdef CONFIG_ASH_MATH_SUPPORT
  644. static const char S_I_T[][4] = {
  645. #ifdef CONFIG_ASH_ALIAS
  646. {CSPCL, CIGN, CIGN, CIGN}, /* 0, PEOA */
  647. #endif
  648. {CSPCL, CWORD, CWORD, CWORD}, /* 1, ' ' */
  649. {CNL, CNL, CNL, CNL}, /* 2, \n */
  650. {CWORD, CCTL, CCTL, CWORD}, /* 3, !*-/:=?[]~ */
  651. {CDQUOTE, CENDQUOTE, CWORD, CWORD}, /* 4, '"' */
  652. {CVAR, CVAR, CWORD, CVAR}, /* 5, $ */
  653. {CSQUOTE, CWORD, CENDQUOTE, CWORD}, /* 6, "'" */
  654. {CSPCL, CWORD, CWORD, CLP}, /* 7, ( */
  655. {CSPCL, CWORD, CWORD, CRP}, /* 8, ) */
  656. {CBACK, CBACK, CCTL, CBACK}, /* 9, \ */
  657. {CBQUOTE, CBQUOTE, CWORD, CBQUOTE}, /* 10, ` */
  658. {CENDVAR, CENDVAR, CWORD, CENDVAR}, /* 11, } */
  659. #ifndef USE_SIT_FUNCTION
  660. {CENDFILE, CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
  661. {CWORD, CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
  662. {CCTL, CCTL, CCTL, CCTL} /* 14, CTLESC ... */
  663. #endif
  664. };
  665. #else
  666. static const char S_I_T[][3] = {
  667. #ifdef CONFIG_ASH_ALIAS
  668. {CSPCL, CIGN, CIGN}, /* 0, PEOA */
  669. #endif
  670. {CSPCL, CWORD, CWORD}, /* 1, ' ' */
  671. {CNL, CNL, CNL}, /* 2, \n */
  672. {CWORD, CCTL, CCTL}, /* 3, !*-/:=?[]~ */
  673. {CDQUOTE, CENDQUOTE, CWORD}, /* 4, '"' */
  674. {CVAR, CVAR, CWORD}, /* 5, $ */
  675. {CSQUOTE, CWORD, CENDQUOTE}, /* 6, "'" */
  676. {CSPCL, CWORD, CWORD}, /* 7, ( */
  677. {CSPCL, CWORD, CWORD}, /* 8, ) */
  678. {CBACK, CBACK, CCTL}, /* 9, \ */
  679. {CBQUOTE, CBQUOTE, CWORD}, /* 10, ` */
  680. {CENDVAR, CENDVAR, CWORD}, /* 11, } */
  681. #ifndef USE_SIT_FUNCTION
  682. {CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
  683. {CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
  684. {CCTL, CCTL, CCTL} /* 14, CTLESC ... */
  685. #endif
  686. };
  687. #endif /* CONFIG_ASH_MATH_SUPPORT */
  688. #ifdef USE_SIT_FUNCTION
  689. #define U_C(c) ((unsigned char)(c))
  690. static int SIT(int c, int syntax)
  691. {
  692. static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
  693. #ifdef CONFIG_ASH_ALIAS
  694. static const char syntax_index_table[] = {
  695. 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
  696. 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
  697. 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
  698. 11, 3 /* "}~" */
  699. };
  700. #else
  701. static const char syntax_index_table[] = {
  702. 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
  703. 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
  704. 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
  705. 10, 2 /* "}~" */
  706. };
  707. #endif
  708. const char *s;
  709. int indx;
  710. if (c == PEOF) /* 2^8+2 */
  711. return CENDFILE;
  712. #ifdef CONFIG_ASH_ALIAS
  713. if (c == PEOA) /* 2^8+1 */
  714. indx = 0;
  715. else
  716. #endif
  717. if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
  718. return CCTL;
  719. else {
  720. s = strchr(spec_symbls, c);
  721. if (s == 0 || *s == 0)
  722. return CWORD;
  723. indx = syntax_index_table[(s - spec_symbls)];
  724. }
  725. return S_I_T[indx][syntax];
  726. }
  727. #else /* USE_SIT_FUNCTION */
  728. #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
  729. #ifdef CONFIG_ASH_ALIAS
  730. #define CSPCL_CIGN_CIGN_CIGN 0
  731. #define CSPCL_CWORD_CWORD_CWORD 1
  732. #define CNL_CNL_CNL_CNL 2
  733. #define CWORD_CCTL_CCTL_CWORD 3
  734. #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
  735. #define CVAR_CVAR_CWORD_CVAR 5
  736. #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
  737. #define CSPCL_CWORD_CWORD_CLP 7
  738. #define CSPCL_CWORD_CWORD_CRP 8
  739. #define CBACK_CBACK_CCTL_CBACK 9
  740. #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
  741. #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
  742. #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
  743. #define CWORD_CWORD_CWORD_CWORD 13
  744. #define CCTL_CCTL_CCTL_CCTL 14
  745. #else
  746. #define CSPCL_CWORD_CWORD_CWORD 0
  747. #define CNL_CNL_CNL_CNL 1
  748. #define CWORD_CCTL_CCTL_CWORD 2
  749. #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
  750. #define CVAR_CVAR_CWORD_CVAR 4
  751. #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
  752. #define CSPCL_CWORD_CWORD_CLP 6
  753. #define CSPCL_CWORD_CWORD_CRP 7
  754. #define CBACK_CBACK_CCTL_CBACK 8
  755. #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
  756. #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
  757. #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
  758. #define CWORD_CWORD_CWORD_CWORD 12
  759. #define CCTL_CCTL_CCTL_CCTL 13
  760. #endif
  761. static const char syntax_index_table[258] = {
  762. /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
  763. /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
  764. #ifdef CONFIG_ASH_ALIAS
  765. /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
  766. #endif
  767. /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
  768. /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
  769. /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
  770. /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
  771. /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
  772. /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
  773. /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
  774. /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
  775. /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
  776. /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
  777. /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
  778. /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
  779. /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
  780. /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
  781. /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
  782. /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
  783. /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
  784. /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
  785. /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
  786. /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
  787. /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
  788. /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
  789. /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
  790. /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
  791. /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
  792. /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
  793. /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
  794. /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
  795. /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
  796. /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
  797. /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
  798. /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
  799. /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
  800. /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
  801. /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
  802. /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
  803. /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
  804. /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
  805. /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
  806. /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
  807. /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
  808. /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
  809. /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
  810. /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
  811. /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
  812. /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
  813. /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
  814. /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
  815. /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
  816. /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
  817. /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
  818. /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
  819. /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
  820. /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
  821. /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
  822. /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
  823. /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
  824. /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
  825. /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
  826. /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
  827. /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
  828. /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
  829. /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
  830. /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
  831. /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
  832. /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
  833. /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
  834. /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
  835. /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
  836. /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
  837. /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
  838. /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
  839. /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
  840. /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
  841. /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
  842. /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
  843. /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
  844. /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
  845. /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
  846. /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
  847. /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
  848. /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
  849. /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
  850. /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
  851. /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
  852. /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
  853. /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
  854. /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
  855. /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
  856. /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
  857. /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
  858. /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
  859. /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
  860. /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
  861. /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
  862. /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
  863. /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
  864. /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
  865. /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
  866. /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
  867. /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
  868. /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
  869. /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
  870. /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
  871. /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
  872. /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
  873. /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
  874. /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
  875. /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
  876. /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
  877. /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
  878. /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
  879. /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
  880. /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
  881. /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
  882. /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
  883. /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
  884. /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
  885. /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
  886. /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
  887. /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
  888. /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
  889. /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
  890. /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
  891. /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
  892. /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
  893. /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
  894. /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
  895. /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
  896. /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
  897. /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
  898. /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
  899. /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
  900. /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
  901. /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
  902. /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
  903. /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
  904. /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
  905. /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
  906. /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
  907. /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
  908. /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
  909. /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
  910. /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
  911. /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
  912. /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
  913. /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
  914. /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
  915. /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
  916. /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
  917. /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
  918. /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
  919. /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
  920. /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
  921. /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
  922. /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
  923. /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
  924. /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
  925. /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
  926. /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
  927. /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
  928. /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
  929. /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
  930. /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
  931. /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
  932. /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
  933. /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
  934. /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
  935. /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
  936. /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
  937. /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
  938. /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
  939. /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
  940. /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
  941. /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
  942. /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
  943. /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
  944. /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
  945. /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
  946. /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
  947. /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
  948. /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
  949. /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
  950. /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
  951. /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
  952. /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
  953. /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
  954. /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
  955. /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
  956. /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
  957. /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
  958. /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
  959. /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
  960. /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
  961. /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
  962. /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
  963. /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
  964. /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
  965. /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
  966. /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
  967. /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
  968. /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
  969. /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
  970. /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
  971. /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
  972. /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
  973. /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
  974. /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
  975. /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
  976. /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
  977. /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
  978. /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
  979. /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
  980. /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
  981. /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
  982. /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
  983. /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
  984. /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
  985. /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
  986. /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
  987. /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
  988. /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
  989. /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
  990. /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
  991. /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
  992. /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
  993. /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
  994. /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
  995. /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
  996. /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
  997. /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
  998. /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
  999. /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
  1000. /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
  1001. /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
  1002. /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
  1003. /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
  1004. /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
  1005. /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
  1006. /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
  1007. /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
  1008. /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
  1009. /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
  1010. /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
  1011. /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
  1012. /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
  1013. /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
  1014. /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
  1015. /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
  1016. /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
  1017. /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
  1018. /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
  1019. /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
  1020. /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
  1021. /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
  1022. /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
  1023. };
  1024. #endif /* USE_SIT_FUNCTION */
  1025. /* $NetBSD: alias.c,v 1.11 2002/11/24 22:35:38 christos Exp $ */
  1026. #define ATABSIZE 39
  1027. static int funcblocksize; /* size of structures in function */
  1028. static int funcstringsize; /* size of strings in node */
  1029. static pointer funcblock; /* block to allocate function from */
  1030. static char *funcstring; /* block to allocate strings from */
  1031. static const short nodesize[26] = {
  1032. SHELL_ALIGN(sizeof (struct ncmd)),
  1033. SHELL_ALIGN(sizeof (struct npipe)),
  1034. SHELL_ALIGN(sizeof (struct nredir)),
  1035. SHELL_ALIGN(sizeof (struct nredir)),
  1036. SHELL_ALIGN(sizeof (struct nredir)),
  1037. SHELL_ALIGN(sizeof (struct nbinary)),
  1038. SHELL_ALIGN(sizeof (struct nbinary)),
  1039. SHELL_ALIGN(sizeof (struct nbinary)),
  1040. SHELL_ALIGN(sizeof (struct nif)),
  1041. SHELL_ALIGN(sizeof (struct nbinary)),
  1042. SHELL_ALIGN(sizeof (struct nbinary)),
  1043. SHELL_ALIGN(sizeof (struct nfor)),
  1044. SHELL_ALIGN(sizeof (struct ncase)),
  1045. SHELL_ALIGN(sizeof (struct nclist)),
  1046. SHELL_ALIGN(sizeof (struct narg)),
  1047. SHELL_ALIGN(sizeof (struct narg)),
  1048. SHELL_ALIGN(sizeof (struct nfile)),
  1049. SHELL_ALIGN(sizeof (struct nfile)),
  1050. SHELL_ALIGN(sizeof (struct nfile)),
  1051. SHELL_ALIGN(sizeof (struct nfile)),
  1052. SHELL_ALIGN(sizeof (struct nfile)),
  1053. SHELL_ALIGN(sizeof (struct ndup)),
  1054. SHELL_ALIGN(sizeof (struct ndup)),
  1055. SHELL_ALIGN(sizeof (struct nhere)),
  1056. SHELL_ALIGN(sizeof (struct nhere)),
  1057. SHELL_ALIGN(sizeof (struct nnot)),
  1058. };
  1059. static void calcsize(union node *);
  1060. static void sizenodelist(struct nodelist *);
  1061. static union node *copynode(union node *);
  1062. static struct nodelist *copynodelist(struct nodelist *);
  1063. static char *nodesavestr(char *);
  1064. static void evalstring(char *);
  1065. union node; /* BLETCH for ansi C */
  1066. static void evaltree(union node *, int);
  1067. static void evalbackcmd(union node *, struct backcmd *);
  1068. /* in_function returns nonzero if we are currently evaluating a function */
  1069. #define in_function() funcnest
  1070. static int evalskip; /* set if we are skipping commands */
  1071. static int skipcount; /* number of levels to skip */
  1072. static int funcnest; /* depth of function calls */
  1073. /* reasons for skipping commands (see comment on breakcmd routine) */
  1074. #define SKIPBREAK 1
  1075. #define SKIPCONT 2
  1076. #define SKIPFUNC 3
  1077. #define SKIPFILE 4
  1078. /*
  1079. * This file was generated by the mkbuiltins program.
  1080. */
  1081. #ifdef JOBS
  1082. static int bgcmd(int, char **);
  1083. #endif
  1084. static int breakcmd(int, char **);
  1085. static int cdcmd(int, char **);
  1086. #ifdef CONFIG_ASH_CMDCMD
  1087. static int commandcmd(int, char **);
  1088. #endif
  1089. static int dotcmd(int, char **);
  1090. static int evalcmd(int, char **);
  1091. static int execcmd(int, char **);
  1092. static int exitcmd(int, char **);
  1093. static int exportcmd(int, char **);
  1094. static int falsecmd(int, char **);
  1095. #ifdef JOBS
  1096. static int fgcmd(int, char **);
  1097. #endif
  1098. #ifdef CONFIG_ASH_GETOPTS
  1099. static int getoptscmd(int, char **);
  1100. #endif
  1101. static int hashcmd(int, char **);
  1102. #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
  1103. static int helpcmd(int argc, char **argv);
  1104. #endif
  1105. #ifdef JOBS
  1106. static int jobscmd(int, char **);
  1107. #endif
  1108. #ifdef CONFIG_ASH_MATH_SUPPORT
  1109. static int letcmd(int, char **);
  1110. #endif
  1111. static int localcmd(int, char **);
  1112. static int pwdcmd(int, char **);
  1113. static int readcmd(int, char **);
  1114. static int returncmd(int, char **);
  1115. static int setcmd(int, char **);
  1116. static int shiftcmd(int, char **);
  1117. static int timescmd(int, char **);
  1118. static int trapcmd(int, char **);
  1119. static int truecmd(int, char **);
  1120. static int typecmd(int, char **);
  1121. static int umaskcmd(int, char **);
  1122. static int unsetcmd(int, char **);
  1123. static int waitcmd(int, char **);
  1124. static int ulimitcmd(int, char **);
  1125. #ifdef JOBS
  1126. static int killcmd(int, char **);
  1127. #endif
  1128. /* $NetBSD: mail.h,v 1.9 2002/11/24 22:35:40 christos Exp $ */
  1129. #ifdef CONFIG_ASH_MAIL
  1130. static void chkmail(void);
  1131. static void changemail(const char *);
  1132. #endif
  1133. /* $NetBSD: exec.h,v 1.20 2003/01/22 20:36:04 dsl Exp $ */
  1134. /* values of cmdtype */
  1135. #define CMDUNKNOWN -1 /* no entry in table for command */
  1136. #define CMDNORMAL 0 /* command is an executable program */
  1137. #define CMDFUNCTION 1 /* command is a shell function */
  1138. #define CMDBUILTIN 2 /* command is a shell builtin */
  1139. struct builtincmd {
  1140. const char *name;
  1141. int (*builtin)(int, char **);
  1142. /* unsigned flags; */
  1143. };
  1144. #ifdef CONFIG_ASH_CMDCMD
  1145. # ifdef JOBS
  1146. # ifdef CONFIG_ASH_ALIAS
  1147. # define COMMANDCMD (builtincmd + 7)
  1148. # define EXECCMD (builtincmd + 10)
  1149. # else
  1150. # define COMMANDCMD (builtincmd + 6)
  1151. # define EXECCMD (builtincmd + 9)
  1152. # endif
  1153. # else /* ! JOBS */
  1154. # ifdef CONFIG_ASH_ALIAS
  1155. # define COMMANDCMD (builtincmd + 6)
  1156. # define EXECCMD (builtincmd + 9)
  1157. # else
  1158. # define COMMANDCMD (builtincmd + 5)
  1159. # define EXECCMD (builtincmd + 8)
  1160. # endif
  1161. # endif /* JOBS */
  1162. #else /* ! CONFIG_ASH_CMDCMD */
  1163. # ifdef JOBS
  1164. # ifdef CONFIG_ASH_ALIAS
  1165. # define EXECCMD (builtincmd + 9)
  1166. # else
  1167. # define EXECCMD (builtincmd + 8)
  1168. # endif
  1169. # else /* ! JOBS */
  1170. # ifdef CONFIG_ASH_ALIAS
  1171. # define EXECCMD (builtincmd + 8)
  1172. # else
  1173. # define EXECCMD (builtincmd + 7)
  1174. # endif
  1175. # endif /* JOBS */
  1176. #endif /* CONFIG_ASH_CMDCMD */
  1177. #define BUILTIN_NOSPEC "0"
  1178. #define BUILTIN_SPECIAL "1"
  1179. #define BUILTIN_REGULAR "2"
  1180. #define BUILTIN_SPEC_REG "3"
  1181. #define BUILTIN_ASSIGN "4"
  1182. #define BUILTIN_SPEC_ASSG "5"
  1183. #define BUILTIN_REG_ASSG "6"
  1184. #define BUILTIN_SPEC_REG_ASSG "7"
  1185. #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
  1186. #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
  1187. static const struct builtincmd builtincmd[] = {
  1188. { BUILTIN_SPEC_REG ".", dotcmd },
  1189. { BUILTIN_SPEC_REG ":", truecmd },
  1190. #ifdef CONFIG_ASH_ALIAS
  1191. { BUILTIN_REG_ASSG "alias", aliascmd },
  1192. #endif
  1193. #ifdef JOBS
  1194. { BUILTIN_REGULAR "bg", bgcmd },
  1195. #endif
  1196. { BUILTIN_SPEC_REG "break", breakcmd },
  1197. { BUILTIN_REGULAR "cd", cdcmd },
  1198. { BUILTIN_NOSPEC "chdir", cdcmd },
  1199. #ifdef CONFIG_ASH_CMDCMD
  1200. { BUILTIN_REGULAR "command", commandcmd },
  1201. #endif
  1202. { BUILTIN_SPEC_REG "continue", breakcmd },
  1203. { BUILTIN_SPEC_REG "eval", evalcmd },
  1204. { BUILTIN_SPEC_REG "exec", execcmd },
  1205. { BUILTIN_SPEC_REG "exit", exitcmd },
  1206. { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
  1207. { BUILTIN_REGULAR "false", falsecmd },
  1208. #ifdef JOBS
  1209. { BUILTIN_REGULAR "fg", fgcmd },
  1210. #endif
  1211. #ifdef CONFIG_ASH_GETOPTS
  1212. { BUILTIN_REGULAR "getopts", getoptscmd },
  1213. #endif
  1214. { BUILTIN_NOSPEC "hash", hashcmd },
  1215. #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
  1216. { BUILTIN_NOSPEC "help", helpcmd },
  1217. #endif
  1218. #ifdef JOBS
  1219. { BUILTIN_REGULAR "jobs", jobscmd },
  1220. { BUILTIN_REGULAR "kill", killcmd },
  1221. #endif
  1222. #ifdef CONFIG_ASH_MATH_SUPPORT
  1223. { BUILTIN_NOSPEC "let", letcmd },
  1224. #endif
  1225. { BUILTIN_ASSIGN "local", localcmd },
  1226. { BUILTIN_NOSPEC "pwd", pwdcmd },
  1227. { BUILTIN_REGULAR "read", readcmd },
  1228. { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
  1229. { BUILTIN_SPEC_REG "return", returncmd },
  1230. { BUILTIN_SPEC_REG "set", setcmd },
  1231. { BUILTIN_SPEC_REG "shift", shiftcmd },
  1232. { BUILTIN_SPEC_REG "times", timescmd },
  1233. { BUILTIN_SPEC_REG "trap", trapcmd },
  1234. { BUILTIN_REGULAR "true", truecmd },
  1235. { BUILTIN_NOSPEC "type", typecmd },
  1236. { BUILTIN_NOSPEC "ulimit", ulimitcmd },
  1237. { BUILTIN_REGULAR "umask", umaskcmd },
  1238. #ifdef CONFIG_ASH_ALIAS
  1239. { BUILTIN_REGULAR "unalias", unaliascmd },
  1240. #endif
  1241. { BUILTIN_SPEC_REG "unset", unsetcmd },
  1242. { BUILTIN_REGULAR "wait", waitcmd },
  1243. };
  1244. #define NUMBUILTINS (sizeof (builtincmd) / sizeof (struct builtincmd) )
  1245. struct cmdentry {
  1246. int cmdtype;
  1247. union param {
  1248. int index;
  1249. const struct builtincmd *cmd;
  1250. struct funcnode *func;
  1251. } u;
  1252. };
  1253. /* action to find_command() */
  1254. #define DO_ERR 0x01 /* prints errors */
  1255. #define DO_ABS 0x02 /* checks absolute paths */
  1256. #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
  1257. #define DO_ALTPATH 0x08 /* using alternate path */
  1258. #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
  1259. static const char *pathopt; /* set by padvance */
  1260. static void shellexec(char **, const char *, int)
  1261. __attribute__((__noreturn__));
  1262. static char *padvance(const char **, const char *);
  1263. static void find_command(char *, struct cmdentry *, int, const char *);
  1264. static struct builtincmd *find_builtin(const char *);
  1265. static void hashcd(void);
  1266. static void changepath(const char *);
  1267. static void defun(char *, union node *);
  1268. static void unsetfunc(const char *);
  1269. #ifdef CONFIG_ASH_MATH_SUPPORT_64
  1270. typedef int64_t arith_t;
  1271. #else
  1272. typedef long arith_t;
  1273. #endif
  1274. #ifdef CONFIG_ASH_MATH_SUPPORT
  1275. static arith_t dash_arith(const char *);
  1276. static arith_t arith(const char *expr, int *perrcode);
  1277. #endif
  1278. #ifdef CONFIG_ASH_RANDOM_SUPPORT
  1279. static unsigned long rseed;
  1280. static void change_random(const char *);
  1281. # ifndef DYNAMIC_VAR
  1282. # define DYNAMIC_VAR
  1283. # endif
  1284. #endif
  1285. /* $NetBSD: init.h,v 1.9 2002/11/24 22:35:40 christos Exp $ */
  1286. static void reset(void);
  1287. /* $NetBSD: var.h,v 1.21 2003/01/22 20:36:04 dsl Exp $ */
  1288. /*
  1289. * Shell variables.
  1290. */
  1291. /* flags */
  1292. #define VEXPORT 0x01 /* variable is exported */
  1293. #define VREADONLY 0x02 /* variable cannot be modified */
  1294. #define VSTRFIXED 0x04 /* variable struct is statically allocated */
  1295. #define VTEXTFIXED 0x08 /* text is statically allocated */
  1296. #define VSTACK 0x10 /* text is allocated on the stack */
  1297. #define VUNSET 0x20 /* the variable is not set */
  1298. #define VNOFUNC 0x40 /* don't call the callback function */
  1299. #define VNOSET 0x80 /* do not set variable - just readonly test */
  1300. #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
  1301. #ifdef DYNAMIC_VAR
  1302. # define VDYNAMIC 0x200 /* dynamic variable */
  1303. # else
  1304. # define VDYNAMIC 0
  1305. #endif
  1306. struct var {
  1307. struct var *next; /* next entry in hash list */
  1308. int flags; /* flags are defined above */
  1309. const char *text; /* name=value */
  1310. void (*func)(const char *); /* function to be called when */
  1311. /* the variable gets set/unset */
  1312. };
  1313. struct localvar {
  1314. struct localvar *next; /* next local variable in list */
  1315. struct var *vp; /* the variable that was made local */
  1316. int flags; /* saved flags */
  1317. const char *text; /* saved text */
  1318. };
  1319. static struct localvar *localvars;
  1320. /*
  1321. * Shell variables.
  1322. */
  1323. #ifdef CONFIG_ASH_GETOPTS
  1324. static void getoptsreset(const char *);
  1325. #endif
  1326. #ifdef CONFIG_LOCALE_SUPPORT
  1327. #include <locale.h>
  1328. static void change_lc_all(const char *value);
  1329. static void change_lc_ctype(const char *value);
  1330. #endif
  1331. #define VTABSIZE 39
  1332. static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
  1333. #ifdef IFS_BROKEN
  1334. static const char defifsvar[] = "IFS= \t\n";
  1335. #define defifs (defifsvar + 4)
  1336. #else
  1337. static const char defifs[] = " \t\n";
  1338. #endif
  1339. static struct var varinit[] = {
  1340. #ifdef IFS_BROKEN
  1341. { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },
  1342. #else
  1343. { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },
  1344. #endif
  1345. #ifdef CONFIG_ASH_MAIL
  1346. { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
  1347. { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
  1348. #endif
  1349. { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
  1350. { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 },
  1351. { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 },
  1352. { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },
  1353. #ifdef CONFIG_ASH_GETOPTS
  1354. { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
  1355. #endif
  1356. #ifdef CONFIG_ASH_RANDOM_SUPPORT
  1357. {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
  1358. #endif
  1359. #ifdef CONFIG_LOCALE_SUPPORT
  1360. {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
  1361. {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
  1362. #endif
  1363. #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
  1364. {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
  1365. #endif
  1366. };
  1367. #define vifs varinit[0]
  1368. #ifdef CONFIG_ASH_MAIL
  1369. #define vmail (&vifs)[1]
  1370. #define vmpath (&vmail)[1]
  1371. #else
  1372. #define vmpath vifs
  1373. #endif
  1374. #define vpath (&vmpath)[1]
  1375. #define vps1 (&vpath)[1]
  1376. #define vps2 (&vps1)[1]
  1377. #define vps4 (&vps2)[1]
  1378. #define voptind (&vps4)[1]
  1379. #ifdef CONFIG_ASH_GETOPTS
  1380. #define vrandom (&voptind)[1]
  1381. #else
  1382. #define vrandom (&vps4)[1]
  1383. #endif
  1384. #define defpath (defpathvar + 5)
  1385. /*
  1386. * The following macros access the values of the above variables.
  1387. * They have to skip over the name. They return the null string
  1388. * for unset variables.
  1389. */
  1390. #define ifsval() (vifs.text + 4)
  1391. #define ifsset() ((vifs.flags & VUNSET) == 0)
  1392. #define mailval() (vmail.text + 5)
  1393. #define mpathval() (vmpath.text + 9)
  1394. #define pathval() (vpath.text + 5)
  1395. #define ps1val() (vps1.text + 4)
  1396. #define ps2val() (vps2.text + 4)
  1397. #define ps4val() (vps4.text + 4)
  1398. #define optindval() (voptind.text + 7)
  1399. #define mpathset() ((vmpath.flags & VUNSET) == 0)
  1400. static void setvar(const char *, const char *, int);
  1401. static void setvareq(char *, int);
  1402. static void listsetvar(struct strlist *, int);
  1403. static char *lookupvar(const char *);
  1404. static char *bltinlookup(const char *);
  1405. static char **listvars(int, int, char ***);
  1406. #define environment() listvars(VEXPORT, VUNSET, 0)
  1407. static int showvars(const char *, int, int);
  1408. static void poplocalvars(void);
  1409. static int unsetvar(const char *);
  1410. #ifdef CONFIG_ASH_GETOPTS
  1411. static int setvarsafe(const char *, const char *, int);
  1412. #endif
  1413. static int varcmp(const char *, const char *);
  1414. static struct var **hashvar(const char *);
  1415. static inline int varequal(const char *a, const char *b) {
  1416. return !varcmp(a, b);
  1417. }
  1418. static int loopnest; /* current loop nesting level */
  1419. /*
  1420. * The parsefile structure pointed to by the global variable parsefile
  1421. * contains information about the current file being read.
  1422. */
  1423. struct redirtab {
  1424. struct redirtab *next;
  1425. int renamed[10];
  1426. int nullredirs;
  1427. };
  1428. static struct redirtab *redirlist;
  1429. static int nullredirs;
  1430. extern char **environ;
  1431. /* $NetBSD: output.h,v 1.16 2002/11/24 22:35:42 christos Exp $ */
  1432. static void outstr(const char *, FILE *);
  1433. static void outcslow(int, FILE *);
  1434. static void flushall(void);
  1435. static void flusherr(void);
  1436. static int out1fmt(const char *, ...)
  1437. __attribute__((__format__(__printf__,1,2)));
  1438. static int fmtstr(char *, size_t, const char *, ...)
  1439. __attribute__((__format__(__printf__,3,4)));
  1440. static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
  1441. static void out1str(const char *p)
  1442. {
  1443. outstr(p, stdout);
  1444. }
  1445. static void out2str(const char *p)
  1446. {
  1447. outstr(p, stderr);
  1448. flusherr();
  1449. }
  1450. /*
  1451. * Initialization code.
  1452. */
  1453. /*
  1454. * This routine initializes the builtin variables.
  1455. */
  1456. static inline void
  1457. initvar(void)
  1458. {
  1459. struct var *vp;
  1460. struct var *end;
  1461. struct var **vpp;
  1462. /*
  1463. * PS1 depends on uid
  1464. */
  1465. #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
  1466. vps1.text = "PS1=\\w \\$ ";
  1467. #else
  1468. if (!geteuid())
  1469. vps1.text = "PS1=# ";
  1470. #endif
  1471. vp = varinit;
  1472. end = vp + sizeof(varinit) / sizeof(varinit[0]);
  1473. do {
  1474. vpp = hashvar(vp->text);
  1475. vp->next = *vpp;
  1476. *vpp = vp;
  1477. } while (++vp < end);
  1478. }
  1479. static inline void
  1480. init(void)
  1481. {
  1482. /* from input.c: */
  1483. {
  1484. basepf.nextc = basepf.buf = basebuf;
  1485. }
  1486. /* from trap.c: */
  1487. {
  1488. signal(SIGCHLD, SIG_DFL);
  1489. }
  1490. /* from var.c: */
  1491. {
  1492. char **envp;
  1493. char ppid[32];
  1494. initvar();
  1495. for (envp = environ ; *envp ; envp++) {
  1496. if (strchr(*envp, '=')) {
  1497. setvareq(*envp, VEXPORT|VTEXTFIXED);
  1498. }
  1499. }
  1500. snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
  1501. setvar("PPID", ppid, 0);
  1502. setpwd(0, 0);
  1503. }
  1504. }
  1505. /* PEOF (the end of file marker) */
  1506. /*
  1507. * The input line number. Input.c just defines this variable, and saves
  1508. * and restores it when files are pushed and popped. The user of this
  1509. * package must set its value.
  1510. */
  1511. static int pgetc(void);
  1512. static int pgetc2(void);
  1513. static int preadbuffer(void);
  1514. static void pungetc(void);
  1515. static void pushstring(char *, void *);
  1516. static void popstring(void);
  1517. static void setinputfile(const char *, int);
  1518. static void setinputfd(int, int);
  1519. static void setinputstring(char *);
  1520. static void popfile(void);
  1521. static void popallfiles(void);
  1522. static void closescript(void);
  1523. /* $NetBSD: jobs.h,v 1.17 2003/01/22 20:36:04 dsl Exp $ */
  1524. /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
  1525. #define FORK_FG 0
  1526. #define FORK_BG 1
  1527. #define FORK_NOJOB 2
  1528. /* mode flags for showjob(s) */
  1529. #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
  1530. #define SHOW_PID 0x04 /* include process pid */
  1531. #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
  1532. /*
  1533. * A job structure contains information about a job. A job is either a
  1534. * single process or a set of processes contained in a pipeline. In the
  1535. * latter case, pidlist will be non-NULL, and will point to a -1 terminated
  1536. * array of pids.
  1537. */
  1538. struct procstat {
  1539. pid_t pid; /* process id */
  1540. int status; /* last process status from wait() */
  1541. char *cmd; /* text of command being run */
  1542. };
  1543. struct job {
  1544. struct procstat ps0; /* status of process */
  1545. struct procstat *ps; /* status or processes when more than one */
  1546. #if JOBS
  1547. int stopstatus; /* status of a stopped job */
  1548. #endif
  1549. uint32_t
  1550. nprocs: 16, /* number of processes */
  1551. state: 8,
  1552. #define JOBRUNNING 0 /* at least one proc running */
  1553. #define JOBSTOPPED 1 /* all procs are stopped */
  1554. #define JOBDONE 2 /* all procs are completed */
  1555. #if JOBS
  1556. sigint: 1, /* job was killed by SIGINT */
  1557. jobctl: 1, /* job running under job control */
  1558. #endif
  1559. waited: 1, /* true if this entry has been waited for */
  1560. used: 1, /* true if this entry is in used */
  1561. changed: 1; /* true if status has changed */
  1562. struct job *prev_job; /* previous job */
  1563. };
  1564. static pid_t backgndpid; /* pid of last background process */
  1565. static int job_warning; /* user was warned about stopped jobs */
  1566. #if JOBS
  1567. static int jobctl; /* true if doing job control */
  1568. #endif
  1569. static struct job *makejob(union node *, int);
  1570. static int forkshell(struct job *, union node *, int);
  1571. static int waitforjob(struct job *);
  1572. static int stoppedjobs(void);
  1573. #if ! JOBS
  1574. #define setjobctl(on) /* do nothing */
  1575. #else
  1576. static void setjobctl(int);
  1577. static void showjobs(FILE *, int);
  1578. #endif
  1579. /* $NetBSD: main.h,v 1.9 2002/11/24 22:35:41 christos Exp $ */
  1580. /* pid of main shell */
  1581. static int rootpid;
  1582. /* true if we aren't a child of the main shell */
  1583. static int rootshell;
  1584. static void readcmdfile(char *);
  1585. static void cmdloop(int);
  1586. /* $NetBSD: memalloc.h,v 1.13 2003/01/22 20:36:04 dsl Exp $ */
  1587. struct stackmark {
  1588. struct stack_block *stackp;
  1589. char *stacknxt;
  1590. size_t stacknleft;
  1591. struct stackmark *marknext;
  1592. };
  1593. /* minimum size of a block */
  1594. #define MINSIZE SHELL_ALIGN(504)
  1595. struct stack_block {
  1596. struct stack_block *prev;
  1597. char space[MINSIZE];
  1598. };
  1599. static struct stack_block stackbase;
  1600. static struct stack_block *stackp = &stackbase;
  1601. static struct stackmark *markp;
  1602. static char *stacknxt = stackbase.space;
  1603. static size_t stacknleft = MINSIZE;
  1604. static char *sstrend = stackbase.space + MINSIZE;
  1605. static int herefd = -1;
  1606. static pointer ckmalloc(size_t);
  1607. static pointer ckrealloc(pointer, size_t);
  1608. static char *savestr(const char *);
  1609. static pointer stalloc(size_t);
  1610. static void stunalloc(pointer);
  1611. static void setstackmark(struct stackmark *);
  1612. static void popstackmark(struct stackmark *);
  1613. static void growstackblock(void);
  1614. static void *growstackstr(void);
  1615. static char *makestrspace(size_t, char *);
  1616. static char *stnputs(const char *, size_t, char *);
  1617. static char *stputs(const char *, char *);
  1618. static inline char *_STPUTC(char c, char *p) {
  1619. if (p == sstrend)
  1620. p = growstackstr();
  1621. *p++ = c;
  1622. return p;
  1623. }
  1624. #define stackblock() ((void *)stacknxt)
  1625. #define stackblocksize() stacknleft
  1626. #define STARTSTACKSTR(p) ((p) = stackblock())
  1627. #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
  1628. #define CHECKSTRSPACE(n, p) \
  1629. ({ \
  1630. char *q = (p); \
  1631. size_t l = (n); \
  1632. size_t m = sstrend - q; \
  1633. if (l > m) \
  1634. (p) = makestrspace(l, q); \
  1635. 0; \
  1636. })
  1637. #define USTPUTC(c, p) (*p++ = (c))
  1638. #define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
  1639. #define STUNPUTC(p) (--p)
  1640. #define STTOPC(p) p[-1]
  1641. #define STADJUST(amount, p) (p += (amount))
  1642. #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
  1643. #define ungrabstackstr(s, p) stunalloc((s))
  1644. #define stackstrend() ((void *)sstrend)
  1645. #define ckfree(p) free((pointer)(p))
  1646. /* $NetBSD: mystring.h,v 1.10 2002/11/24 22:35:42 christos Exp $ */
  1647. #define DOLATSTRLEN 4
  1648. static char *prefix(const char *, const char *);
  1649. static int number(const char *);
  1650. static int is_number(const char *);
  1651. static char *single_quote(const char *);
  1652. static char *sstrdup(const char *);
  1653. #define equal(s1, s2) (strcmp(s1, s2) == 0)
  1654. #define scopy(s1, s2) ((void)strcpy(s2, s1))
  1655. /* $NetBSD: options.h,v 1.16 2003/01/22 20:36:04 dsl Exp $ */
  1656. struct shparam {
  1657. int nparam; /* # of positional parameters (without $0) */
  1658. unsigned char malloc; /* if parameter list dynamically allocated */
  1659. char **p; /* parameter list */
  1660. #ifdef CONFIG_ASH_GETOPTS
  1661. int optind; /* next parameter to be processed by getopts */
  1662. int optoff; /* used by getopts */
  1663. #endif
  1664. };
  1665. #define eflag optlist[0]
  1666. #define fflag optlist[1]
  1667. #define Iflag optlist[2]
  1668. #define iflag optlist[3]
  1669. #define mflag optlist[4]
  1670. #define nflag optlist[5]
  1671. #define sflag optlist[6]
  1672. #define xflag optlist[7]
  1673. #define vflag optlist[8]
  1674. #define Cflag optlist[9]
  1675. #define aflag optlist[10]
  1676. #define bflag optlist[11]
  1677. #define uflag optlist[12]
  1678. #define qflag optlist[13]
  1679. #ifdef DEBUG
  1680. #define nolog optlist[14]
  1681. #define debug optlist[15]
  1682. #define NOPTS 16
  1683. #else
  1684. #define NOPTS 14
  1685. #endif
  1686. /* $NetBSD: options.c,v 1.33 2003/01/22 20:36:04 dsl Exp $ */
  1687. static const char *const optletters_optnames[NOPTS] = {
  1688. "e" "errexit",
  1689. "f" "noglob",
  1690. "I" "ignoreeof",
  1691. "i" "interactive",
  1692. "m" "monitor",
  1693. "n" "noexec",
  1694. "s" "stdin",
  1695. "x" "xtrace",
  1696. "v" "verbose",
  1697. "C" "noclobber",
  1698. "a" "allexport",
  1699. "b" "notify",
  1700. "u" "nounset",
  1701. "q" "quietprofile",
  1702. #ifdef DEBUG
  1703. "\0" "nolog",
  1704. "\0" "debug",
  1705. #endif
  1706. };
  1707. #define optletters(n) optletters_optnames[(n)][0]
  1708. #define optnames(n) (&optletters_optnames[(n)][1])
  1709. static char optlist[NOPTS];
  1710. static char *arg0; /* value of $0 */
  1711. static struct shparam shellparam; /* $@ current positional parameters */
  1712. static char **argptr; /* argument list for builtin commands */
  1713. static char *optionarg; /* set by nextopt (like getopt) */
  1714. static char *optptr; /* used by nextopt */
  1715. static char *minusc; /* argument to -c option */
  1716. static void procargs(int, char **);
  1717. static void optschanged(void);
  1718. static void setparam(char **);
  1719. static void freeparam(volatile struct shparam *);
  1720. static int shiftcmd(int, char **);
  1721. static int setcmd(int, char **);
  1722. static int nextopt(const char *);
  1723. /* $NetBSD: redir.h,v 1.14 2002/11/24 22:35:43 christos Exp $ */
  1724. /* flags passed to redirect */
  1725. #define REDIR_PUSH 01 /* save previous values of file descriptors */
  1726. #define REDIR_SAVEFD2 03 /* set preverrout */
  1727. union node;
  1728. static void redirect(union node *, int);
  1729. static void popredir(int);
  1730. static void clearredir(int);
  1731. static int copyfd(int, int);
  1732. static int redirectsafe(union node *, int);
  1733. /* $NetBSD: show.h,v 1.6 2003/01/22 20:36:04 dsl Exp $ */
  1734. #ifdef DEBUG
  1735. static void showtree(union node *);
  1736. static void trace(const char *, ...);
  1737. static void tracev(const char *, va_list);
  1738. static void trargs(char **);
  1739. static void trputc(int);
  1740. static void trputs(const char *);
  1741. static void opentrace(void);
  1742. #endif
  1743. /* $NetBSD: trap.h,v 1.16 2002/11/24 22:35:43 christos Exp $ */
  1744. /* trap handler commands */
  1745. static char *trap[NSIG];
  1746. /* current value of signal */
  1747. static char sigmode[NSIG - 1];
  1748. /* indicates specified signal received */
  1749. static char gotsig[NSIG - 1];
  1750. static void clear_traps(void);
  1751. static void setsignal(int);
  1752. static void ignoresig(int);
  1753. static void onsig(int);
  1754. static void dotrap(void);
  1755. static void setinteractive(int);
  1756. static void exitshell(void) __attribute__((__noreturn__));
  1757. static int decode_signal(const char *, int);
  1758. /*
  1759. * This routine is called when an error or an interrupt occurs in an
  1760. * interactive shell and control is returned to the main command loop.
  1761. */
  1762. static void
  1763. reset(void)
  1764. {
  1765. /* from eval.c: */
  1766. {
  1767. evalskip = 0;
  1768. loopnest = 0;
  1769. funcnest = 0;
  1770. }
  1771. /* from input.c: */
  1772. {
  1773. parselleft = parsenleft = 0; /* clear input buffer */
  1774. popallfiles();
  1775. }
  1776. /* from parser.c: */
  1777. {
  1778. tokpushback = 0;
  1779. checkkwd = 0;
  1780. }
  1781. /* from redir.c: */
  1782. {
  1783. clearredir(0);
  1784. }
  1785. }
  1786. #ifdef CONFIG_ASH_ALIAS
  1787. static struct alias *atab[ATABSIZE];
  1788. static void setalias(const char *, const char *);
  1789. static struct alias *freealias(struct alias *);
  1790. static struct alias **__lookupalias(const char *);
  1791. static void
  1792. setalias(const char *name, const char *val)
  1793. {
  1794. struct alias *ap, **app;
  1795. app = __lookupalias(name);
  1796. ap = *app;
  1797. INTOFF;
  1798. if (ap) {
  1799. if (!(ap->flag & ALIASINUSE)) {
  1800. ckfree(ap->val);
  1801. }
  1802. ap->val = savestr(val);
  1803. ap->flag &= ~ALIASDEAD;
  1804. } else {
  1805. /* not found */
  1806. ap = ckmalloc(sizeof (struct alias));
  1807. ap->name = savestr(name);
  1808. ap->val = savestr(val);
  1809. ap->flag = 0;
  1810. ap->next = 0;
  1811. *app = ap;
  1812. }
  1813. INTON;
  1814. }
  1815. static int
  1816. unalias(const char *name)
  1817. {
  1818. struct alias **app;
  1819. app = __lookupalias(name);
  1820. if (*app) {
  1821. INTOFF;
  1822. *app = freealias(*app);
  1823. INTON;
  1824. return (0);
  1825. }
  1826. return (1);
  1827. }
  1828. static void
  1829. rmaliases(void)
  1830. {
  1831. struct alias *ap, **app;
  1832. int i;
  1833. INTOFF;
  1834. for (i = 0; i < ATABSIZE; i++) {
  1835. app = &atab[i];
  1836. for (ap = *app; ap; ap = *app) {
  1837. *app = freealias(*app);
  1838. if (ap == *app) {
  1839. app = &ap->next;
  1840. }
  1841. }
  1842. }
  1843. INTON;
  1844. }
  1845. static struct alias *
  1846. lookupalias(const char *name, int check)
  1847. {
  1848. struct alias *ap = *__lookupalias(name);
  1849. if (check && ap && (ap->flag & ALIASINUSE))
  1850. return (NULL);
  1851. return (ap);
  1852. }
  1853. /*
  1854. * TODO - sort output
  1855. */
  1856. static int
  1857. aliascmd(int argc, char **argv)
  1858. {
  1859. char *n, *v;
  1860. int ret = 0;
  1861. struct alias *ap;
  1862. if (argc == 1) {
  1863. int i;
  1864. for (i = 0; i < ATABSIZE; i++)
  1865. for (ap = atab[i]; ap; ap = ap->next) {
  1866. printalias(ap);
  1867. }
  1868. return (0);
  1869. }
  1870. while ((n = *++argv) != NULL) {
  1871. if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
  1872. if ((ap = *__lookupalias(n)) == NULL) {
  1873. fprintf(stderr, "%s: %s not found\n", "alias", n);
  1874. ret = 1;
  1875. } else
  1876. printalias(ap);
  1877. } else {
  1878. *v++ = '\0';
  1879. setalias(n, v);
  1880. }
  1881. }
  1882. return (ret);
  1883. }
  1884. static int
  1885. unaliascmd(int argc, char **argv)
  1886. {
  1887. int i;
  1888. while ((i = nextopt("a")) != '\0') {
  1889. if (i == 'a') {
  1890. rmaliases();
  1891. return (0);
  1892. }
  1893. }
  1894. for (i = 0; *argptr; argptr++) {
  1895. if (unalias(*argptr)) {
  1896. fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
  1897. i = 1;
  1898. }
  1899. }
  1900. return (i);
  1901. }
  1902. static struct alias *
  1903. freealias(struct alias *ap) {
  1904. struct alias *next;
  1905. if (ap->flag & ALIASINUSE) {
  1906. ap->flag |= ALIASDEAD;
  1907. return ap;
  1908. }
  1909. next = ap->next;
  1910. ckfree(ap->name);
  1911. ckfree(ap->val);
  1912. ckfree(ap);
  1913. return next;
  1914. }
  1915. static void
  1916. printalias(const struct alias *ap) {
  1917. out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
  1918. }
  1919. static struct alias **
  1920. __lookupalias(const char *name) {
  1921. unsigned int hashval;
  1922. struct alias **app;
  1923. const char *p;
  1924. unsigned int ch;
  1925. p = name;
  1926. ch = (unsigned char)*p;
  1927. hashval = ch << 4;
  1928. while (ch) {
  1929. hashval += ch;
  1930. ch = (unsigned char)*++p;
  1931. }
  1932. app = &atab[hashval % ATABSIZE];
  1933. for (; *app; app = &(*app)->next) {
  1934. if (equal(name, (*app)->name)) {
  1935. break;
  1936. }
  1937. }
  1938. return app;
  1939. }
  1940. #endif /* CONFIG_ASH_ALIAS */
  1941. /* $NetBSD: cd.c,v 1.30 2003/01/22 20:36:03 dsl Exp $ */
  1942. /*
  1943. * The cd and pwd commands.
  1944. */
  1945. #define CD_PHYSICAL 1
  1946. #define CD_PRINT 2
  1947. static int docd(const char *, int);
  1948. static int cdopt(void);
  1949. static char *curdir = nullstr; /* current working directory */
  1950. static char *physdir = nullstr; /* physical working directory */
  1951. static int
  1952. cdopt(void)
  1953. {
  1954. int flags = 0;
  1955. int i, j;
  1956. j = 'L';
  1957. while ((i = nextopt("LP"))) {
  1958. if (i != j) {
  1959. flags ^= CD_PHYSICAL;
  1960. j = i;
  1961. }
  1962. }
  1963. return flags;
  1964. }
  1965. static int
  1966. cdcmd(int argc, char **argv)
  1967. {
  1968. const char *dest;
  1969. const char *path;
  1970. const char *p;
  1971. char c;
  1972. struct stat statb;
  1973. int flags;
  1974. flags = cdopt();
  1975. dest = *argptr;
  1976. if (!dest)
  1977. dest = bltinlookup(homestr);
  1978. else if (dest[0] == '-' && dest[1] == '\0') {
  1979. dest = bltinlookup("OLDPWD");
  1980. if ( !dest ) goto out;
  1981. flags |= CD_PRINT;
  1982. goto step7;
  1983. }
  1984. if (!dest)
  1985. dest = nullstr;
  1986. if (*dest == '/')
  1987. goto step7;
  1988. if (*dest == '.') {
  1989. c = dest[1];
  1990. dotdot:
  1991. switch (c) {
  1992. case '\0':
  1993. case '/':
  1994. goto step6;
  1995. case '.':
  1996. c = dest[2];
  1997. if (c != '.')
  1998. goto dotdot;
  1999. }
  2000. }
  2001. if (!*dest)
  2002. dest = ".";
  2003. if (!(path = bltinlookup("CDPATH"))) {
  2004. step6:
  2005. step7:
  2006. p = dest;
  2007. goto docd;
  2008. }
  2009. do {
  2010. c = *path;
  2011. p = padvance(&path, dest);
  2012. if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
  2013. if (c && c != ':')
  2014. flags |= CD_PRINT;
  2015. docd:
  2016. if (!docd(p, flags))
  2017. goto out;
  2018. break;
  2019. }
  2020. } while (path);
  2021. error("can't cd to %s", dest);
  2022. /* NOTREACHED */
  2023. out:
  2024. if (flags & CD_PRINT)
  2025. out1fmt(snlfmt, curdir);
  2026. return 0;
  2027. }
  2028. /*
  2029. * Update curdir (the name of the current directory) in response to a
  2030. * cd command.
  2031. */
  2032. static inline const char *
  2033. updatepwd(const char *dir)
  2034. {
  2035. char *new;
  2036. char *p;
  2037. char *cdcomppath;
  2038. const char *lim;
  2039. cdcomppath = sstrdup(dir);
  2040. STARTSTACKSTR(new);
  2041. if (*dir != '/') {
  2042. if (curdir == nullstr)
  2043. return 0;
  2044. new = stputs(curdir, new);
  2045. }
  2046. new = makestrspace(strlen(dir) + 2, new);
  2047. lim = stackblock() + 1;
  2048. if (*dir != '/') {
  2049. if (new[-1] != '/')
  2050. USTPUTC('/', new);
  2051. if (new > lim && *lim == '/')
  2052. lim++;
  2053. } else {
  2054. USTPUTC('/', new);
  2055. cdcomppath++;
  2056. if (dir[1] == '/' && dir[2] != '/') {
  2057. USTPUTC('/', new);
  2058. cdcomppath++;
  2059. lim++;
  2060. }
  2061. }
  2062. p = strtok(cdcomppath, "/");
  2063. while (p) {
  2064. switch(*p) {
  2065. case '.':
  2066. if (p[1] == '.' && p[2] == '\0') {
  2067. while (new > lim) {
  2068. STUNPUTC(new);
  2069. if (new[-1] == '/')
  2070. break;
  2071. }
  2072. break;
  2073. } else if (p[1] == '\0')
  2074. break;
  2075. /* fall through */
  2076. default:
  2077. new = stputs(p, new);
  2078. USTPUTC('/', new);
  2079. }
  2080. p = strtok(0, "/");
  2081. }
  2082. if (new > lim)
  2083. STUNPUTC(new);
  2084. *new = 0;
  2085. return stackblock();
  2086. }
  2087. /*
  2088. * Actually do the chdir. We also call hashcd to let the routines in exec.c
  2089. * know that the current directory has changed.
  2090. */
  2091. static int
  2092. docd(const char *dest, int flags)
  2093. {
  2094. const char *dir = 0;
  2095. int err;
  2096. TRACE(("docd(\"%s\", %d) called\n", dest, flags));
  2097. INTOFF;
  2098. if (!(flags & CD_PHYSICAL)) {
  2099. dir = updatepwd(dest);
  2100. if (dir)
  2101. dest = dir;
  2102. }
  2103. err = chdir(dest);
  2104. if (err)
  2105. goto out;
  2106. setpwd(dir, 1);
  2107. hashcd();
  2108. out:
  2109. INTON;
  2110. return err;
  2111. }
  2112. /*
  2113. * Find out what the current directory is. If we already know the current
  2114. * directory, this routine returns immediately.
  2115. */
  2116. static inline char *
  2117. getpwd(void)
  2118. {
  2119. char *dir = getcwd(0, 0);
  2120. return dir ? dir : nullstr;
  2121. }
  2122. static int
  2123. pwdcmd(int argc, char **argv)
  2124. {
  2125. int flags;
  2126. const char *dir = curdir;
  2127. flags = cdopt();
  2128. if (flags) {
  2129. if (physdir == nullstr)
  2130. setpwd(dir, 0);
  2131. dir = physdir;
  2132. }
  2133. out1fmt(snlfmt, dir);
  2134. return 0;
  2135. }
  2136. static void
  2137. setpwd(const char *val, int setold)
  2138. {
  2139. char *oldcur, *dir;
  2140. oldcur = dir = curdir;
  2141. if (setold) {
  2142. setvar("OLDPWD", oldcur, VEXPORT);
  2143. }
  2144. INTOFF;
  2145. if (physdir != nullstr) {
  2146. if (physdir != oldcur)
  2147. free(physdir);
  2148. physdir = nullstr;
  2149. }
  2150. if (oldcur == val || !val) {
  2151. char *s = getpwd();
  2152. physdir = s;
  2153. if (!val)
  2154. dir = s;
  2155. } else
  2156. dir = savestr(val);
  2157. if (oldcur != dir && oldcur != nullstr) {
  2158. free(oldcur);
  2159. }
  2160. curdir = dir;
  2161. INTON;
  2162. setvar("PWD", dir, VEXPORT);
  2163. }
  2164. /* $NetBSD: error.c,v 1.30 2003/01/22 20:36:03 dsl Exp $ */
  2165. /*
  2166. * Errors and exceptions.
  2167. */
  2168. /*
  2169. * Code to handle exceptions in C.
  2170. */
  2171. static void exverror(int, const char *, va_list)
  2172. __attribute__((__noreturn__));
  2173. /*
  2174. * Called to raise an exception. Since C doesn't include exceptions, we
  2175. * just do a longjmp to the exception handler. The type of exception is
  2176. * stored in the global variable "exception".
  2177. */
  2178. static void
  2179. exraise(int e)
  2180. {
  2181. #ifdef DEBUG
  2182. if (handler == NULL)
  2183. abort();
  2184. #endif
  2185. INTOFF;
  2186. exception = e;
  2187. longjmp(handler->loc, 1);
  2188. }
  2189. /*
  2190. * Called from trap.c when a SIGINT is received. (If the user specifies
  2191. * that SIGINT is to be trapped or ignored using the trap builtin, then
  2192. * this routine is not called.) Suppressint is nonzero when interrupts
  2193. * are held using the INTOFF macro. (The test for iflag is just
  2194. * defensive programming.)
  2195. */
  2196. static void
  2197. onint(void) {
  2198. int i;
  2199. intpending = 0;
  2200. sigsetmask(0);
  2201. i = EXSIG;
  2202. if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
  2203. if (!(rootshell && iflag)) {
  2204. signal(SIGINT, SIG_DFL);
  2205. raise(SIGINT);
  2206. }
  2207. i = EXINT;
  2208. }
  2209. exraise(i);
  2210. /* NOTREACHED */
  2211. }
  2212. static void
  2213. exvwarning(const char *msg, va_list ap)
  2214. {
  2215. FILE *errs;
  2216. const char *name;
  2217. const char *fmt;
  2218. errs = stderr;
  2219. name = arg0;
  2220. fmt = "%s: ";
  2221. if (commandname) {
  2222. name = commandname;
  2223. fmt = "%s: %d: ";
  2224. }
  2225. fprintf(errs, fmt, name, startlinno);
  2226. vfprintf(errs, msg, ap);
  2227. outcslow('\n', errs);
  2228. }
  2229. /*
  2230. * Exverror is called to raise the error exception. If the second argument
  2231. * is not NULL then error prints an error message using printf style
  2232. * formatting. It then raises the error exception.
  2233. */
  2234. static void
  2235. exverror(int cond, const char *msg, va_list ap)
  2236. {
  2237. #ifdef DEBUG
  2238. if (msg) {
  2239. TRACE(("exverror(%d, \"", cond));
  2240. TRACEV((msg, ap));
  2241. TRACE(("\") pid=%d\n", getpid()));
  2242. } else
  2243. TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
  2244. if (msg)
  2245. #endif
  2246. exvwarning(msg, ap);
  2247. flushall();
  2248. exraise(cond);
  2249. /* NOTREACHED */
  2250. }
  2251. static void
  2252. error(const char *msg, ...)
  2253. {
  2254. va_list ap;
  2255. va_start(ap, msg);
  2256. exverror(EXERROR, msg, ap);
  2257. /* NOTREACHED */
  2258. va_end(ap);
  2259. }
  2260. static void
  2261. exerror(int cond, const char *msg, ...)
  2262. {
  2263. va_list ap;
  2264. va_start(ap, msg);
  2265. exverror(cond, msg, ap);
  2266. /* NOTREACHED */
  2267. va_end(ap);
  2268. }
  2269. /*
  2270. * error/warning routines for external builtins
  2271. */
  2272. static void
  2273. sh_warnx(const char *fmt, ...)
  2274. {
  2275. va_list ap;
  2276. va_start(ap, fmt);
  2277. exvwarning(fmt, ap);
  2278. va_end(ap);
  2279. }
  2280. /*
  2281. * Return a string describing an error. The returned string may be a
  2282. * pointer to a static buffer that will be overwritten on the next call.
  2283. * Action describes the operation that got the error.
  2284. */
  2285. static const char *
  2286. errmsg(int e, const char *em)
  2287. {
  2288. if(e == ENOENT || e == ENOTDIR) {
  2289. return em;
  2290. }
  2291. return strerror(e);
  2292. }
  2293. /* $NetBSD: eval.c,v 1.71 2003/01/23 03:33:16 rafal Exp $ */
  2294. /*
  2295. * Evaluate a command.
  2296. */
  2297. /* flags in argument to evaltree */
  2298. #define EV_EXIT 01 /* exit after evaluating tree */
  2299. #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
  2300. #define EV_BACKCMD 04 /* command executing within back quotes */
  2301. static void evalloop(union node *, int);
  2302. static void evalfor(union node *, int);
  2303. static void evalcase(union node *, int);
  2304. static void evalsubshell(union node *, int);
  2305. static void expredir(union node *);
  2306. static void evalpipe(union node *, int);
  2307. static void evalcommand(union node *, int);
  2308. static int evalbltin(const struct builtincmd *, int, char **);
  2309. static int evalfun(struct funcnode *, int, char **, int);
  2310. static void prehash(union node *);
  2311. static int bltincmd(int, char **);
  2312. static const struct builtincmd bltin = {
  2313. "\0\0", bltincmd
  2314. };
  2315. /*
  2316. * Called to reset things after an exception.
  2317. */
  2318. /*
  2319. * The eval command.
  2320. */
  2321. static int
  2322. evalcmd(int argc, char **argv)
  2323. {
  2324. char *p;
  2325. char *concat;
  2326. char **ap;
  2327. if (argc > 1) {
  2328. p = argv[1];
  2329. if (argc > 2) {
  2330. STARTSTACKSTR(concat);
  2331. ap = argv + 2;
  2332. for (;;) {
  2333. concat = stputs(p, concat);
  2334. if ((p = *ap++) == NULL)
  2335. break;
  2336. STPUTC(' ', concat);
  2337. }
  2338. STPUTC('\0', concat);
  2339. p = grabstackstr(concat);
  2340. }
  2341. evalstring(p);
  2342. }
  2343. return exitstatus;
  2344. }
  2345. /*
  2346. * Execute a command or commands contained in a string.
  2347. */
  2348. static void
  2349. evalstring(char *s)
  2350. {
  2351. union node *n;
  2352. struct stackmark smark;
  2353. setstackmark(&smark);
  2354. setinputstring(s);
  2355. while ((n = parsecmd(0)) != NEOF) {
  2356. evaltree(n, 0);
  2357. popstackmark(&smark);
  2358. if (evalskip)
  2359. break;
  2360. }
  2361. popfile();
  2362. popstackmark(&smark);
  2363. }
  2364. /*
  2365. * Evaluate a parse tree. The value is left in the global variable
  2366. * exitstatus.
  2367. */
  2368. static void
  2369. evaltree(union node *n, int flags)
  2370. {
  2371. int checkexit = 0;
  2372. void (*evalfn)(union node *, int);
  2373. unsigned isor;
  2374. int status;
  2375. if (n == NULL) {
  2376. TRACE(("evaltree(NULL) called\n"));
  2377. goto out;
  2378. }
  2379. TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
  2380. getpid(), n, n->type, flags));
  2381. switch (n->type) {
  2382. default:
  2383. #ifdef DEBUG
  2384. out1fmt("Node type = %d\n", n->type);
  2385. fflush(stdout);
  2386. break;
  2387. #endif
  2388. case NNOT:
  2389. evaltree(n->nnot.com, EV_TESTED);
  2390. status = !exitstatus;
  2391. goto setstatus;
  2392. case NREDIR:
  2393. expredir(n->nredir.redirect);
  2394. status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
  2395. if (!status) {
  2396. evaltree(n->nredir.n, flags & EV_TESTED);
  2397. status = exitstatus;
  2398. }
  2399. popredir(0);
  2400. goto setstatus;
  2401. case NCMD:
  2402. evalfn = evalcommand;
  2403. checkexit:
  2404. if (eflag && !(flags & EV_TESTED))
  2405. checkexit = ~0;
  2406. goto calleval;
  2407. case NFOR:
  2408. evalfn = evalfor;
  2409. goto calleval;
  2410. case NWHILE:
  2411. case NUNTIL:
  2412. evalfn = evalloop;
  2413. goto calleval;
  2414. case NSUBSHELL:
  2415. case NBACKGND:
  2416. evalfn = evalsubshell;
  2417. goto calleval;
  2418. case NPIPE:
  2419. evalfn = evalpipe;
  2420. goto checkexit;
  2421. case NCASE:
  2422. evalfn = evalcase;
  2423. goto calleval;
  2424. case NAND:
  2425. case NOR:
  2426. case NSEMI:
  2427. #if NAND + 1 != NOR
  2428. #error NAND + 1 != NOR
  2429. #endif
  2430. #if NOR + 1 != NSEMI
  2431. #error NOR + 1 != NSEMI
  2432. #endif
  2433. isor = n->type - NAND;
  2434. evaltree(
  2435. n->nbinary.ch1,
  2436. (flags | ((isor >> 1) - 1)) & EV_TESTED
  2437. );
  2438. if (!exitstatus == isor)
  2439. break;
  2440. if (!evalskip) {
  2441. n = n->nbinary.ch2;
  2442. evaln:
  2443. evalfn = evaltree;
  2444. calleval:
  2445. evalfn(n, flags);
  2446. break;
  2447. }
  2448. break;
  2449. case NIF:
  2450. evaltree(n->nif.test, EV_TESTED);
  2451. if (evalskip)
  2452. break;
  2453. if (exitstatus == 0) {
  2454. n = n->nif.ifpart;
  2455. goto evaln;
  2456. } else if (n->nif.elsepart) {
  2457. n = n->nif.elsepart;
  2458. goto evaln;
  2459. }
  2460. goto success;
  2461. case NDEFUN:
  2462. defun(n->narg.text, n->narg.next);
  2463. success:
  2464. status = 0;
  2465. setstatus:
  2466. exitstatus = status;
  2467. break;
  2468. }
  2469. out:
  2470. if (pendingsigs)
  2471. dotrap();
  2472. if (flags & EV_EXIT || checkexit & exitstatus)
  2473. exraise(EXEXIT);
  2474. }
  2475. #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
  2476. static
  2477. #endif
  2478. void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
  2479. static void
  2480. evalloop(union node *n, int flags)
  2481. {
  2482. int status;
  2483. loopnest++;
  2484. status = 0;
  2485. flags &= EV_TESTED;
  2486. for (;;) {
  2487. int i;
  2488. evaltree(n->nbinary.ch1, EV_TESTED);
  2489. if (evalskip) {
  2490. skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
  2491. evalskip = 0;
  2492. continue;
  2493. }
  2494. if (evalskip == SKIPBREAK && --skipcount <= 0)
  2495. evalskip = 0;
  2496. break;
  2497. }
  2498. i = exitstatus;
  2499. if (n->type != NWHILE)
  2500. i = !i;
  2501. if (i != 0)
  2502. break;
  2503. evaltree(n->nbinary.ch2, flags);
  2504. status = exitstatus;
  2505. if (evalskip)
  2506. goto skipping;
  2507. }
  2508. loopnest--;
  2509. exitstatus = status;
  2510. }
  2511. static void
  2512. evalfor(union node *n, int flags)
  2513. {
  2514. struct arglist arglist;
  2515. union node *argp;
  2516. struct strlist *sp;
  2517. struct stackmark smark;
  2518. setstackmark(&smark);
  2519. arglist.lastp = &arglist.list;
  2520. for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
  2521. expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
  2522. /* XXX */
  2523. if (evalskip)
  2524. goto out;
  2525. }
  2526. *arglist.lastp = NULL;
  2527. exitstatus = 0;
  2528. loopnest++;
  2529. flags &= EV_TESTED;
  2530. for (sp = arglist.list ; sp ; sp = sp->next) {
  2531. setvar(n->nfor.var, sp->text, 0);
  2532. evaltree(n->nfor.body, flags);
  2533. if (evalskip) {
  2534. if (evalskip == SKIPCONT && --skipcount <= 0) {
  2535. evalskip = 0;
  2536. continue;
  2537. }
  2538. if (evalskip == SKIPBREAK && --skipcount <= 0)
  2539. evalskip = 0;
  2540. break;
  2541. }
  2542. }
  2543. loopnest--;
  2544. out:
  2545. popstackmark(&smark);
  2546. }
  2547. static void
  2548. evalcase(union node *n, int flags)
  2549. {
  2550. union node *cp;
  2551. union node *patp;
  2552. struct arglist arglist;
  2553. struct stackmark smark;
  2554. setstackmark(&smark);
  2555. arglist.lastp = &arglist.list;
  2556. expandarg(n->ncase.expr, &arglist, EXP_TILDE);
  2557. exitstatus = 0;
  2558. for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
  2559. for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
  2560. if (casematch(patp, arglist.list->text)) {
  2561. if (evalskip == 0) {
  2562. evaltree(cp->nclist.body, flags);
  2563. }
  2564. goto out;
  2565. }
  2566. }
  2567. }
  2568. out:
  2569. popstackmark(&smark);
  2570. }
  2571. /*
  2572. * Kick off a subshell to evaluate a tree.
  2573. */
  2574. static void
  2575. evalsubshell(union node *n, int flags)
  2576. {
  2577. struct job *jp;
  2578. int backgnd = (n->type == NBACKGND);
  2579. int status;
  2580. expredir(n->nredir.redirect);
  2581. if (!backgnd && flags & EV_EXIT && !trap[0])
  2582. goto nofork;
  2583. INTOFF;
  2584. jp = makejob(n, 1);
  2585. if (forkshell(jp, n, backgnd) == 0) {
  2586. INTON;
  2587. flags |= EV_EXIT;
  2588. if (backgnd)
  2589. flags &=~ EV_TESTED;
  2590. nofork:
  2591. redirect(n->nredir.redirect, 0);
  2592. evaltreenr(n->nredir.n, flags);
  2593. /* never returns */
  2594. }
  2595. status = 0;
  2596. if (! backgnd)
  2597. status = waitforjob(jp);
  2598. exitstatus = status;
  2599. INTON;
  2600. }
  2601. /*
  2602. * Compute the names of the files in a redirection list.
  2603. */
  2604. static void
  2605. expredir(union node *n)
  2606. {
  2607. union node *redir;
  2608. for (redir = n ; redir ; redir = redir->nfile.next) {
  2609. struct arglist fn;
  2610. fn.lastp = &fn.list;
  2611. switch (redir->type) {
  2612. case NFROMTO:
  2613. case NFROM:
  2614. case NTO:
  2615. case NCLOBBER:
  2616. case NAPPEND:
  2617. expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
  2618. redir->nfile.expfname = fn.list->text;
  2619. break;
  2620. case NFROMFD:
  2621. case NTOFD:
  2622. if (redir->ndup.vname) {
  2623. expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
  2624. fixredir(redir, fn.list->text, 1);
  2625. }
  2626. break;
  2627. }
  2628. }
  2629. }
  2630. /*
  2631. * Evaluate a pipeline. All the processes in the pipeline are children
  2632. * of the process creating the pipeline. (This differs from some versions
  2633. * of the shell, which make the last process in a pipeline the parent
  2634. * of all the rest.)
  2635. */
  2636. static void
  2637. evalpipe(union node *n, int flags)
  2638. {
  2639. struct job *jp;
  2640. struct nodelist *lp;
  2641. int pipelen;
  2642. int prevfd;
  2643. int pip[2];
  2644. TRACE(("evalpipe(0x%lx) called\n", (long)n));
  2645. pipelen = 0;
  2646. for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
  2647. pipelen++;
  2648. flags |= EV_EXIT;
  2649. INTOFF;
  2650. jp = makejob(n, pipelen);
  2651. prevfd = -1;
  2652. for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
  2653. prehash(lp->n);
  2654. pip[1] = -1;
  2655. if (lp->next) {
  2656. if (pipe(pip) < 0) {
  2657. close(prevfd);
  2658. error("Pipe call failed");
  2659. }
  2660. }
  2661. if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
  2662. INTON;
  2663. if (pip[1] >= 0) {
  2664. close(pip[0]);
  2665. }
  2666. if (prevfd > 0) {
  2667. dup2(prevfd, 0);
  2668. close(prevfd);
  2669. }
  2670. if (pip[1] > 1) {
  2671. dup2(pip[1], 1);
  2672. close(pip[1]);
  2673. }
  2674. evaltreenr(lp->n, flags);
  2675. /* never returns */
  2676. }
  2677. if (prevfd >= 0)
  2678. close(prevfd);
  2679. prevfd = pip[0];
  2680. close(pip[1]);
  2681. }
  2682. if (n->npipe.backgnd == 0) {
  2683. exitstatus = waitforjob(jp);
  2684. TRACE(("evalpipe: job done exit status %d\n", exitstatus));
  2685. }
  2686. INTON;
  2687. }
  2688. /*
  2689. * Execute a command inside back quotes. If it's a builtin command, we
  2690. * want to save its output in a block obtained from malloc. Otherwise
  2691. * we fork off a subprocess and get the output of the command via a pipe.
  2692. * Should be called with interrupts off.
  2693. */
  2694. static void
  2695. evalbackcmd(union node *n, struct backcmd *result)
  2696. {
  2697. int saveherefd;
  2698. result->fd = -1;
  2699. result->buf = NULL;
  2700. result->nleft = 0;
  2701. result->jp = NULL;
  2702. if (n == NULL) {
  2703. goto out;
  2704. }
  2705. saveherefd = herefd;
  2706. herefd = -1;
  2707. {
  2708. int pip[2];
  2709. struct job *jp;
  2710. if (pipe(pip) < 0)
  2711. error("Pipe call failed");
  2712. jp = makejob(n, 1);
  2713. if (forkshell(jp, n, FORK_NOJOB) == 0) {
  2714. FORCEINTON;
  2715. close(pip[0]);
  2716. if (pip[1] != 1) {
  2717. close(1);
  2718. copyfd(pip[1], 1);
  2719. close(pip[1]);
  2720. }
  2721. eflag = 0;
  2722. evaltreenr(n, EV_EXIT);
  2723. /* NOTREACHED */
  2724. }
  2725. close(pip[1]);
  2726. result->fd = pip[0];
  2727. result->jp = jp;
  2728. }
  2729. herefd = saveherefd;
  2730. out:
  2731. TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
  2732. result->fd, result->buf, result->nleft, result->jp));
  2733. }
  2734. #ifdef CONFIG_ASH_CMDCMD
  2735. static inline char **
  2736. parse_command_args(char **argv, const char **path)
  2737. {
  2738. char *cp, c;
  2739. for (;;) {
  2740. cp = *++argv;
  2741. if (!cp)
  2742. return 0;
  2743. if (*cp++ != '-')
  2744. break;
  2745. if (!(c = *cp++))
  2746. break;
  2747. if (c == '-' && !*cp) {
  2748. argv++;
  2749. break;
  2750. }
  2751. do {
  2752. switch (c) {
  2753. case 'p':
  2754. *path = defpath;
  2755. break;
  2756. default:
  2757. /* run 'typecmd' for other options */
  2758. return 0;
  2759. }
  2760. } while ((c = *cp++));
  2761. }
  2762. return argv;
  2763. }
  2764. #endif
  2765. /*
  2766. * Execute a simple command.
  2767. */
  2768. static void
  2769. evalcommand(union node *cmd, int flags)
  2770. {
  2771. struct stackmark smark;
  2772. union node *argp;
  2773. struct arglist arglist;
  2774. struct arglist varlist;
  2775. char **argv;
  2776. int argc;
  2777. const struct strlist *sp;
  2778. struct cmdentry cmdentry;
  2779. struct job *jp;
  2780. char *lastarg;
  2781. const char *path;
  2782. int spclbltin;
  2783. int cmd_is_exec;
  2784. int status;
  2785. char **nargv;
  2786. /* First expand the arguments. */
  2787. TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
  2788. setstackmark(&smark);
  2789. back_exitstatus = 0;
  2790. cmdentry.cmdtype = CMDBUILTIN;
  2791. cmdentry.u.cmd = &bltin;
  2792. varlist.lastp = &varlist.list;
  2793. *varlist.lastp = NULL;
  2794. arglist.lastp = &arglist.list;
  2795. *arglist.lastp = NULL;
  2796. argc = 0;
  2797. for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
  2798. struct strlist **spp;
  2799. spp = arglist.lastp;
  2800. expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
  2801. for (sp = *spp; sp; sp = sp->next)
  2802. argc++;
  2803. }
  2804. argv = nargv = stalloc(sizeof (char *) * (argc + 1));
  2805. for (sp = arglist.list ; sp ; sp = sp->next) {
  2806. TRACE(("evalcommand arg: %s\n", sp->text));
  2807. *nargv++ = sp->text;
  2808. }
  2809. *nargv = NULL;
  2810. lastarg = NULL;
  2811. if (iflag && funcnest == 0 && argc > 0)
  2812. lastarg = nargv[-1];
  2813. preverrout_fd = 2;
  2814. expredir(cmd->ncmd.redirect);
  2815. status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
  2816. path = vpath.text;
  2817. for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
  2818. struct strlist **spp;
  2819. char *p;
  2820. spp = varlist.lastp;
  2821. expandarg(argp, &varlist, EXP_VARTILDE);
  2822. /*
  2823. * Modify the command lookup path, if a PATH= assignment
  2824. * is present
  2825. */
  2826. p = (*spp)->text;
  2827. if (varequal(p, path))
  2828. path = p;
  2829. }
  2830. /* Print the command if xflag is set. */
  2831. if (xflag) {
  2832. int n;
  2833. const char *p = " %s";
  2834. p++;
  2835. dprintf(preverrout_fd, p, ps4val());
  2836. sp = varlist.list;
  2837. for(n = 0; n < 2; n++) {
  2838. while (sp) {
  2839. dprintf(preverrout_fd, p, sp->text);
  2840. sp = sp->next;
  2841. if(*p == '%') {
  2842. p--;
  2843. }
  2844. }
  2845. sp = arglist.list;
  2846. }
  2847. bb_full_write(preverrout_fd, "\n", 1);
  2848. }
  2849. cmd_is_exec = 0;
  2850. spclbltin = -1;
  2851. /* Now locate the command. */
  2852. if (argc) {
  2853. const char *oldpath;
  2854. int cmd_flag = DO_ERR;
  2855. path += 5;
  2856. oldpath = path;
  2857. for (;;) {
  2858. find_command(argv[0], &cmdentry, cmd_flag, path);
  2859. if (cmdentry.cmdtype == CMDUNKNOWN) {
  2860. status = 127;
  2861. flusherr();
  2862. goto bail;
  2863. }
  2864. /* implement bltin and command here */
  2865. if (cmdentry.cmdtype != CMDBUILTIN)
  2866. break;
  2867. if (spclbltin < 0)
  2868. spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
  2869. if (cmdentry.u.cmd == EXECCMD)
  2870. cmd_is_exec++;
  2871. #ifdef CONFIG_ASH_CMDCMD
  2872. if (cmdentry.u.cmd == COMMANDCMD) {
  2873. path = oldpath;
  2874. nargv = parse_command_args(argv, &path);
  2875. if (!nargv)
  2876. break;
  2877. argc -= nargv - argv;
  2878. argv = nargv;
  2879. cmd_flag |= DO_NOFUNC;
  2880. } else
  2881. #endif
  2882. break;
  2883. }
  2884. }
  2885. if (status) {
  2886. /* We have a redirection error. */
  2887. if (spclbltin > 0)
  2888. exraise(EXERROR);
  2889. bail:
  2890. exitstatus = status;
  2891. goto out;
  2892. }
  2893. /* Execute the command. */
  2894. switch (cmdentry.cmdtype) {
  2895. default:
  2896. /* Fork off a child process if necessary. */
  2897. if (!(flags & EV_EXIT) || trap[0]) {
  2898. INTOFF;
  2899. jp = makejob(cmd, 1);
  2900. if (forkshell(jp, cmd, FORK_FG) != 0) {
  2901. exitstatus = waitforjob(jp);
  2902. INTON;
  2903. break;
  2904. }
  2905. FORCEINTON;
  2906. }
  2907. listsetvar(varlist.list, VEXPORT|VSTACK);
  2908. shellexec(argv, path, cmdentry.u.index);
  2909. /* NOTREACHED */
  2910. case CMDBUILTIN:
  2911. cmdenviron = varlist.list;
  2912. if (cmdenviron) {
  2913. struct strlist *list = cmdenviron;
  2914. int i = VNOSET;
  2915. if (spclbltin > 0 || argc == 0) {
  2916. i = 0;
  2917. if (cmd_is_exec && argc > 1)
  2918. i = VEXPORT;
  2919. }
  2920. listsetvar(list, i);
  2921. }
  2922. if (evalbltin(cmdentry.u.cmd, argc, argv)) {
  2923. int exit_status;
  2924. int i, j;
  2925. i = exception;
  2926. if (i == EXEXIT)
  2927. goto raise;
  2928. exit_status = 2;
  2929. j = 0;
  2930. if (i == EXINT)
  2931. j = SIGINT;
  2932. if (i == EXSIG)
  2933. j = pendingsigs;
  2934. if (j)
  2935. exit_status = j + 128;
  2936. exitstatus = exit_status;
  2937. if (i == EXINT || spclbltin > 0) {
  2938. raise:
  2939. longjmp(handler->loc, 1);
  2940. }
  2941. FORCEINTON;
  2942. }
  2943. break;
  2944. case CMDFUNCTION:
  2945. listsetvar(varlist.list, 0);
  2946. if (evalfun(cmdentry.u.func, argc, argv, flags))
  2947. goto raise;
  2948. break;
  2949. }
  2950. out:
  2951. popredir(cmd_is_exec);
  2952. if (lastarg)
  2953. /* dsl: I think this is intended to be used to support
  2954. * '_' in 'vi' command mode during line editing...
  2955. * However I implemented that within libedit itself.
  2956. */
  2957. setvar("_", lastarg, 0);
  2958. popstackmark(&smark);
  2959. }
  2960. static int
  2961. evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
  2962. char *volatile savecmdname;
  2963. struct jmploc *volatile savehandler;
  2964. struct jmploc jmploc;
  2965. int i;
  2966. savecmdname = commandname;
  2967. if ((i = setjmp(jmploc.loc)))
  2968. goto cmddone;
  2969. savehandler = handler;
  2970. handler = &jmploc;
  2971. commandname = argv[0];
  2972. argptr = argv + 1;
  2973. optptr = NULL; /* initialize nextopt */
  2974. exitstatus = (*cmd->builtin)(argc, argv);
  2975. flushall();
  2976. cmddone:
  2977. exitstatus |= ferror(stdout);
  2978. commandname = savecmdname;
  2979. exsig = 0;
  2980. handler = savehandler;
  2981. return i;
  2982. }
  2983. static int
  2984. evalfun(struct funcnode *func, int argc, char **argv, int flags)
  2985. {
  2986. volatile struct shparam saveparam;
  2987. struct localvar *volatile savelocalvars;
  2988. struct jmploc *volatile savehandler;
  2989. struct jmploc jmploc;
  2990. int e;
  2991. saveparam = shellparam;
  2992. savelocalvars = localvars;
  2993. if ((e = setjmp(jmploc.loc))) {
  2994. goto funcdone;
  2995. }
  2996. INTOFF;
  2997. savehandler = handler;
  2998. handler = &jmploc;
  2999. localvars = NULL;
  3000. shellparam.malloc = 0;
  3001. func->count++;
  3002. INTON;
  3003. shellparam.nparam = argc - 1;
  3004. shellparam.p = argv + 1;
  3005. #ifdef CONFIG_ASH_GETOPTS
  3006. shellparam.optind = 1;
  3007. shellparam.optoff = -1;
  3008. #endif
  3009. funcnest++;
  3010. evaltree(&func->n, flags & EV_TESTED);
  3011. funcnest--;
  3012. funcdone:
  3013. INTOFF;
  3014. freefunc(func);
  3015. poplocalvars();
  3016. localvars = savelocalvars;
  3017. freeparam(&shellparam);
  3018. shellparam = saveparam;
  3019. handler = savehandler;
  3020. INTON;
  3021. if (evalskip == SKIPFUNC) {
  3022. evalskip = 0;
  3023. skipcount = 0;
  3024. }
  3025. return e;
  3026. }
  3027. static inline int
  3028. goodname(const char *p)
  3029. {
  3030. return !*endofname(p);
  3031. }
  3032. /*
  3033. * Search for a command. This is called before we fork so that the
  3034. * location of the command will be available in the parent as well as
  3035. * the child. The check for "goodname" is an overly conservative
  3036. * check that the name will not be subject to expansion.
  3037. */
  3038. static void
  3039. prehash(union node *n)
  3040. {
  3041. struct cmdentry entry;
  3042. if (n->type == NCMD && n->ncmd.args)
  3043. if (goodname(n->ncmd.args->narg.text))
  3044. find_command(n->ncmd.args->narg.text, &entry, 0,
  3045. pathval());
  3046. }
  3047. /*
  3048. * Builtin commands. Builtin commands whose functions are closely
  3049. * tied to evaluation are implemented here.
  3050. */
  3051. /*
  3052. * No command given.
  3053. */
  3054. static int
  3055. bltincmd(int argc, char **argv)
  3056. {
  3057. /*
  3058. * Preserve exitstatus of a previous possible redirection
  3059. * as POSIX mandates
  3060. */
  3061. return back_exitstatus;
  3062. }
  3063. /*
  3064. * Handle break and continue commands. Break, continue, and return are
  3065. * all handled by setting the evalskip flag. The evaluation routines
  3066. * above all check this flag, and if it is set they start skipping
  3067. * commands rather than executing them. The variable skipcount is
  3068. * the number of loops to break/continue, or the number of function
  3069. * levels to return. (The latter is always 1.) It should probably
  3070. * be an error to break out of more loops than exist, but it isn't
  3071. * in the standard shell so we don't make it one here.
  3072. */
  3073. static int
  3074. breakcmd(int argc, char **argv)
  3075. {
  3076. int n = argc > 1 ? number(argv[1]) : 1;
  3077. if (n <= 0)
  3078. error(illnum, argv[1]);
  3079. if (n > loopnest)
  3080. n = loopnest;
  3081. if (n > 0) {
  3082. evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
  3083. skipcount = n;
  3084. }
  3085. return 0;
  3086. }
  3087. /*
  3088. * The return command.
  3089. */
  3090. static int
  3091. returncmd(int argc, char **argv)
  3092. {
  3093. int ret = argc > 1 ? number(argv[1]) : exitstatus;
  3094. if (funcnest) {
  3095. evalskip = SKIPFUNC;
  3096. skipcount = 1;
  3097. return ret;
  3098. }
  3099. else {
  3100. /* Do what ksh does; skip the rest of the file */
  3101. evalskip = SKIPFILE;
  3102. skipcount = 1;
  3103. return ret;
  3104. }
  3105. }
  3106. static int
  3107. falsecmd(int argc, char **argv)
  3108. {
  3109. return 1;
  3110. }
  3111. static int
  3112. truecmd(int argc, char **argv)
  3113. {
  3114. return 0;
  3115. }
  3116. static int
  3117. execcmd(int argc, char **argv)
  3118. {
  3119. if (argc > 1) {
  3120. iflag = 0; /* exit on error */
  3121. mflag = 0;
  3122. optschanged();
  3123. shellexec(argv + 1, pathval(), 0);
  3124. }
  3125. return 0;
  3126. }
  3127. /* $NetBSD: exec.c,v 1.35 2003/01/22 20:36:04 dsl Exp $ */
  3128. /*
  3129. * When commands are first encountered, they are entered in a hash table.
  3130. * This ensures that a full path search will not have to be done for them
  3131. * on each invocation.
  3132. *
  3133. * We should investigate converting to a linear search, even though that
  3134. * would make the command name "hash" a misnomer.
  3135. */
  3136. #define CMDTABLESIZE 31 /* should be prime */
  3137. #define ARB 1 /* actual size determined at run time */
  3138. struct tblentry {
  3139. struct tblentry *next; /* next entry in hash chain */
  3140. union param param; /* definition of builtin function */
  3141. short cmdtype; /* index identifying command */
  3142. char rehash; /* if set, cd done since entry created */
  3143. char cmdname[ARB]; /* name of command */
  3144. };
  3145. static struct tblentry *cmdtable[CMDTABLESIZE];
  3146. static int builtinloc = -1; /* index in path of %builtin, or -1 */
  3147. static void tryexec(char *, char **, char **);
  3148. static void clearcmdentry(int);
  3149. static struct tblentry *cmdlookup(const char *, int);
  3150. static void delete_cmd_entry(void);
  3151. /*
  3152. * Exec a program. Never returns. If you change this routine, you may
  3153. * have to change the find_command routine as well.
  3154. */
  3155. static void
  3156. shellexec(char **argv, const char *path, int idx)
  3157. {
  3158. char *cmdname;
  3159. int e;
  3160. char **envp;
  3161. clearredir(1);
  3162. envp = environment();
  3163. if (strchr(argv[0], '/') != NULL
  3164. #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
  3165. || find_applet_by_name(argv[0])
  3166. #endif
  3167. ) {
  3168. tryexec(argv[0], argv, envp);
  3169. e = errno;
  3170. } else {
  3171. e = ENOENT;
  3172. while ((cmdname = padvance(&path, argv[0])) != NULL) {
  3173. if (--idx < 0 && pathopt == NULL) {
  3174. tryexec(cmdname, argv, envp);
  3175. if (errno != ENOENT && errno != ENOTDIR)
  3176. e = errno;
  3177. }
  3178. stunalloc(cmdname);
  3179. }
  3180. }
  3181. /* Map to POSIX errors */
  3182. switch (e) {
  3183. case EACCES:
  3184. exerrno = 126;
  3185. break;
  3186. case ENOENT:
  3187. exerrno = 127;
  3188. break;
  3189. default:
  3190. exerrno = 2;
  3191. break;
  3192. }
  3193. TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
  3194. argv[0], e, suppressint ));
  3195. exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
  3196. /* NOTREACHED */
  3197. }
  3198. static void
  3199. tryexec(char *cmd, char **argv, char **envp)
  3200. {
  3201. int repeated = 0;
  3202. #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
  3203. if(find_applet_by_name(cmd) != NULL) {
  3204. /* re-exec ourselves with the new arguments */
  3205. execve("/proc/self/exe",argv,envp);
  3206. /* If proc isn't mounted, try hardcoded path to busybox binary*/
  3207. execve("/bin/busybox",argv,envp);
  3208. /* If they called chroot or otherwise made the binary no longer
  3209. * executable, fall through */
  3210. }
  3211. #endif
  3212. repeat:
  3213. #ifdef SYSV
  3214. do {
  3215. execve(cmd, argv, envp);
  3216. } while (errno == EINTR);
  3217. #else
  3218. execve(cmd, argv, envp);
  3219. #endif
  3220. if (repeated++) {
  3221. ckfree(argv);
  3222. } else if (errno == ENOEXEC) {
  3223. char **ap;
  3224. char **new;
  3225. for (ap = argv; *ap; ap++)
  3226. ;
  3227. ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
  3228. ap[1] = cmd;
  3229. *ap = cmd = (char *)DEFAULT_SHELL;
  3230. ap += 2;
  3231. argv++;
  3232. while ((*ap++ = *argv++))
  3233. ;
  3234. argv = new;
  3235. goto repeat;
  3236. }
  3237. }
  3238. /*
  3239. * Do a path search. The variable path (passed by reference) should be
  3240. * set to the start of the path before the first call; padvance will update
  3241. * this value as it proceeds. Successive calls to padvance will return
  3242. * the possible path expansions in sequence. If an option (indicated by
  3243. * a percent sign) appears in the path entry then the global variable
  3244. * pathopt will be set to point to it; otherwise pathopt will be set to
  3245. * NULL.
  3246. */
  3247. static char *
  3248. padvance(const char **path, const char *name)
  3249. {
  3250. const char *p;
  3251. char *q;
  3252. const char *start;
  3253. size_t len;
  3254. if (*path == NULL)
  3255. return NULL;
  3256. start = *path;
  3257. for (p = start ; *p && *p != ':' && *p != '%' ; p++);
  3258. len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
  3259. while (stackblocksize() < len)
  3260. growstackblock();
  3261. q = stackblock();
  3262. if (p != start) {
  3263. memcpy(q, start, p - start);
  3264. q += p - start;
  3265. *q++ = '/';
  3266. }
  3267. strcpy(q, name);
  3268. pathopt = NULL;
  3269. if (*p == '%') {
  3270. pathopt = ++p;
  3271. while (*p && *p != ':') p++;
  3272. }
  3273. if (*p == ':')
  3274. *path = p + 1;
  3275. else
  3276. *path = NULL;
  3277. return stalloc(len);
  3278. }
  3279. /*** Command hashing code ***/
  3280. static void
  3281. printentry(struct tblentry *cmdp)
  3282. {
  3283. int idx;
  3284. const char *path;
  3285. char *name;
  3286. idx = cmdp->param.index;
  3287. path = pathval();
  3288. do {
  3289. name = padvance(&path, cmdp->cmdname);
  3290. stunalloc(name);
  3291. } while (--idx >= 0);
  3292. out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
  3293. }
  3294. static int
  3295. hashcmd(int argc, char **argv)
  3296. {
  3297. struct tblentry **pp;
  3298. struct tblentry *cmdp;
  3299. int c;
  3300. struct cmdentry entry;
  3301. char *name;
  3302. while ((c = nextopt("r")) != '\0') {
  3303. clearcmdentry(0);
  3304. return 0;
  3305. }
  3306. if (*argptr == NULL) {
  3307. for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
  3308. for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
  3309. if (cmdp->cmdtype == CMDNORMAL)
  3310. printentry(cmdp);
  3311. }
  3312. }
  3313. return 0;
  3314. }
  3315. c = 0;
  3316. while ((name = *argptr) != NULL) {
  3317. if ((cmdp = cmdlookup(name, 0)) != NULL
  3318. && (cmdp->cmdtype == CMDNORMAL
  3319. || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
  3320. delete_cmd_entry();
  3321. find_command(name, &entry, DO_ERR, pathval());
  3322. if (entry.cmdtype == CMDUNKNOWN)
  3323. c = 1;
  3324. argptr++;
  3325. }
  3326. return c;
  3327. }
  3328. /*
  3329. * Resolve a command name. If you change this routine, you may have to
  3330. * change the shellexec routine as well.
  3331. */
  3332. static void
  3333. find_command(char *name, struct cmdentry *entry, int act, const char *path)
  3334. {
  3335. struct tblentry *cmdp;
  3336. int idx;
  3337. int prev;
  3338. char *fullname;
  3339. struct stat statb;
  3340. int e;
  3341. int updatetbl;
  3342. struct builtincmd *bcmd;
  3343. /* If name contains a slash, don't use PATH or hash table */
  3344. if (strchr(name, '/') != NULL) {
  3345. entry->u.index = -1;
  3346. if (act & DO_ABS) {
  3347. while (stat(name, &statb) < 0) {
  3348. #ifdef SYSV
  3349. if (errno == EINTR)
  3350. continue;
  3351. #endif
  3352. entry->cmdtype = CMDUNKNOWN;
  3353. return;
  3354. }
  3355. }
  3356. entry->cmdtype = CMDNORMAL;
  3357. return;
  3358. }
  3359. #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
  3360. if (find_applet_by_name(name)) {
  3361. entry->cmdtype = CMDNORMAL;
  3362. entry->u.index = -1;
  3363. return;
  3364. }
  3365. #endif
  3366. updatetbl = (path == pathval());
  3367. if (!updatetbl) {
  3368. act |= DO_ALTPATH;
  3369. if (strstr(path, "%builtin") != NULL)
  3370. act |= DO_ALTBLTIN;
  3371. }
  3372. /* If name is in the table, check answer will be ok */
  3373. if ((cmdp = cmdlookup(name, 0)) != NULL) {
  3374. int bit;
  3375. switch (cmdp->cmdtype) {
  3376. default:
  3377. #if DEBUG
  3378. abort();
  3379. #endif
  3380. case CMDNORMAL:
  3381. bit = DO_ALTPATH;
  3382. break;
  3383. case CMDFUNCTION:
  3384. bit = DO_NOFUNC;
  3385. break;
  3386. case CMDBUILTIN:
  3387. bit = DO_ALTBLTIN;
  3388. break;
  3389. }
  3390. if (act & bit) {
  3391. updatetbl = 0;
  3392. cmdp = NULL;
  3393. } else if (cmdp->rehash == 0)
  3394. /* if not invalidated by cd, we're done */
  3395. goto success;
  3396. }
  3397. /* If %builtin not in path, check for builtin next */
  3398. bcmd = find_builtin(name);
  3399. if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
  3400. act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
  3401. )))
  3402. goto builtin_success;
  3403. /* We have to search path. */
  3404. prev = -1; /* where to start */
  3405. if (cmdp && cmdp->rehash) { /* doing a rehash */
  3406. if (cmdp->cmdtype == CMDBUILTIN)
  3407. prev = builtinloc;
  3408. else
  3409. prev = cmdp->param.index;
  3410. }
  3411. e = ENOENT;
  3412. idx = -1;
  3413. loop:
  3414. while ((fullname = padvance(&path, name)) != NULL) {
  3415. stunalloc(fullname);
  3416. idx++;
  3417. if (pathopt) {
  3418. if (prefix(pathopt, "builtin")) {
  3419. if (bcmd)
  3420. goto builtin_success;
  3421. continue;
  3422. } else if (!(act & DO_NOFUNC) &&
  3423. prefix(pathopt, "func")) {
  3424. /* handled below */
  3425. } else {
  3426. /* ignore unimplemented options */
  3427. continue;
  3428. }
  3429. }
  3430. /* if rehash, don't redo absolute path names */
  3431. if (fullname[0] == '/' && idx <= prev) {
  3432. if (idx < prev)
  3433. continue;
  3434. TRACE(("searchexec \"%s\": no change\n", name));
  3435. goto success;
  3436. }
  3437. while (stat(fullname, &statb) < 0) {
  3438. #ifdef SYSV
  3439. if (errno == EINTR)
  3440. continue;
  3441. #endif
  3442. if (errno != ENOENT && errno != ENOTDIR)
  3443. e = errno;
  3444. goto loop;
  3445. }
  3446. e = EACCES; /* if we fail, this will be the error */
  3447. if (!S_ISREG(statb.st_mode))
  3448. continue;
  3449. if (pathopt) { /* this is a %func directory */
  3450. stalloc(strlen(fullname) + 1);
  3451. readcmdfile(fullname);
  3452. if ((cmdp = cmdlookup(name, 0)) == NULL ||
  3453. cmdp->cmdtype != CMDFUNCTION)
  3454. error("%s not defined in %s", name, fullname);
  3455. stunalloc(fullname);
  3456. goto success;
  3457. }
  3458. TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
  3459. if (!updatetbl) {
  3460. entry->cmdtype = CMDNORMAL;
  3461. entry->u.index = idx;
  3462. return;
  3463. }
  3464. INTOFF;
  3465. cmdp = cmdlookup(name, 1);
  3466. cmdp->cmdtype = CMDNORMAL;
  3467. cmdp->param.index = idx;
  3468. INTON;
  3469. goto success;
  3470. }
  3471. /* We failed. If there was an entry for this command, delete it */
  3472. if (cmdp && updatetbl)
  3473. delete_cmd_entry();
  3474. if (act & DO_ERR)
  3475. sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
  3476. entry->cmdtype = CMDUNKNOWN;
  3477. return;
  3478. builtin_success:
  3479. if (!updatetbl) {
  3480. entry->cmdtype = CMDBUILTIN;
  3481. entry->u.cmd = bcmd;
  3482. return;
  3483. }
  3484. INTOFF;
  3485. cmdp = cmdlookup(name, 1);
  3486. cmdp->cmdtype = CMDBUILTIN;
  3487. cmdp->param.cmd = bcmd;
  3488. INTON;
  3489. success:
  3490. cmdp->rehash = 0;
  3491. entry->cmdtype = cmdp->cmdtype;
  3492. entry->u = cmdp->param;
  3493. }
  3494. /*
  3495. * Wrapper around strcmp for qsort/bsearch/...
  3496. */
  3497. static int pstrcmp(const void *a, const void *b)
  3498. {
  3499. return strcmp((const char *) a, (*(const char *const *) b) + 1);
  3500. }
  3501. /*
  3502. * Search the table of builtin commands.
  3503. */
  3504. static struct builtincmd *
  3505. find_builtin(const char *name)
  3506. {
  3507. struct builtincmd *bp;
  3508. bp = bsearch(
  3509. name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
  3510. pstrcmp
  3511. );
  3512. return bp;
  3513. }
  3514. /*
  3515. * Called when a cd is done. Marks all commands so the next time they
  3516. * are executed they will be rehashed.
  3517. */
  3518. static void
  3519. hashcd(void)
  3520. {
  3521. struct tblentry **pp;
  3522. struct tblentry *cmdp;
  3523. for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
  3524. for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
  3525. if (cmdp->cmdtype == CMDNORMAL || (
  3526. cmdp->cmdtype == CMDBUILTIN &&
  3527. !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
  3528. builtinloc > 0
  3529. ))
  3530. cmdp->rehash = 1;
  3531. }
  3532. }
  3533. }
  3534. /*
  3535. * Fix command hash table when PATH changed.
  3536. * Called before PATH is changed. The argument is the new value of PATH;
  3537. * pathval() still returns the old value at this point.
  3538. * Called with interrupts off.
  3539. */
  3540. static void
  3541. changepath(const char *newval)
  3542. {
  3543. const char *old, *new;
  3544. int idx;
  3545. int firstchange;
  3546. int idx_bltin;
  3547. old = pathval();
  3548. new = newval;
  3549. firstchange = 9999; /* assume no change */
  3550. idx = 0;
  3551. idx_bltin = -1;
  3552. for (;;) {
  3553. if (*old != *new) {
  3554. firstchange = idx;
  3555. if ((*old == '\0' && *new == ':')
  3556. || (*old == ':' && *new == '\0'))
  3557. firstchange++;
  3558. old = new; /* ignore subsequent differences */
  3559. }
  3560. if (*new == '\0')
  3561. break;
  3562. if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
  3563. idx_bltin = idx;
  3564. if (*new == ':') {
  3565. idx++;
  3566. }
  3567. new++, old++;
  3568. }
  3569. if (builtinloc < 0 && idx_bltin >= 0)
  3570. builtinloc = idx_bltin; /* zap builtins */
  3571. if (builtinloc >= 0 && idx_bltin < 0)
  3572. firstchange = 0;
  3573. clearcmdentry(firstchange);
  3574. builtinloc = idx_bltin;
  3575. }
  3576. /*
  3577. * Clear out command entries. The argument specifies the first entry in
  3578. * PATH which has changed.
  3579. */
  3580. static void
  3581. clearcmdentry(int firstchange)
  3582. {
  3583. struct tblentry **tblp;
  3584. struct tblentry **pp;
  3585. struct tblentry *cmdp;
  3586. INTOFF;
  3587. for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
  3588. pp = tblp;
  3589. while ((cmdp = *pp) != NULL) {
  3590. if ((cmdp->cmdtype == CMDNORMAL &&
  3591. cmdp->param.index >= firstchange)
  3592. || (cmdp->cmdtype == CMDBUILTIN &&
  3593. builtinloc >= firstchange)) {
  3594. *pp = cmdp->next;
  3595. ckfree(cmdp);
  3596. } else {
  3597. pp = &cmdp->next;
  3598. }
  3599. }
  3600. }
  3601. INTON;
  3602. }
  3603. /*
  3604. * Locate a command in the command hash table. If "add" is nonzero,
  3605. * add the command to the table if it is not already present. The
  3606. * variable "lastcmdentry" is set to point to the address of the link
  3607. * pointing to the entry, so that delete_cmd_entry can delete the
  3608. * entry.
  3609. *
  3610. * Interrupts must be off if called with add != 0.
  3611. */
  3612. static struct tblentry **lastcmdentry;
  3613. static struct tblentry *
  3614. cmdlookup(const char *name, int add)
  3615. {
  3616. unsigned int hashval;
  3617. const char *p;
  3618. struct tblentry *cmdp;
  3619. struct tblentry **pp;
  3620. p = name;
  3621. hashval = (unsigned char)*p << 4;
  3622. while (*p)
  3623. hashval += (unsigned char)*p++;
  3624. hashval &= 0x7FFF;
  3625. pp = &cmdtable[hashval % CMDTABLESIZE];
  3626. for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
  3627. if (equal(cmdp->cmdname, name))
  3628. break;
  3629. pp = &cmdp->next;
  3630. }
  3631. if (add && cmdp == NULL) {
  3632. cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
  3633. + strlen(name) + 1);
  3634. cmdp->next = NULL;
  3635. cmdp->cmdtype = CMDUNKNOWN;
  3636. strcpy(cmdp->cmdname, name);
  3637. }
  3638. lastcmdentry = pp;
  3639. return cmdp;
  3640. }
  3641. /*
  3642. * Delete the command entry returned on the last lookup.
  3643. */
  3644. static void
  3645. delete_cmd_entry(void)
  3646. {
  3647. struct tblentry *cmdp;
  3648. INTOFF;
  3649. cmdp = *lastcmdentry;
  3650. *lastcmdentry = cmdp->next;
  3651. if (cmdp->cmdtype == CMDFUNCTION)
  3652. freefunc(cmdp->param.func);
  3653. ckfree(cmdp);
  3654. INTON;
  3655. }
  3656. /*
  3657. * Add a new command entry, replacing any existing command entry for
  3658. * the same name - except special builtins.
  3659. */
  3660. static inline void
  3661. addcmdentry(char *name, struct cmdentry *entry)
  3662. {
  3663. struct tblentry *cmdp;
  3664. cmdp = cmdlookup(name, 1);
  3665. if (cmdp->cmdtype == CMDFUNCTION) {
  3666. freefunc(cmdp->param.func);
  3667. }
  3668. cmdp->cmdtype = entry->cmdtype;
  3669. cmdp->param = entry->u;
  3670. cmdp->rehash = 0;
  3671. }
  3672. /*
  3673. * Make a copy of a parse tree.
  3674. */
  3675. static inline struct funcnode *
  3676. copyfunc(union node *n)
  3677. {
  3678. struct funcnode *f;
  3679. size_t blocksize;
  3680. funcblocksize = offsetof(struct funcnode, n);
  3681. funcstringsize = 0;
  3682. calcsize(n);
  3683. blocksize = funcblocksize;
  3684. f = ckmalloc(blocksize + funcstringsize);
  3685. funcblock = (char *) f + offsetof(struct funcnode, n);
  3686. funcstring = (char *) f + blocksize;
  3687. copynode(n);
  3688. f->count = 0;
  3689. return f;
  3690. }
  3691. /*
  3692. * Define a shell function.
  3693. */
  3694. static void
  3695. defun(char *name, union node *func)
  3696. {
  3697. struct cmdentry entry;
  3698. INTOFF;
  3699. entry.cmdtype = CMDFUNCTION;
  3700. entry.u.func = copyfunc(func);
  3701. addcmdentry(name, &entry);
  3702. INTON;
  3703. }
  3704. /*
  3705. * Delete a function if it exists.
  3706. */
  3707. static void
  3708. unsetfunc(const char *name)
  3709. {
  3710. struct tblentry *cmdp;
  3711. if ((cmdp = cmdlookup(name, 0)) != NULL &&
  3712. cmdp->cmdtype == CMDFUNCTION)
  3713. delete_cmd_entry();
  3714. }
  3715. /*
  3716. * Locate and print what a word is...
  3717. */
  3718. #ifdef CONFIG_ASH_CMDCMD
  3719. static int
  3720. describe_command(char *command, int describe_command_verbose)
  3721. #else
  3722. #define describe_command_verbose 1
  3723. static int
  3724. describe_command(char *command)
  3725. #endif
  3726. {
  3727. struct cmdentry entry;
  3728. struct tblentry *cmdp;
  3729. #ifdef CONFIG_ASH_ALIAS
  3730. const struct alias *ap;
  3731. #endif
  3732. const char *path = pathval();
  3733. if (describe_command_verbose) {
  3734. out1str(command);
  3735. }
  3736. /* First look at the keywords */
  3737. if (findkwd(command)) {
  3738. out1str(describe_command_verbose ? " is a shell keyword" : command);
  3739. goto out;
  3740. }
  3741. #ifdef CONFIG_ASH_ALIAS
  3742. /* Then look at the aliases */
  3743. if ((ap = lookupalias(command, 0)) != NULL) {
  3744. if (describe_command_verbose) {
  3745. out1fmt(" is an alias for %s", ap->val);
  3746. } else {
  3747. out1str("alias ");
  3748. printalias(ap);
  3749. return 0;
  3750. }
  3751. goto out;
  3752. }
  3753. #endif
  3754. /* Then check if it is a tracked alias */
  3755. if ((cmdp = cmdlookup(command, 0)) != NULL) {
  3756. entry.cmdtype = cmdp->cmdtype;
  3757. entry.u = cmdp->param;
  3758. } else {
  3759. /* Finally use brute force */
  3760. find_command(command, &entry, DO_ABS, path);
  3761. }
  3762. switch (entry.cmdtype) {
  3763. case CMDNORMAL: {
  3764. int j = entry.u.index;
  3765. char *p;
  3766. if (j == -1) {
  3767. p = command;
  3768. } else {
  3769. do {
  3770. p = padvance(&path, command);
  3771. stunalloc(p);
  3772. } while (--j >= 0);
  3773. }
  3774. if (describe_command_verbose) {
  3775. out1fmt(" is%s %s",
  3776. (cmdp ? " a tracked alias for" : nullstr), p
  3777. );
  3778. } else {
  3779. out1str(p);
  3780. }
  3781. break;
  3782. }
  3783. case CMDFUNCTION:
  3784. if (describe_command_verbose) {
  3785. out1str(" is a shell function");
  3786. } else {
  3787. out1str(command);
  3788. }
  3789. break;
  3790. case CMDBUILTIN:
  3791. if (describe_command_verbose) {
  3792. out1fmt(" is a %sshell builtin",
  3793. IS_BUILTIN_SPECIAL(entry.u.cmd) ?
  3794. "special " : nullstr
  3795. );
  3796. } else {
  3797. out1str(command);
  3798. }
  3799. break;
  3800. default:
  3801. if (describe_command_verbose) {
  3802. out1str(": not found\n");
  3803. }
  3804. return 127;
  3805. }
  3806. out:
  3807. outstr("\n", stdout);
  3808. return 0;
  3809. }
  3810. static int
  3811. typecmd(int argc, char **argv)
  3812. {
  3813. int i;
  3814. int err = 0;
  3815. for (i = 1; i < argc; i++) {
  3816. #ifdef CONFIG_ASH_CMDCMD
  3817. err |= describe_command(argv[i], 1);
  3818. #else
  3819. err |= describe_command(argv[i]);
  3820. #endif
  3821. }
  3822. return err;
  3823. }
  3824. #ifdef CONFIG_ASH_CMDCMD
  3825. static int
  3826. commandcmd(int argc, char **argv)
  3827. {
  3828. int c;
  3829. int default_path = 0;
  3830. int verify_only = 0;
  3831. int verbose_verify_only = 0;
  3832. while ((c = nextopt("pvV")) != '\0')
  3833. switch (c) {
  3834. default:
  3835. #ifdef DEBUG
  3836. fprintf(stderr,
  3837. "command: nextopt returned character code 0%o\n", c);
  3838. return EX_SOFTWARE;
  3839. #endif
  3840. case 'p':
  3841. default_path = 1;
  3842. break;
  3843. case 'v':
  3844. verify_only = 1;
  3845. break;
  3846. case 'V':
  3847. verbose_verify_only = 1;
  3848. break;
  3849. }
  3850. if (default_path + verify_only + verbose_verify_only > 1 ||
  3851. !*argptr) {
  3852. fprintf(stderr,
  3853. "command [-p] command [arg ...]\n"
  3854. "command {-v|-V} command\n");
  3855. return EX_USAGE;
  3856. }
  3857. if (verify_only || verbose_verify_only) {
  3858. return describe_command(*argptr, verbose_verify_only);
  3859. }
  3860. return 0;
  3861. }
  3862. #endif
  3863. /* $NetBSD: expand.c,v 1.56 2002/11/24 22:35:39 christos Exp $ */
  3864. /*
  3865. * Routines to expand arguments to commands. We have to deal with
  3866. * backquotes, shell variables, and file metacharacters.
  3867. */
  3868. /*
  3869. * _rmescape() flags
  3870. */
  3871. #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
  3872. #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
  3873. #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
  3874. #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
  3875. #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
  3876. /*
  3877. * Structure specifying which parts of the string should be searched
  3878. * for IFS characters.
  3879. */
  3880. struct ifsregion {
  3881. struct ifsregion *next; /* next region in list */
  3882. int begoff; /* offset of start of region */
  3883. int endoff; /* offset of end of region */
  3884. int nulonly; /* search for nul bytes only */
  3885. };
  3886. /* output of current string */
  3887. static char *expdest;
  3888. /* list of back quote expressions */
  3889. static struct nodelist *argbackq;
  3890. /* first struct in list of ifs regions */
  3891. static struct ifsregion ifsfirst;
  3892. /* last struct in list */
  3893. static struct ifsregion *ifslastp;
  3894. /* holds expanded arg list */
  3895. static struct arglist exparg;
  3896. static void argstr(char *, int);
  3897. static char *exptilde(char *, char *, int);
  3898. static void expbackq(union node *, int, int);
  3899. static const char *subevalvar(char *, char *, int, int, int, int, int);
  3900. static char *evalvar(char *, int);
  3901. static void strtodest(const char *, int, int);
  3902. static void memtodest(const char *p, size_t len, int syntax, int quotes);
  3903. static ssize_t varvalue(char *, int, int);
  3904. static void recordregion(int, int, int);
  3905. static void removerecordregions(int);
  3906. static void ifsbreakup(char *, struct arglist *);
  3907. static void ifsfree(void);
  3908. static void expandmeta(struct strlist *, int);
  3909. static int patmatch(char *, const char *);
  3910. static int cvtnum(arith_t);
  3911. static size_t esclen(const char *, const char *);
  3912. static char *scanleft(char *, char *, char *, char *, int, int);
  3913. static char *scanright(char *, char *, char *, char *, int, int);
  3914. static void varunset(const char *, const char *, const char *, int)
  3915. __attribute__((__noreturn__));
  3916. #define pmatch(a, b) !fnmatch((a), (b), 0)
  3917. /*
  3918. * Prepare a pattern for a expmeta (internal glob(3)) call.
  3919. *
  3920. * Returns an stalloced string.
  3921. */
  3922. static inline char *
  3923. preglob(const char *pattern, int quoted, int flag) {
  3924. flag |= RMESCAPE_GLOB;
  3925. if (quoted) {
  3926. flag |= RMESCAPE_QUOTED;
  3927. }
  3928. return _rmescapes((char *)pattern, flag);
  3929. }
  3930. static size_t
  3931. esclen(const char *start, const char *p) {
  3932. size_t esc = 0;
  3933. while (p > start && *--p == CTLESC) {
  3934. esc++;
  3935. }
  3936. return esc;
  3937. }
  3938. /*
  3939. * Expand shell variables and backquotes inside a here document.
  3940. */
  3941. static inline void
  3942. expandhere(union node *arg, int fd)
  3943. {
  3944. herefd = fd;
  3945. expandarg(arg, (struct arglist *)NULL, 0);
  3946. bb_full_write(fd, stackblock(), expdest - (char *)stackblock());
  3947. }
  3948. /*
  3949. * Perform variable substitution and command substitution on an argument,
  3950. * placing the resulting list of arguments in arglist. If EXP_FULL is true,
  3951. * perform splitting and file name expansion. When arglist is NULL, perform
  3952. * here document expansion.
  3953. */
  3954. void
  3955. expandarg(union node *arg, struct arglist *arglist, int flag)
  3956. {
  3957. struct strlist *sp;
  3958. char *p;
  3959. argbackq = arg->narg.backquote;
  3960. STARTSTACKSTR(expdest);
  3961. ifsfirst.next = NULL;
  3962. ifslastp = NULL;
  3963. argstr(arg->narg.text, flag);
  3964. if (arglist == NULL) {
  3965. return; /* here document expanded */
  3966. }
  3967. STPUTC('\0', expdest);
  3968. p = grabstackstr(expdest);
  3969. exparg.lastp = &exparg.list;
  3970. /*
  3971. * TODO - EXP_REDIR
  3972. */
  3973. if (flag & EXP_FULL) {
  3974. ifsbreakup(p, &exparg);
  3975. *exparg.lastp = NULL;
  3976. exparg.lastp = &exparg.list;
  3977. expandmeta(exparg.list, flag);
  3978. } else {
  3979. if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
  3980. rmescapes(p);
  3981. sp = (struct strlist *)stalloc(sizeof (struct strlist));
  3982. sp->text = p;
  3983. *exparg.lastp = sp;
  3984. exparg.lastp = &sp->next;
  3985. }
  3986. if (ifsfirst.next)
  3987. ifsfree();
  3988. *exparg.lastp = NULL;
  3989. if (exparg.list) {
  3990. *arglist->lastp = exparg.list;
  3991. arglist->lastp = exparg.lastp;
  3992. }
  3993. }
  3994. /*
  3995. * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
  3996. * characters to allow for further processing. Otherwise treat
  3997. * $@ like $* since no splitting will be performed.
  3998. */
  3999. static void
  4000. argstr(char *p, int flag)
  4001. {
  4002. static const char spclchars[] = {
  4003. '=',
  4004. ':',
  4005. CTLQUOTEMARK,
  4006. CTLENDVAR,
  4007. CTLESC,
  4008. CTLVAR,
  4009. CTLBACKQ,
  4010. CTLBACKQ | CTLQUOTE,
  4011. #ifdef CONFIG_ASH_MATH_SUPPORT
  4012. CTLENDARI,
  4013. #endif
  4014. 0
  4015. };
  4016. const char *reject = spclchars;
  4017. int c;
  4018. int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
  4019. int breakall = flag & EXP_WORD;
  4020. int inquotes;
  4021. size_t length;
  4022. int startloc;
  4023. if (!(flag & EXP_VARTILDE)) {
  4024. reject += 2;
  4025. } else if (flag & EXP_VARTILDE2) {
  4026. reject++;
  4027. }
  4028. inquotes = 0;
  4029. length = 0;
  4030. if (flag & EXP_TILDE) {
  4031. char *q;
  4032. flag &= ~EXP_TILDE;
  4033. tilde:
  4034. q = p;
  4035. if (*q == CTLESC && (flag & EXP_QWORD))
  4036. q++;
  4037. if (*q == '~')
  4038. p = exptilde(p, q, flag);
  4039. }
  4040. start:
  4041. startloc = expdest - (char *)stackblock();
  4042. for (;;) {
  4043. length += strcspn(p + length, reject);
  4044. c = p[length];
  4045. if (c && (!(c & 0x80)
  4046. #ifdef CONFIG_ASH_MATH_SUPPORT
  4047. || c == CTLENDARI
  4048. #endif
  4049. )) {
  4050. /* c == '=' || c == ':' || c == CTLENDARI */
  4051. length++;
  4052. }
  4053. if (length > 0) {
  4054. int newloc;
  4055. expdest = stnputs(p, length, expdest);
  4056. newloc = expdest - (char *)stackblock();
  4057. if (breakall && !inquotes && newloc > startloc) {
  4058. recordregion(startloc, newloc, 0);
  4059. }
  4060. startloc = newloc;
  4061. }
  4062. p += length + 1;
  4063. length = 0;
  4064. switch (c) {
  4065. case '\0':
  4066. goto breakloop;
  4067. case '=':
  4068. if (flag & EXP_VARTILDE2) {
  4069. p--;
  4070. continue;
  4071. }
  4072. flag |= EXP_VARTILDE2;
  4073. reject++;
  4074. /* fall through */
  4075. case ':':
  4076. /*
  4077. * sort of a hack - expand tildes in variable
  4078. * assignments (after the first '=' and after ':'s).
  4079. */
  4080. if (*--p == '~') {
  4081. goto tilde;
  4082. }
  4083. continue;
  4084. }
  4085. switch (c) {
  4086. case CTLENDVAR: /* ??? */
  4087. goto breakloop;
  4088. case CTLQUOTEMARK:
  4089. /* "$@" syntax adherence hack */
  4090. if (
  4091. !inquotes &&
  4092. !memcmp(p, dolatstr, DOLATSTRLEN) &&
  4093. (p[4] == CTLQUOTEMARK || (
  4094. p[4] == CTLENDVAR &&
  4095. p[5] == CTLQUOTEMARK
  4096. ))
  4097. ) {
  4098. p = evalvar(p + 1, flag) + 1;
  4099. goto start;
  4100. }
  4101. inquotes = !inquotes;
  4102. addquote:
  4103. if (quotes) {
  4104. p--;
  4105. length++;
  4106. startloc++;
  4107. }
  4108. break;
  4109. case CTLESC:
  4110. startloc++;
  4111. length++;
  4112. goto addquote;
  4113. case CTLVAR:
  4114. p = evalvar(p, flag);
  4115. goto start;
  4116. case CTLBACKQ:
  4117. c = 0;
  4118. case CTLBACKQ|CTLQUOTE:
  4119. expbackq(argbackq->n, c, quotes);
  4120. argbackq = argbackq->next;
  4121. goto start;
  4122. #ifdef CONFIG_ASH_MATH_SUPPORT
  4123. case CTLENDARI:
  4124. p--;
  4125. expari(quotes);
  4126. goto start;
  4127. #endif
  4128. }
  4129. }
  4130. breakloop:
  4131. ;
  4132. }
  4133. static char *
  4134. exptilde(char *startp, char *p, int flag)
  4135. {
  4136. char c;
  4137. char *name;
  4138. struct passwd *pw;
  4139. const char *home;
  4140. int quotes = flag & (EXP_FULL | EXP_CASE);
  4141. int startloc;
  4142. name = p + 1;
  4143. while ((c = *++p) != '\0') {
  4144. switch(c) {
  4145. case CTLESC:
  4146. return (startp);
  4147. case CTLQUOTEMARK:
  4148. return (startp);
  4149. case ':':
  4150. if (flag & EXP_VARTILDE)
  4151. goto done;
  4152. break;
  4153. case '/':
  4154. case CTLENDVAR:
  4155. goto done;
  4156. }
  4157. }
  4158. done:
  4159. *p = '\0';
  4160. if (*name == '\0') {
  4161. if ((home = lookupvar(homestr)) == NULL)
  4162. goto lose;
  4163. } else {
  4164. if ((pw = getpwnam(name)) == NULL)
  4165. goto lose;
  4166. home = pw->pw_dir;
  4167. }
  4168. if (*home == '\0')
  4169. goto lose;
  4170. *p = c;
  4171. startloc = expdest - (char *)stackblock();
  4172. strtodest(home, SQSYNTAX, quotes);
  4173. recordregion(startloc, expdest - (char *)stackblock(), 0);
  4174. return (p);
  4175. lose:
  4176. *p = c;
  4177. return (startp);
  4178. }
  4179. static void
  4180. removerecordregions(int endoff)
  4181. {
  4182. if (ifslastp == NULL)
  4183. return;
  4184. if (ifsfirst.endoff > endoff) {
  4185. while (ifsfirst.next != NULL) {
  4186. struct ifsregion *ifsp;
  4187. INTOFF;
  4188. ifsp = ifsfirst.next->next;
  4189. ckfree(ifsfirst.next);
  4190. ifsfirst.next = ifsp;
  4191. INTON;
  4192. }
  4193. if (ifsfirst.begoff > endoff)
  4194. ifslastp = NULL;
  4195. else {
  4196. ifslastp = &ifsfirst;
  4197. ifsfirst.endoff = endoff;
  4198. }
  4199. return;
  4200. }
  4201. ifslastp = &ifsfirst;
  4202. while (ifslastp->next && ifslastp->next->begoff < endoff)
  4203. ifslastp=ifslastp->next;
  4204. while (ifslastp->next != NULL) {
  4205. struct ifsregion *ifsp;
  4206. INTOFF;
  4207. ifsp = ifslastp->next->next;
  4208. ckfree(ifslastp->next);
  4209. ifslastp->next = ifsp;
  4210. INTON;
  4211. }
  4212. if (ifslastp->endoff > endoff)
  4213. ifslastp->endoff = endoff;
  4214. }
  4215. #ifdef CONFIG_ASH_MATH_SUPPORT
  4216. /*
  4217. * Expand arithmetic expression. Backup to start of expression,
  4218. * evaluate, place result in (backed up) result, adjust string position.
  4219. */
  4220. void
  4221. expari(int quotes)
  4222. {
  4223. char *p, *start;
  4224. int begoff;
  4225. int flag;
  4226. int len;
  4227. /* ifsfree(); */
  4228. /*
  4229. * This routine is slightly over-complicated for
  4230. * efficiency. Next we scan backwards looking for the
  4231. * start of arithmetic.
  4232. */
  4233. start = stackblock();
  4234. p = expdest - 1;
  4235. *p = '\0';
  4236. p--;
  4237. do {
  4238. int esc;
  4239. while (*p != CTLARI) {
  4240. p--;
  4241. #ifdef DEBUG
  4242. if (p < start) {
  4243. error("missing CTLARI (shouldn't happen)");
  4244. }
  4245. #endif
  4246. }
  4247. esc = esclen(start, p);
  4248. if (!(esc % 2)) {
  4249. break;
  4250. }
  4251. p -= esc + 1;
  4252. } while (1);
  4253. begoff = p - start;
  4254. removerecordregions(begoff);
  4255. flag = p[1];
  4256. expdest = p;
  4257. if (quotes)
  4258. rmescapes(p + 2);
  4259. len = cvtnum(dash_arith(p + 2));
  4260. if (flag != '"')
  4261. recordregion(begoff, begoff + len, 0);
  4262. }
  4263. #endif
  4264. /*
  4265. * Expand stuff in backwards quotes.
  4266. */
  4267. static void
  4268. expbackq(union node *cmd, int quoted, int quotes)
  4269. {
  4270. struct backcmd in;
  4271. int i;
  4272. char buf[128];
  4273. char *p;
  4274. char *dest;
  4275. int startloc;
  4276. int syntax = quoted? DQSYNTAX : BASESYNTAX;
  4277. struct stackmark smark;
  4278. INTOFF;
  4279. setstackmark(&smark);
  4280. dest = expdest;
  4281. startloc = dest - (char *)stackblock();
  4282. grabstackstr(dest);
  4283. evalbackcmd(cmd, (struct backcmd *) &in);
  4284. popstackmark(&smark);
  4285. p = in.buf;
  4286. i = in.nleft;
  4287. if (i == 0)
  4288. goto read;
  4289. for (;;) {
  4290. memtodest(p, i, syntax, quotes);
  4291. read:
  4292. if (in.fd < 0)
  4293. break;
  4294. i = safe_read(in.fd, buf, sizeof buf);
  4295. TRACE(("expbackq: read returns %d\n", i));
  4296. if (i <= 0)
  4297. break;
  4298. p = buf;
  4299. }
  4300. if (in.buf)
  4301. ckfree(in.buf);
  4302. if (in.fd >= 0) {
  4303. close(in.fd);
  4304. back_exitstatus = waitforjob(in.jp);
  4305. }
  4306. INTON;
  4307. /* Eat all trailing newlines */
  4308. dest = expdest;
  4309. for (; dest > (char *)stackblock() && dest[-1] == '\n';)
  4310. STUNPUTC(dest);
  4311. expdest = dest;
  4312. if (quoted == 0)
  4313. recordregion(startloc, dest - (char *)stackblock(), 0);
  4314. TRACE(("evalbackq: size=%d: \"%.*s\"\n",
  4315. (dest - (char *)stackblock()) - startloc,
  4316. (dest - (char *)stackblock()) - startloc,
  4317. stackblock() + startloc));
  4318. }
  4319. static char *
  4320. scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
  4321. int zero)
  4322. {
  4323. char *loc;
  4324. char *loc2;
  4325. char c;
  4326. loc = startp;
  4327. loc2 = rmesc;
  4328. do {
  4329. int match;
  4330. const char *s = loc2;
  4331. c = *loc2;
  4332. if (zero) {
  4333. *loc2 = '\0';
  4334. s = rmesc;
  4335. }
  4336. match = pmatch(str, s);
  4337. *loc2 = c;
  4338. if (match)
  4339. return loc;
  4340. if (quotes && *loc == CTLESC)
  4341. loc++;
  4342. loc++;
  4343. loc2++;
  4344. } while (c);
  4345. return 0;
  4346. }
  4347. static char *
  4348. scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
  4349. int zero)
  4350. {
  4351. int esc = 0;
  4352. char *loc;
  4353. char *loc2;
  4354. for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
  4355. int match;
  4356. char c = *loc2;
  4357. const char *s = loc2;
  4358. if (zero) {
  4359. *loc2 = '\0';
  4360. s = rmesc;
  4361. }
  4362. match = pmatch(str, s);
  4363. *loc2 = c;
  4364. if (match)
  4365. return loc;
  4366. loc--;
  4367. if (quotes) {
  4368. if (--esc < 0) {
  4369. esc = esclen(startp, loc);
  4370. }
  4371. if (esc % 2) {
  4372. esc--;
  4373. loc--;
  4374. }
  4375. }
  4376. }
  4377. return 0;
  4378. }
  4379. static const char *
  4380. subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
  4381. {
  4382. char *startp;
  4383. char *loc;
  4384. int saveherefd = herefd;
  4385. struct nodelist *saveargbackq = argbackq;
  4386. int amount;
  4387. char *rmesc, *rmescend;
  4388. int zero;
  4389. char *(*scan)(char *, char *, char *, char *, int , int);
  4390. herefd = -1;
  4391. argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
  4392. STPUTC('\0', expdest);
  4393. herefd = saveherefd;
  4394. argbackq = saveargbackq;
  4395. startp = stackblock() + startloc;
  4396. switch (subtype) {
  4397. case VSASSIGN:
  4398. setvar(str, startp, 0);
  4399. amount = startp - expdest;
  4400. STADJUST(amount, expdest);
  4401. return startp;
  4402. case VSQUESTION:
  4403. varunset(p, str, startp, varflags);
  4404. /* NOTREACHED */
  4405. }
  4406. subtype -= VSTRIMRIGHT;
  4407. #ifdef DEBUG
  4408. if (subtype < 0 || subtype > 3)
  4409. abort();
  4410. #endif
  4411. rmesc = startp;
  4412. rmescend = stackblock() + strloc;
  4413. if (quotes) {
  4414. rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
  4415. if (rmesc != startp) {
  4416. rmescend = expdest;
  4417. startp = stackblock() + startloc;
  4418. }
  4419. }
  4420. rmescend--;
  4421. str = stackblock() + strloc;
  4422. preglob(str, varflags & VSQUOTE, 0);
  4423. /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
  4424. zero = subtype >> 1;
  4425. /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
  4426. scan = (subtype & 1) ^ zero ? scanleft : scanright;
  4427. loc = scan(startp, rmesc, rmescend, str, quotes, zero);
  4428. if (loc) {
  4429. if (zero) {
  4430. memmove(startp, loc, str - loc);
  4431. loc = startp + (str - loc) - 1;
  4432. }
  4433. *loc = '\0';
  4434. amount = loc - expdest;
  4435. STADJUST(amount, expdest);
  4436. }
  4437. return loc;
  4438. }
  4439. /*
  4440. * Expand a variable, and return a pointer to the next character in the
  4441. * input string.
  4442. */
  4443. static char *
  4444. evalvar(char *p, int flag)
  4445. {
  4446. int subtype;
  4447. int varflags;
  4448. char *var;
  4449. int patloc;
  4450. int c;
  4451. int startloc;
  4452. ssize_t varlen;
  4453. int easy;
  4454. int quotes;
  4455. int quoted;
  4456. quotes = flag & (EXP_FULL | EXP_CASE);
  4457. varflags = *p++;
  4458. subtype = varflags & VSTYPE;
  4459. quoted = varflags & VSQUOTE;
  4460. var = p;
  4461. easy = (!quoted || (*var == '@' && shellparam.nparam));
  4462. startloc = expdest - (char *)stackblock();
  4463. p = strchr(p, '=') + 1;
  4464. again:
  4465. varlen = varvalue(var, varflags, flag);
  4466. if (varflags & VSNUL)
  4467. varlen--;
  4468. if (subtype == VSPLUS) {
  4469. varlen = -1 - varlen;
  4470. goto vsplus;
  4471. }
  4472. if (subtype == VSMINUS) {
  4473. vsplus:
  4474. if (varlen < 0) {
  4475. argstr(
  4476. p, flag | EXP_TILDE |
  4477. (quoted ? EXP_QWORD : EXP_WORD)
  4478. );
  4479. goto end;
  4480. }
  4481. if (easy)
  4482. goto record;
  4483. goto end;
  4484. }
  4485. if (subtype == VSASSIGN || subtype == VSQUESTION) {
  4486. if (varlen < 0) {
  4487. if (subevalvar(p, var, 0, subtype, startloc,
  4488. varflags, 0)) {
  4489. varflags &= ~VSNUL;
  4490. /*
  4491. * Remove any recorded regions beyond
  4492. * start of variable
  4493. */
  4494. removerecordregions(startloc);
  4495. goto again;
  4496. }
  4497. goto end;
  4498. }
  4499. if (easy)
  4500. goto record;
  4501. goto end;
  4502. }
  4503. if (varlen < 0 && uflag)
  4504. varunset(p, var, 0, 0);
  4505. if (subtype == VSLENGTH) {
  4506. cvtnum(varlen > 0 ? varlen : 0);
  4507. goto record;
  4508. }
  4509. if (subtype == VSNORMAL) {
  4510. if (!easy)
  4511. goto end;
  4512. record:
  4513. recordregion(startloc, expdest - (char *)stackblock(), quoted);
  4514. goto end;
  4515. }
  4516. #ifdef DEBUG
  4517. switch (subtype) {
  4518. case VSTRIMLEFT:
  4519. case VSTRIMLEFTMAX:
  4520. case VSTRIMRIGHT:
  4521. case VSTRIMRIGHTMAX:
  4522. break;
  4523. default:
  4524. abort();
  4525. }
  4526. #endif
  4527. if (varlen >= 0) {
  4528. /*
  4529. * Terminate the string and start recording the pattern
  4530. * right after it
  4531. */
  4532. STPUTC('\0', expdest);
  4533. patloc = expdest - (char *)stackblock();
  4534. if (subevalvar(p, NULL, patloc, subtype,
  4535. startloc, varflags, quotes) == 0) {
  4536. int amount = expdest - (
  4537. (char *)stackblock() + patloc - 1
  4538. );
  4539. STADJUST(-amount, expdest);
  4540. }
  4541. /* Remove any recorded regions beyond start of variable */
  4542. removerecordregions(startloc);
  4543. goto record;
  4544. }
  4545. end:
  4546. if (subtype != VSNORMAL) { /* skip to end of alternative */
  4547. int nesting = 1;
  4548. for (;;) {
  4549. if ((c = *p++) == CTLESC)
  4550. p++;
  4551. else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
  4552. if (varlen >= 0)
  4553. argbackq = argbackq->next;
  4554. } else if (c == CTLVAR) {
  4555. if ((*p++ & VSTYPE) != VSNORMAL)
  4556. nesting++;
  4557. } else if (c == CTLENDVAR) {
  4558. if (--nesting == 0)
  4559. break;
  4560. }
  4561. }
  4562. }
  4563. return p;
  4564. }
  4565. /*
  4566. * Put a string on the stack.
  4567. */
  4568. static void
  4569. memtodest(const char *p, size_t len, int syntax, int quotes) {
  4570. char *q = expdest;
  4571. q = makestrspace(len * 2, q);
  4572. while (len--) {
  4573. int c = *p++;
  4574. if (!c)
  4575. continue;
  4576. if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
  4577. USTPUTC(CTLESC, q);
  4578. USTPUTC(c, q);
  4579. }
  4580. expdest = q;
  4581. }
  4582. static void
  4583. strtodest(const char *p, int syntax, int quotes)
  4584. {
  4585. memtodest(p, strlen(p), syntax, quotes);
  4586. }
  4587. /*
  4588. * Add the value of a specialized variable to the stack string.
  4589. */
  4590. static ssize_t
  4591. varvalue(char *name, int varflags, int flags)
  4592. {
  4593. int num;
  4594. char *p;
  4595. int i;
  4596. int sep = 0;
  4597. int sepq = 0;
  4598. ssize_t len = 0;
  4599. char **ap;
  4600. int syntax;
  4601. int quoted = varflags & VSQUOTE;
  4602. int subtype = varflags & VSTYPE;
  4603. int quotes = flags & (EXP_FULL | EXP_CASE);
  4604. if (quoted && (flags & EXP_FULL))
  4605. sep = 1 << CHAR_BIT;
  4606. syntax = quoted ? DQSYNTAX : BASESYNTAX;
  4607. switch (*name) {
  4608. case '$':
  4609. num = rootpid;
  4610. goto numvar;
  4611. case '?':
  4612. num = exitstatus;
  4613. goto numvar;
  4614. case '#':
  4615. num = shellparam.nparam;
  4616. goto numvar;
  4617. case '!':
  4618. num = backgndpid;
  4619. if (num == 0)
  4620. return -1;
  4621. numvar:
  4622. len = cvtnum(num);
  4623. break;
  4624. case '-':
  4625. p = makestrspace(NOPTS, expdest);
  4626. for (i = NOPTS - 1; i >= 0; i--) {
  4627. if (optlist[i]) {
  4628. USTPUTC(optletters(i), p);
  4629. len++;
  4630. }
  4631. }
  4632. expdest = p;
  4633. break;
  4634. case '@':
  4635. if (sep)
  4636. goto param;
  4637. /* fall through */
  4638. case '*':
  4639. sep = ifsset() ? ifsval()[0] : ' ';
  4640. if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
  4641. sepq = 1;
  4642. param:
  4643. if (!(ap = shellparam.p))
  4644. return -1;
  4645. while ((p = *ap++)) {
  4646. size_t partlen;
  4647. partlen = strlen(p);
  4648. len += partlen;
  4649. if (len > partlen && sep) {
  4650. char *q;
  4651. len++;
  4652. if (subtype == VSPLUS || subtype == VSLENGTH) {
  4653. continue;
  4654. }
  4655. q = expdest;
  4656. if (sepq)
  4657. STPUTC(CTLESC, q);
  4658. STPUTC(sep, q);
  4659. expdest = q;
  4660. }
  4661. if (!(subtype == VSPLUS || subtype == VSLENGTH))
  4662. memtodest(p, partlen, syntax, quotes);
  4663. }
  4664. return len;
  4665. case '0':
  4666. case '1':
  4667. case '2':
  4668. case '3':
  4669. case '4':
  4670. case '5':
  4671. case '6':
  4672. case '7':
  4673. case '8':
  4674. case '9':
  4675. num = atoi(name);
  4676. if (num < 0 || num > shellparam.nparam)
  4677. return -1;
  4678. p = num ? shellparam.p[num - 1] : arg0;
  4679. goto value;
  4680. default:
  4681. p = lookupvar(name);
  4682. value:
  4683. if (!p)
  4684. return -1;
  4685. len = strlen(p);
  4686. if (!(subtype == VSPLUS || subtype == VSLENGTH))
  4687. memtodest(p, len, syntax, quotes);
  4688. return len;
  4689. }
  4690. if (subtype == VSPLUS || subtype == VSLENGTH)
  4691. STADJUST(-len, expdest);
  4692. return len;
  4693. }
  4694. /*
  4695. * Record the fact that we have to scan this region of the
  4696. * string for IFS characters.
  4697. */
  4698. static void
  4699. recordregion(int start, int end, int nulonly)
  4700. {
  4701. struct ifsregion *ifsp;
  4702. if (ifslastp == NULL) {
  4703. ifsp = &ifsfirst;
  4704. } else {
  4705. INTOFF;
  4706. ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
  4707. ifsp->next = NULL;
  4708. ifslastp->next = ifsp;
  4709. INTON;
  4710. }
  4711. ifslastp = ifsp;
  4712. ifslastp->begoff = start;
  4713. ifslastp->endoff = end;
  4714. ifslastp->nulonly = nulonly;
  4715. }
  4716. /*
  4717. * Break the argument string into pieces based upon IFS and add the
  4718. * strings to the argument list. The regions of the string to be
  4719. * searched for IFS characters have been stored by recordregion.
  4720. */
  4721. static void
  4722. ifsbreakup(char *string, struct arglist *arglist)
  4723. {
  4724. struct ifsregion *ifsp;
  4725. struct strlist *sp;
  4726. char *start;
  4727. char *p;
  4728. char *q;
  4729. const char *ifs, *realifs;
  4730. int ifsspc;
  4731. int nulonly;
  4732. start = string;
  4733. if (ifslastp != NULL) {
  4734. ifsspc = 0;
  4735. nulonly = 0;
  4736. realifs = ifsset() ? ifsval() : defifs;
  4737. ifsp = &ifsfirst;
  4738. do {
  4739. p = string + ifsp->begoff;
  4740. nulonly = ifsp->nulonly;
  4741. ifs = nulonly ? nullstr : realifs;
  4742. ifsspc = 0;
  4743. while (p < string + ifsp->endoff) {
  4744. q = p;
  4745. if (*p == CTLESC)
  4746. p++;
  4747. if (strchr(ifs, *p)) {
  4748. if (!nulonly)
  4749. ifsspc = (strchr(defifs, *p) != NULL);
  4750. /* Ignore IFS whitespace at start */
  4751. if (q == start && ifsspc) {
  4752. p++;
  4753. start = p;
  4754. continue;
  4755. }
  4756. *q = '\0';
  4757. sp = (struct strlist *)stalloc(sizeof *sp);
  4758. sp->text = start;
  4759. *arglist->lastp = sp;
  4760. arglist->lastp = &sp->next;
  4761. p++;
  4762. if (!nulonly) {
  4763. for (;;) {
  4764. if (p >= string + ifsp->endoff) {
  4765. break;
  4766. }
  4767. q = p;
  4768. if (*p == CTLESC)
  4769. p++;
  4770. if (strchr(ifs, *p) == NULL ) {
  4771. p = q;
  4772. break;
  4773. } else if (strchr(defifs, *p) == NULL) {
  4774. if (ifsspc) {
  4775. p++;
  4776. ifsspc = 0;
  4777. } else {
  4778. p = q;
  4779. break;
  4780. }
  4781. } else
  4782. p++;
  4783. }
  4784. }
  4785. start = p;
  4786. } else
  4787. p++;
  4788. }
  4789. } while ((ifsp = ifsp->next) != NULL);
  4790. if (nulonly)
  4791. goto add;
  4792. }
  4793. if (!*start)
  4794. return;
  4795. add:
  4796. sp = (struct strlist *)stalloc(sizeof *sp);
  4797. sp->text = start;
  4798. *arglist->lastp = sp;
  4799. arglist->lastp = &sp->next;
  4800. }
  4801. static void
  4802. ifsfree(void)
  4803. {
  4804. struct ifsregion *p;
  4805. INTOFF;
  4806. p = ifsfirst.next;
  4807. do {
  4808. struct ifsregion *ifsp;
  4809. ifsp = p->next;
  4810. ckfree(p);
  4811. p = ifsp;
  4812. } while (p);
  4813. ifslastp = NULL;
  4814. ifsfirst.next = NULL;
  4815. INTON;
  4816. }
  4817. static void expmeta(char *, char *);
  4818. static struct strlist *expsort(struct strlist *);
  4819. static struct strlist *msort(struct strlist *, int);
  4820. static char *expdir;
  4821. static void
  4822. expandmeta(struct strlist *str, int flag)
  4823. {
  4824. static const char metachars[] = {
  4825. '*', '?', '[', 0
  4826. };
  4827. /* TODO - EXP_REDIR */
  4828. while (str) {
  4829. struct strlist **savelastp;
  4830. struct strlist *sp;
  4831. char *p;
  4832. if (fflag)
  4833. goto nometa;
  4834. if (!strpbrk(str->text, metachars))
  4835. goto nometa;
  4836. savelastp = exparg.lastp;
  4837. INTOFF;
  4838. p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
  4839. {
  4840. int i = strlen(str->text);
  4841. expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
  4842. }
  4843. expmeta(expdir, p);
  4844. ckfree(expdir);
  4845. if (p != str->text)
  4846. ckfree(p);
  4847. INTON;
  4848. if (exparg.lastp == savelastp) {
  4849. /*
  4850. * no matches
  4851. */
  4852. nometa:
  4853. *exparg.lastp = str;
  4854. rmescapes(str->text);
  4855. exparg.lastp = &str->next;
  4856. } else {
  4857. *exparg.lastp = NULL;
  4858. *savelastp = sp = expsort(*savelastp);
  4859. while (sp->next != NULL)
  4860. sp = sp->next;
  4861. exparg.lastp = &sp->next;
  4862. }
  4863. str = str->next;
  4864. }
  4865. }
  4866. /*
  4867. * Add a file name to the list.
  4868. */
  4869. static void
  4870. addfname(const char *name)
  4871. {
  4872. struct strlist *sp;
  4873. sp = (struct strlist *)stalloc(sizeof *sp);
  4874. sp->text = sstrdup(name);
  4875. *exparg.lastp = sp;
  4876. exparg.lastp = &sp->next;
  4877. }
  4878. /*
  4879. * Do metacharacter (i.e. *, ?, [...]) expansion.
  4880. */
  4881. static void
  4882. expmeta(char *enddir, char *name)
  4883. {
  4884. char *p;
  4885. const char *cp;
  4886. char *start;
  4887. char *endname;
  4888. int metaflag;
  4889. struct stat statb;
  4890. DIR *dirp;
  4891. struct dirent *dp;
  4892. int atend;
  4893. int matchdot;
  4894. metaflag = 0;
  4895. start = name;
  4896. for (p = name; *p; p++) {
  4897. if (*p == '*' || *p == '?')
  4898. metaflag = 1;
  4899. else if (*p == '[') {
  4900. char *q = p + 1;
  4901. if (*q == '!')
  4902. q++;
  4903. for (;;) {
  4904. if (*q == '\\')
  4905. q++;
  4906. if (*q == '/' || *q == '\0')
  4907. break;
  4908. if (*++q == ']') {
  4909. metaflag = 1;
  4910. break;
  4911. }
  4912. }
  4913. } else if (*p == '\\')
  4914. p++;
  4915. else if (*p == '/') {
  4916. if (metaflag)
  4917. goto out;
  4918. start = p + 1;
  4919. }
  4920. }
  4921. out:
  4922. if (metaflag == 0) { /* we've reached the end of the file name */
  4923. if (enddir != expdir)
  4924. metaflag++;
  4925. p = name;
  4926. do {
  4927. if (*p == '\\')
  4928. p++;
  4929. *enddir++ = *p;
  4930. } while (*p++);
  4931. if (metaflag == 0 || lstat(expdir, &statb) >= 0)
  4932. addfname(expdir);
  4933. return;
  4934. }
  4935. endname = p;
  4936. if (name < start) {
  4937. p = name;
  4938. do {
  4939. if (*p == '\\')
  4940. p++;
  4941. *enddir++ = *p++;
  4942. } while (p < start);
  4943. }
  4944. if (enddir == expdir) {
  4945. cp = ".";
  4946. } else if (enddir == expdir + 1 && *expdir == '/') {
  4947. cp = "/";
  4948. } else {
  4949. cp = expdir;
  4950. enddir[-1] = '\0';
  4951. }
  4952. if ((dirp = opendir(cp)) == NULL)
  4953. return;
  4954. if (enddir != expdir)
  4955. enddir[-1] = '/';
  4956. if (*endname == 0) {
  4957. atend = 1;
  4958. } else {
  4959. atend = 0;
  4960. *endname++ = '\0';
  4961. }
  4962. matchdot = 0;
  4963. p = start;
  4964. if (*p == '\\')
  4965. p++;
  4966. if (*p == '.')
  4967. matchdot++;
  4968. while (! intpending && (dp = readdir(dirp)) != NULL) {
  4969. if (dp->d_name[0] == '.' && ! matchdot)
  4970. continue;
  4971. if (pmatch(start, dp->d_name)) {
  4972. if (atend) {
  4973. scopy(dp->d_name, enddir);
  4974. addfname(expdir);
  4975. } else {
  4976. for (p = enddir, cp = dp->d_name;
  4977. (*p++ = *cp++) != '\0';)
  4978. continue;
  4979. p[-1] = '/';
  4980. expmeta(p, endname);
  4981. }
  4982. }
  4983. }
  4984. closedir(dirp);
  4985. if (! atend)
  4986. endname[-1] = '/';
  4987. }
  4988. /*
  4989. * Sort the results of file name expansion. It calculates the number of
  4990. * strings to sort and then calls msort (short for merge sort) to do the
  4991. * work.
  4992. */
  4993. static struct strlist *
  4994. expsort(struct strlist *str)
  4995. {
  4996. int len;
  4997. struct strlist *sp;
  4998. len = 0;
  4999. for (sp = str ; sp ; sp = sp->next)
  5000. len++;
  5001. return msort(str, len);
  5002. }
  5003. static struct strlist *
  5004. msort(struct strlist *list, int len)
  5005. {
  5006. struct strlist *p, *q = NULL;
  5007. struct strlist **lpp;
  5008. int half;
  5009. int n;
  5010. if (len <= 1)
  5011. return list;
  5012. half = len >> 1;
  5013. p = list;
  5014. for (n = half ; --n >= 0 ; ) {
  5015. q = p;
  5016. p = p->next;
  5017. }
  5018. q->next = NULL; /* terminate first half of list */
  5019. q = msort(list, half); /* sort first half of list */
  5020. p = msort(p, len - half); /* sort second half */
  5021. lpp = &list;
  5022. for (;;) {
  5023. #ifdef CONFIG_LOCALE_SUPPORT
  5024. if (strcoll(p->text, q->text) < 0)
  5025. #else
  5026. if (strcmp(p->text, q->text) < 0)
  5027. #endif
  5028. {
  5029. *lpp = p;
  5030. lpp = &p->next;
  5031. if ((p = *lpp) == NULL) {
  5032. *lpp = q;
  5033. break;
  5034. }
  5035. } else {
  5036. *lpp = q;
  5037. lpp = &q->next;
  5038. if ((q = *lpp) == NULL) {
  5039. *lpp = p;
  5040. break;
  5041. }
  5042. }
  5043. }
  5044. return list;
  5045. }
  5046. /*
  5047. * Returns true if the pattern matches the string.
  5048. */
  5049. static inline int
  5050. patmatch(char *pattern, const char *string)
  5051. {
  5052. return pmatch(preglob(pattern, 0, 0), string);
  5053. }
  5054. /*
  5055. * Remove any CTLESC characters from a string.
  5056. */
  5057. static char *
  5058. _rmescapes(char *str, int flag)
  5059. {
  5060. char *p, *q, *r;
  5061. static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
  5062. unsigned inquotes;
  5063. int notescaped;
  5064. int globbing;
  5065. p = strpbrk(str, qchars);
  5066. if (!p) {
  5067. return str;
  5068. }
  5069. q = p;
  5070. r = str;
  5071. if (flag & RMESCAPE_ALLOC) {
  5072. size_t len = p - str;
  5073. size_t fulllen = len + strlen(p) + 1;
  5074. if (flag & RMESCAPE_GROW) {
  5075. r = makestrspace(fulllen, expdest);
  5076. } else if (flag & RMESCAPE_HEAP) {
  5077. r = ckmalloc(fulllen);
  5078. } else {
  5079. r = stalloc(fulllen);
  5080. }
  5081. q = r;
  5082. if (len > 0) {
  5083. q = mempcpy(q, str, len);
  5084. }
  5085. }
  5086. inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
  5087. globbing = flag & RMESCAPE_GLOB;
  5088. notescaped = globbing;
  5089. while (*p) {
  5090. if (*p == CTLQUOTEMARK) {
  5091. inquotes = ~inquotes;
  5092. p++;
  5093. notescaped = globbing;
  5094. continue;
  5095. }
  5096. if (*p == '\\') {
  5097. /* naked back slash */
  5098. notescaped = 0;
  5099. goto copy;
  5100. }
  5101. if (*p == CTLESC) {
  5102. p++;
  5103. if (notescaped && inquotes && *p != '/') {
  5104. *q++ = '\\';
  5105. }
  5106. }
  5107. notescaped = globbing;
  5108. copy:
  5109. *q++ = *p++;
  5110. }
  5111. *q = '\0';
  5112. if (flag & RMESCAPE_GROW) {
  5113. expdest = r;
  5114. STADJUST(q - r + 1, expdest);
  5115. }
  5116. return r;
  5117. }
  5118. /*
  5119. * See if a pattern matches in a case statement.
  5120. */
  5121. int
  5122. casematch(union node *pattern, char *val)
  5123. {
  5124. struct stackmark smark;
  5125. int result;
  5126. setstackmark(&smark);
  5127. argbackq = pattern->narg.backquote;
  5128. STARTSTACKSTR(expdest);
  5129. ifslastp = NULL;
  5130. argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
  5131. STACKSTRNUL(expdest);
  5132. result = patmatch(stackblock(), val);
  5133. popstackmark(&smark);
  5134. return result;
  5135. }
  5136. /*
  5137. * Our own itoa().
  5138. */
  5139. static int
  5140. cvtnum(arith_t num)
  5141. {
  5142. int len;
  5143. expdest = makestrspace(32, expdest);
  5144. #ifdef CONFIG_ASH_MATH_SUPPORT_64
  5145. len = fmtstr(expdest, 32, "%lld", (long long) num);
  5146. #else
  5147. len = fmtstr(expdest, 32, "%ld", num);
  5148. #endif
  5149. STADJUST(len, expdest);
  5150. return len;
  5151. }
  5152. static void
  5153. varunset(const char *end, const char *var, const char *umsg, int varflags)
  5154. {
  5155. const char *msg;
  5156. const char *tail;
  5157. tail = nullstr;
  5158. msg = "parameter not set";
  5159. if (umsg) {
  5160. if (*end == CTLENDVAR) {
  5161. if (varflags & VSNUL)
  5162. tail = " or null";
  5163. } else
  5164. msg = umsg;
  5165. }
  5166. error("%.*s: %s%s", end - var - 1, var, msg, tail);
  5167. }
  5168. /* $NetBSD: input.c,v 1.37 2002/11/24 22:35:40 christos Exp $ */
  5169. /*
  5170. * This implements the input routines used by the parser.
  5171. */
  5172. #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
  5173. #define IBUFSIZ (BUFSIZ + 1)
  5174. static void pushfile(void);
  5175. /*
  5176. * Read a character from the script, returning PEOF on end of file.
  5177. * Nul characters in the input are silently discarded.
  5178. */
  5179. #define pgetc_as_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
  5180. #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
  5181. #define pgetc_macro() pgetc()
  5182. static int
  5183. pgetc(void)
  5184. {
  5185. return pgetc_as_macro();
  5186. }
  5187. #else
  5188. #define pgetc_macro() pgetc_as_macro()
  5189. static int
  5190. pgetc(void)
  5191. {
  5192. return pgetc_macro();
  5193. }
  5194. #endif
  5195. /*
  5196. * Same as pgetc(), but ignores PEOA.
  5197. */
  5198. #ifdef CONFIG_ASH_ALIAS
  5199. static int pgetc2(void)
  5200. {
  5201. int c;
  5202. do {
  5203. c = pgetc_macro();
  5204. } while (c == PEOA);
  5205. return c;
  5206. }
  5207. #else
  5208. static inline int pgetc2(void)
  5209. {
  5210. return pgetc_macro();
  5211. }
  5212. #endif
  5213. /*
  5214. * Read a line from the script.
  5215. */
  5216. static inline char *
  5217. pfgets(char *line, int len)
  5218. {
  5219. char *p = line;
  5220. int nleft = len;
  5221. int c;
  5222. while (--nleft > 0) {
  5223. c = pgetc2();
  5224. if (c == PEOF) {
  5225. if (p == line)
  5226. return NULL;
  5227. break;
  5228. }
  5229. *p++ = c;
  5230. if (c == '\n')
  5231. break;
  5232. }
  5233. *p = '\0';
  5234. return line;
  5235. }
  5236. #ifdef CONFIG_FEATURE_COMMAND_EDITING
  5237. static const char *cmdedit_prompt;
  5238. static inline void putprompt(const char *s)
  5239. {
  5240. cmdedit_prompt = s;
  5241. }
  5242. #else
  5243. static inline void putprompt(const char *s)
  5244. {
  5245. out2str(s);
  5246. }
  5247. #endif
  5248. static inline int
  5249. preadfd(void)
  5250. {
  5251. int nr;
  5252. char *buf = parsefile->buf;
  5253. parsenextc = buf;
  5254. retry:
  5255. #ifdef CONFIG_FEATURE_COMMAND_EDITING
  5256. if (!iflag || parsefile->fd)
  5257. nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
  5258. else {
  5259. #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
  5260. cmdedit_path_lookup = pathval();
  5261. #endif
  5262. nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
  5263. if(nr == 0) {
  5264. /* Ctrl+C presend */
  5265. if(trap[SIGINT]) {
  5266. buf[0] = '\n';
  5267. buf[1] = 0;
  5268. raise(SIGINT);
  5269. return 1;
  5270. }
  5271. goto retry;
  5272. }
  5273. if(nr < 0 && errno == 0) {
  5274. /* Ctrl+D presend */
  5275. nr = 0;
  5276. }
  5277. }
  5278. #else
  5279. nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
  5280. #endif
  5281. if (nr < 0) {
  5282. if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
  5283. int flags = fcntl(0, F_GETFL, 0);
  5284. if (flags >= 0 && flags & O_NONBLOCK) {
  5285. flags &=~ O_NONBLOCK;
  5286. if (fcntl(0, F_SETFL, flags) >= 0) {
  5287. out2str("sh: turning off NDELAY mode\n");
  5288. goto retry;
  5289. }
  5290. }
  5291. }
  5292. }
  5293. return nr;
  5294. }
  5295. /*
  5296. * Refill the input buffer and return the next input character:
  5297. *
  5298. * 1) If a string was pushed back on the input, pop it;
  5299. * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
  5300. * from a string so we can't refill the buffer, return EOF.
  5301. * 3) If the is more stuff in this buffer, use it else call read to fill it.
  5302. * 4) Process input up to the next newline, deleting nul characters.
  5303. */
  5304. int
  5305. preadbuffer(void)
  5306. {
  5307. char *p, *q;
  5308. int more;
  5309. char savec;
  5310. while (parsefile->strpush) {
  5311. #ifdef CONFIG_ASH_ALIAS
  5312. if (parsenleft == -1 && parsefile->strpush->ap &&
  5313. parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
  5314. return PEOA;
  5315. }
  5316. #endif
  5317. popstring();
  5318. if (--parsenleft >= 0)
  5319. return (*parsenextc++);
  5320. }
  5321. if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
  5322. return PEOF;
  5323. flushall();
  5324. again:
  5325. if (parselleft <= 0) {
  5326. if ((parselleft = preadfd()) <= 0) {
  5327. parselleft = parsenleft = EOF_NLEFT;
  5328. return PEOF;
  5329. }
  5330. }
  5331. q = p = parsenextc;
  5332. /* delete nul characters */
  5333. for (more = 1; more;) {
  5334. switch (*p) {
  5335. case '\0':
  5336. p++; /* Skip nul */
  5337. goto check;
  5338. case '\n':
  5339. parsenleft = q - parsenextc;
  5340. more = 0; /* Stop processing here */
  5341. break;
  5342. }
  5343. *q++ = *p++;
  5344. check:
  5345. if (--parselleft <= 0 && more) {
  5346. parsenleft = q - parsenextc - 1;
  5347. if (parsenleft < 0)
  5348. goto again;
  5349. more = 0;
  5350. }
  5351. }
  5352. savec = *q;
  5353. *q = '\0';
  5354. if (vflag) {
  5355. out2str(parsenextc);
  5356. }
  5357. *q = savec;
  5358. return *parsenextc++;
  5359. }
  5360. /*
  5361. * Undo the last call to pgetc. Only one character may be pushed back.
  5362. * PEOF may be pushed back.
  5363. */
  5364. void
  5365. pungetc(void)
  5366. {
  5367. parsenleft++;
  5368. parsenextc--;
  5369. }
  5370. /*
  5371. * Push a string back onto the input at this current parsefile level.
  5372. * We handle aliases this way.
  5373. */
  5374. void
  5375. pushstring(char *s, void *ap)
  5376. {
  5377. struct strpush *sp;
  5378. size_t len;
  5379. len = strlen(s);
  5380. INTOFF;
  5381. /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
  5382. if (parsefile->strpush) {
  5383. sp = ckmalloc(sizeof (struct strpush));
  5384. sp->prev = parsefile->strpush;
  5385. parsefile->strpush = sp;
  5386. } else
  5387. sp = parsefile->strpush = &(parsefile->basestrpush);
  5388. sp->prevstring = parsenextc;
  5389. sp->prevnleft = parsenleft;
  5390. #ifdef CONFIG_ASH_ALIAS
  5391. sp->ap = (struct alias *)ap;
  5392. if (ap) {
  5393. ((struct alias *)ap)->flag |= ALIASINUSE;
  5394. sp->string = s;
  5395. }
  5396. #endif
  5397. parsenextc = s;
  5398. parsenleft = len;
  5399. INTON;
  5400. }
  5401. void
  5402. popstring(void)
  5403. {
  5404. struct strpush *sp = parsefile->strpush;
  5405. INTOFF;
  5406. #ifdef CONFIG_ASH_ALIAS
  5407. if (sp->ap) {
  5408. if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
  5409. checkkwd |= CHKALIAS;
  5410. }
  5411. if (sp->string != sp->ap->val) {
  5412. ckfree(sp->string);
  5413. }
  5414. sp->ap->flag &= ~ALIASINUSE;
  5415. if (sp->ap->flag & ALIASDEAD) {
  5416. unalias(sp->ap->name);
  5417. }
  5418. }
  5419. #endif
  5420. parsenextc = sp->prevstring;
  5421. parsenleft = sp->prevnleft;
  5422. /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
  5423. parsefile->strpush = sp->prev;
  5424. if (sp != &(parsefile->basestrpush))
  5425. ckfree(sp);
  5426. INTON;
  5427. }
  5428. /*
  5429. * Set the input to take input from a file. If push is set, push the
  5430. * old input onto the stack first.
  5431. */
  5432. void
  5433. setinputfile(const char *fname, int push)
  5434. {
  5435. int fd;
  5436. int fd2;
  5437. INTOFF;
  5438. if ((fd = open(fname, O_RDONLY)) < 0)
  5439. error("Can't open %s", fname);
  5440. if (fd < 10) {
  5441. fd2 = copyfd(fd, 10);
  5442. close(fd);
  5443. if (fd2 < 0)
  5444. error("Out of file descriptors");
  5445. fd = fd2;
  5446. }
  5447. setinputfd(fd, push);
  5448. INTON;
  5449. }
  5450. /*
  5451. * Like setinputfile, but takes an open file descriptor. Call this with
  5452. * interrupts off.
  5453. */
  5454. static void
  5455. setinputfd(int fd, int push)
  5456. {
  5457. (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
  5458. if (push) {
  5459. pushfile();
  5460. parsefile->buf = 0;
  5461. }
  5462. parsefile->fd = fd;
  5463. if (parsefile->buf == NULL)
  5464. parsefile->buf = ckmalloc(IBUFSIZ);
  5465. parselleft = parsenleft = 0;
  5466. plinno = 1;
  5467. }
  5468. /*
  5469. * Like setinputfile, but takes input from a string.
  5470. */
  5471. static void
  5472. setinputstring(char *string)
  5473. {
  5474. INTOFF;
  5475. pushfile();
  5476. parsenextc = string;
  5477. parsenleft = strlen(string);
  5478. parsefile->buf = NULL;
  5479. plinno = 1;
  5480. INTON;
  5481. }
  5482. /*
  5483. * To handle the "." command, a stack of input files is used. Pushfile
  5484. * adds a new entry to the stack and popfile restores the previous level.
  5485. */
  5486. static void
  5487. pushfile(void)
  5488. {
  5489. struct parsefile *pf;
  5490. parsefile->nleft = parsenleft;
  5491. parsefile->lleft = parselleft;
  5492. parsefile->nextc = parsenextc;
  5493. parsefile->linno = plinno;
  5494. pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
  5495. pf->prev = parsefile;
  5496. pf->fd = -1;
  5497. pf->strpush = NULL;
  5498. pf->basestrpush.prev = NULL;
  5499. parsefile = pf;
  5500. }
  5501. static void
  5502. popfile(void)
  5503. {
  5504. struct parsefile *pf = parsefile;
  5505. INTOFF;
  5506. if (pf->fd >= 0)
  5507. close(pf->fd);
  5508. if (pf->buf)
  5509. ckfree(pf->buf);
  5510. while (pf->strpush)
  5511. popstring();
  5512. parsefile = pf->prev;
  5513. ckfree(pf);
  5514. parsenleft = parsefile->nleft;
  5515. parselleft = parsefile->lleft;
  5516. parsenextc = parsefile->nextc;
  5517. plinno = parsefile->linno;
  5518. INTON;
  5519. }
  5520. /*
  5521. * Return to top level.
  5522. */
  5523. static void
  5524. popallfiles(void)
  5525. {
  5526. while (parsefile != &basepf)
  5527. popfile();
  5528. }
  5529. /*
  5530. * Close the file(s) that the shell is reading commands from. Called
  5531. * after a fork is done.
  5532. */
  5533. static void
  5534. closescript(void)
  5535. {
  5536. popallfiles();
  5537. if (parsefile->fd > 0) {
  5538. close(parsefile->fd);
  5539. parsefile->fd = 0;
  5540. }
  5541. }
  5542. /* $NetBSD: jobs.c,v 1.56 2002/11/25 12:13:03 agc Exp $ */
  5543. /* mode flags for set_curjob */
  5544. #define CUR_DELETE 2
  5545. #define CUR_RUNNING 1
  5546. #define CUR_STOPPED 0
  5547. /* mode flags for dowait */
  5548. #define DOWAIT_NORMAL 0
  5549. #define DOWAIT_BLOCK 1
  5550. /* array of jobs */
  5551. static struct job *jobtab;
  5552. /* size of array */
  5553. static unsigned njobs;
  5554. #if JOBS
  5555. /* pgrp of shell on invocation */
  5556. static int initialpgrp;
  5557. static int ttyfd = -1;
  5558. #endif
  5559. /* current job */
  5560. static struct job *curjob;
  5561. /* number of presumed living untracked jobs */
  5562. static int jobless;
  5563. static void set_curjob(struct job *, unsigned);
  5564. #if JOBS
  5565. static int restartjob(struct job *, int);
  5566. static void xtcsetpgrp(int, pid_t);
  5567. static char *commandtext(union node *);
  5568. static void cmdlist(union node *, int);
  5569. static void cmdtxt(union node *);
  5570. static void cmdputs(const char *);
  5571. static void showpipe(struct job *, FILE *);
  5572. #endif
  5573. static int sprint_status(char *, int, int);
  5574. static void freejob(struct job *);
  5575. static struct job *getjob(const char *, int);
  5576. static struct job *growjobtab(void);
  5577. static void forkchild(struct job *, union node *, int);
  5578. static void forkparent(struct job *, union node *, int, pid_t);
  5579. static int dowait(int, struct job *);
  5580. static int getstatus(struct job *);
  5581. static void
  5582. set_curjob(struct job *jp, unsigned mode)
  5583. {
  5584. struct job *jp1;
  5585. struct job **jpp, **curp;
  5586. /* first remove from list */
  5587. jpp = curp = &curjob;
  5588. do {
  5589. jp1 = *jpp;
  5590. if (jp1 == jp)
  5591. break;
  5592. jpp = &jp1->prev_job;
  5593. } while (1);
  5594. *jpp = jp1->prev_job;
  5595. /* Then re-insert in correct position */
  5596. jpp = curp;
  5597. switch (mode) {
  5598. default:
  5599. #ifdef DEBUG
  5600. abort();
  5601. #endif
  5602. case CUR_DELETE:
  5603. /* job being deleted */
  5604. break;
  5605. case CUR_RUNNING:
  5606. /* newly created job or backgrounded job,
  5607. put after all stopped jobs. */
  5608. do {
  5609. jp1 = *jpp;
  5610. #ifdef JOBS
  5611. if (!jp1 || jp1->state != JOBSTOPPED)
  5612. #endif
  5613. break;
  5614. jpp = &jp1->prev_job;
  5615. } while (1);
  5616. /* FALLTHROUGH */
  5617. #ifdef JOBS
  5618. case CUR_STOPPED:
  5619. #endif
  5620. /* newly stopped job - becomes curjob */
  5621. jp->prev_job = *jpp;
  5622. *jpp = jp;
  5623. break;
  5624. }
  5625. }
  5626. #if JOBS
  5627. /*
  5628. * Turn job control on and off.
  5629. *
  5630. * Note: This code assumes that the third arg to ioctl is a character
  5631. * pointer, which is true on Berkeley systems but not System V. Since
  5632. * System V doesn't have job control yet, this isn't a problem now.
  5633. *
  5634. * Called with interrupts off.
  5635. */
  5636. void
  5637. setjobctl(int on)
  5638. {
  5639. int fd;
  5640. int pgrp;
  5641. if (on == jobctl || rootshell == 0)
  5642. return;
  5643. if (on) {
  5644. int ofd;
  5645. ofd = fd = open(_PATH_TTY, O_RDWR);
  5646. if (fd < 0) {
  5647. fd += 3;
  5648. while (!isatty(fd) && --fd >= 0)
  5649. ;
  5650. }
  5651. fd = fcntl(fd, F_DUPFD, 10);
  5652. close(ofd);
  5653. if (fd < 0)
  5654. goto out;
  5655. fcntl(fd, F_SETFD, FD_CLOEXEC);
  5656. do { /* while we are in the background */
  5657. if ((pgrp = tcgetpgrp(fd)) < 0) {
  5658. out:
  5659. sh_warnx("can't access tty; job control turned off");
  5660. mflag = on = 0;
  5661. goto close;
  5662. }
  5663. if (pgrp == getpgrp())
  5664. break;
  5665. killpg(0, SIGTTIN);
  5666. } while (1);
  5667. initialpgrp = pgrp;
  5668. setsignal(SIGTSTP);
  5669. setsignal(SIGTTOU);
  5670. setsignal(SIGTTIN);
  5671. pgrp = rootpid;
  5672. setpgid(0, pgrp);
  5673. xtcsetpgrp(fd, pgrp);
  5674. } else {
  5675. /* turning job control off */
  5676. fd = ttyfd;
  5677. pgrp = initialpgrp;
  5678. xtcsetpgrp(fd, pgrp);
  5679. setpgid(0, pgrp);
  5680. setsignal(SIGTSTP);
  5681. setsignal(SIGTTOU);
  5682. setsignal(SIGTTIN);
  5683. close:
  5684. close(fd);
  5685. fd = -1;
  5686. }
  5687. ttyfd = fd;
  5688. jobctl = on;
  5689. }
  5690. static int
  5691. killcmd(int argc, char **argv)
  5692. {
  5693. int signo = -1;
  5694. int list = 0;
  5695. int i;
  5696. pid_t pid;
  5697. struct job *jp;
  5698. if (argc <= 1) {
  5699. usage:
  5700. error(
  5701. "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
  5702. "kill -l [exitstatus]"
  5703. );
  5704. }
  5705. if (**++argv == '-') {
  5706. signo = decode_signal(*argv + 1, 1);
  5707. if (signo < 0) {
  5708. int c;
  5709. while ((c = nextopt("ls:")) != '\0')
  5710. switch (c) {
  5711. default:
  5712. #ifdef DEBUG
  5713. abort();
  5714. #endif
  5715. case 'l':
  5716. list = 1;
  5717. break;
  5718. case 's':
  5719. signo = decode_signal(optionarg, 1);
  5720. if (signo < 0) {
  5721. error(
  5722. "invalid signal number or name: %s",
  5723. optionarg
  5724. );
  5725. }
  5726. break;
  5727. }
  5728. argv = argptr;
  5729. } else
  5730. argv++;
  5731. }
  5732. if (!list && signo < 0)
  5733. signo = SIGTERM;
  5734. if ((signo < 0 || !*argv) ^ list) {
  5735. goto usage;
  5736. }
  5737. if (list) {
  5738. const char *name;
  5739. if (!*argv) {
  5740. for (i = 1; i < NSIG; i++) {
  5741. name = u_signal_names(0, &i, 1);
  5742. if (name)
  5743. out1fmt(snlfmt, name);
  5744. }
  5745. return 0;
  5746. }
  5747. name = u_signal_names(*argptr, &signo, -1);
  5748. if (name)
  5749. out1fmt(snlfmt, name);
  5750. else
  5751. error("invalid signal number or exit status: %s", *argptr);
  5752. return 0;
  5753. }
  5754. i = 0;
  5755. do {
  5756. if (**argv == '%') {
  5757. jp = getjob(*argv, 0);
  5758. pid = -jp->ps[0].pid;
  5759. } else
  5760. pid = number(*argv);
  5761. if (kill(pid, signo) != 0) {
  5762. sh_warnx("%m\n");
  5763. i = 1;
  5764. }
  5765. } while (*++argv);
  5766. return i;
  5767. }
  5768. #endif /* JOBS */
  5769. #if defined(JOBS) || defined(DEBUG)
  5770. static int
  5771. jobno(const struct job *jp)
  5772. {
  5773. return jp - jobtab + 1;
  5774. }
  5775. #endif
  5776. #ifdef JOBS
  5777. static int
  5778. fgcmd(int argc, char **argv)
  5779. {
  5780. struct job *jp;
  5781. FILE *out;
  5782. int mode;
  5783. int retval;
  5784. mode = (**argv == 'f') ? FORK_FG : FORK_BG;
  5785. nextopt(nullstr);
  5786. argv = argptr;
  5787. out = stdout;
  5788. do {
  5789. jp = getjob(*argv, 1);
  5790. if (mode == FORK_BG) {
  5791. set_curjob(jp, CUR_RUNNING);
  5792. fprintf(out, "[%d] ", jobno(jp));
  5793. }
  5794. outstr(jp->ps->cmd, out);
  5795. showpipe(jp, out);
  5796. retval = restartjob(jp, mode);
  5797. } while (*argv && *++argv);
  5798. return retval;
  5799. }
  5800. static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
  5801. static int
  5802. restartjob(struct job *jp, int mode)
  5803. {
  5804. struct procstat *ps;
  5805. int i;
  5806. int status;
  5807. pid_t pgid;
  5808. INTOFF;
  5809. if (jp->state == JOBDONE)
  5810. goto out;
  5811. jp->state = JOBRUNNING;
  5812. pgid = jp->ps->pid;
  5813. if (mode == FORK_FG)
  5814. xtcsetpgrp(ttyfd, pgid);
  5815. killpg(pgid, SIGCONT);
  5816. ps = jp->ps;
  5817. i = jp->nprocs;
  5818. do {
  5819. if (WIFSTOPPED(ps->status)) {
  5820. ps->status = -1;
  5821. }
  5822. } while (ps++, --i);
  5823. out:
  5824. status = (mode == FORK_FG) ? waitforjob(jp) : 0;
  5825. INTON;
  5826. return status;
  5827. }
  5828. #endif
  5829. static int
  5830. sprint_status(char *s, int status, int sigonly)
  5831. {
  5832. int col;
  5833. int st;
  5834. col = 0;
  5835. if (!WIFEXITED(status)) {
  5836. #if JOBS
  5837. if (WIFSTOPPED(status))
  5838. st = WSTOPSIG(status);
  5839. else
  5840. #endif
  5841. st = WTERMSIG(status);
  5842. if (sigonly) {
  5843. if (st == SIGINT || st == SIGPIPE)
  5844. goto out;
  5845. #if JOBS
  5846. if (WIFSTOPPED(status))
  5847. goto out;
  5848. #endif
  5849. }
  5850. st &= 0x7f;
  5851. col = fmtstr(s, 32, strsignal(st));
  5852. if (WCOREDUMP(status)) {
  5853. col += fmtstr(s + col, 16, " (core dumped)");
  5854. }
  5855. } else if (!sigonly) {
  5856. st = WEXITSTATUS(status);
  5857. if (st)
  5858. col = fmtstr(s, 16, "Done(%d)", st);
  5859. else
  5860. col = fmtstr(s, 16, "Done");
  5861. }
  5862. out:
  5863. return col;
  5864. }
  5865. #if JOBS
  5866. static void
  5867. showjob(FILE *out, struct job *jp, int mode)
  5868. {
  5869. struct procstat *ps;
  5870. struct procstat *psend;
  5871. int col;
  5872. int indent;
  5873. char s[80];
  5874. ps = jp->ps;
  5875. if (mode & SHOW_PGID) {
  5876. /* just output process (group) id of pipeline */
  5877. fprintf(out, "%d\n", ps->pid);
  5878. return;
  5879. }
  5880. col = fmtstr(s, 16, "[%d] ", jobno(jp));
  5881. indent = col;
  5882. if (jp == curjob)
  5883. s[col - 2] = '+';
  5884. else if (curjob && jp == curjob->prev_job)
  5885. s[col - 2] = '-';
  5886. if (mode & SHOW_PID)
  5887. col += fmtstr(s + col, 16, "%d ", ps->pid);
  5888. psend = ps + jp->nprocs;
  5889. if (jp->state == JOBRUNNING) {
  5890. scopy("Running", s + col);
  5891. col += strlen("Running");
  5892. } else {
  5893. int status = psend[-1].status;
  5894. #if JOBS
  5895. if (jp->state == JOBSTOPPED)
  5896. status = jp->stopstatus;
  5897. #endif
  5898. col += sprint_status(s + col, status, 0);
  5899. }
  5900. goto start;
  5901. do {
  5902. /* for each process */
  5903. col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
  5904. start:
  5905. fprintf(out, "%s%*c%s",
  5906. s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
  5907. );
  5908. if (!(mode & SHOW_PID)) {
  5909. showpipe(jp, out);
  5910. break;
  5911. }
  5912. if (++ps == psend) {
  5913. outcslow('\n', out);
  5914. break;
  5915. }
  5916. } while (1);
  5917. jp->changed = 0;
  5918. if (jp->state == JOBDONE) {
  5919. TRACE(("showjob: freeing job %d\n", jobno(jp)));
  5920. freejob(jp);
  5921. }
  5922. }
  5923. static int
  5924. jobscmd(int argc, char **argv)
  5925. {
  5926. int mode, m;
  5927. FILE *out;
  5928. mode = 0;
  5929. while ((m = nextopt("lp")))
  5930. if (m == 'l')
  5931. mode = SHOW_PID;
  5932. else
  5933. mode = SHOW_PGID;
  5934. out = stdout;
  5935. argv = argptr;
  5936. if (*argv)
  5937. do
  5938. showjob(out, getjob(*argv,0), mode);
  5939. while (*++argv);
  5940. else
  5941. showjobs(out, mode);
  5942. return 0;
  5943. }
  5944. /*
  5945. * Print a list of jobs. If "change" is nonzero, only print jobs whose
  5946. * statuses have changed since the last call to showjobs.
  5947. */
  5948. static void
  5949. showjobs(FILE *out, int mode)
  5950. {
  5951. struct job *jp;
  5952. TRACE(("showjobs(%x) called\n", mode));
  5953. /* If not even one one job changed, there is nothing to do */
  5954. while (dowait(DOWAIT_NORMAL, NULL) > 0)
  5955. continue;
  5956. for (jp = curjob; jp; jp = jp->prev_job) {
  5957. if (!(mode & SHOW_CHANGED) || jp->changed)
  5958. showjob(out, jp, mode);
  5959. }
  5960. }
  5961. #endif /* JOBS */
  5962. /*
  5963. * Mark a job structure as unused.
  5964. */
  5965. static void
  5966. freejob(struct job *jp)
  5967. {
  5968. struct procstat *ps;
  5969. int i;
  5970. INTOFF;
  5971. for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
  5972. if (ps->cmd != nullstr)
  5973. ckfree(ps->cmd);
  5974. }
  5975. if (jp->ps != &jp->ps0)
  5976. ckfree(jp->ps);
  5977. jp->used = 0;
  5978. set_curjob(jp, CUR_DELETE);
  5979. INTON;
  5980. }
  5981. static int
  5982. waitcmd(int argc, char **argv)
  5983. {
  5984. struct job *job;
  5985. int retval;
  5986. struct job *jp;
  5987. EXSIGON();
  5988. nextopt(nullstr);
  5989. retval = 0;
  5990. argv = argptr;
  5991. if (!*argv) {
  5992. /* wait for all jobs */
  5993. for (;;) {
  5994. jp = curjob;
  5995. while (1) {
  5996. if (!jp) {
  5997. /* no running procs */
  5998. goto out;
  5999. }
  6000. if (jp->state == JOBRUNNING)
  6001. break;
  6002. jp->waited = 1;
  6003. jp = jp->prev_job;
  6004. }
  6005. dowait(DOWAIT_BLOCK, 0);
  6006. }
  6007. }
  6008. retval = 127;
  6009. do {
  6010. if (**argv != '%') {
  6011. pid_t pid = number(*argv);
  6012. job = curjob;
  6013. goto start;
  6014. do {
  6015. if (job->ps[job->nprocs - 1].pid == pid)
  6016. break;
  6017. job = job->prev_job;
  6018. start:
  6019. if (!job)
  6020. goto repeat;
  6021. } while (1);
  6022. } else
  6023. job = getjob(*argv, 0);
  6024. /* loop until process terminated or stopped */
  6025. while (job->state == JOBRUNNING)
  6026. dowait(DOWAIT_BLOCK, 0);
  6027. job->waited = 1;
  6028. retval = getstatus(job);
  6029. repeat:
  6030. ;
  6031. } while (*++argv);
  6032. out:
  6033. return retval;
  6034. }
  6035. /*
  6036. * Convert a job name to a job structure.
  6037. */
  6038. static struct job *
  6039. getjob(const char *name, int getctl)
  6040. {
  6041. struct job *jp;
  6042. struct job *found;
  6043. const char *err_msg = "No such job: %s";
  6044. unsigned num;
  6045. int c;
  6046. const char *p;
  6047. char *(*match)(const char *, const char *);
  6048. jp = curjob;
  6049. p = name;
  6050. if (!p)
  6051. goto currentjob;
  6052. if (*p != '%')
  6053. goto err;
  6054. c = *++p;
  6055. if (!c)
  6056. goto currentjob;
  6057. if (!p[1]) {
  6058. if (c == '+' || c == '%') {
  6059. currentjob:
  6060. err_msg = "No current job";
  6061. goto check;
  6062. } else if (c == '-') {
  6063. if (jp)
  6064. jp = jp->prev_job;
  6065. err_msg = "No previous job";
  6066. check:
  6067. if (!jp)
  6068. goto err;
  6069. goto gotit;
  6070. }
  6071. }
  6072. if (is_number(p)) {
  6073. num = atoi(p);
  6074. if (num < njobs) {
  6075. jp = jobtab + num - 1;
  6076. if (jp->used)
  6077. goto gotit;
  6078. goto err;
  6079. }
  6080. }
  6081. match = prefix;
  6082. if (*p == '?') {
  6083. match = strstr;
  6084. p++;
  6085. }
  6086. found = 0;
  6087. while (1) {
  6088. if (!jp)
  6089. goto err;
  6090. if (match(jp->ps[0].cmd, p)) {
  6091. if (found)
  6092. goto err;
  6093. found = jp;
  6094. err_msg = "%s: ambiguous";
  6095. }
  6096. jp = jp->prev_job;
  6097. }
  6098. gotit:
  6099. #if JOBS
  6100. err_msg = "job %s not created under job control";
  6101. if (getctl && jp->jobctl == 0)
  6102. goto err;
  6103. #endif
  6104. return jp;
  6105. err:
  6106. error(err_msg, name);
  6107. }
  6108. /*
  6109. * Return a new job structure.
  6110. * Called with interrupts off.
  6111. */
  6112. static struct job *
  6113. makejob(union node *node, int nprocs)
  6114. {
  6115. int i;
  6116. struct job *jp;
  6117. for (i = njobs, jp = jobtab ; ; jp++) {
  6118. if (--i < 0) {
  6119. jp = growjobtab();
  6120. break;
  6121. }
  6122. if (jp->used == 0)
  6123. break;
  6124. if (jp->state != JOBDONE || !jp->waited)
  6125. continue;
  6126. #if JOBS
  6127. if (jobctl)
  6128. continue;
  6129. #endif
  6130. freejob(jp);
  6131. break;
  6132. }
  6133. memset(jp, 0, sizeof(*jp));
  6134. #if JOBS
  6135. if (jobctl)
  6136. jp->jobctl = 1;
  6137. #endif
  6138. jp->prev_job = curjob;
  6139. curjob = jp;
  6140. jp->used = 1;
  6141. jp->ps = &jp->ps0;
  6142. if (nprocs > 1) {
  6143. jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
  6144. }
  6145. TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
  6146. jobno(jp)));
  6147. return jp;
  6148. }
  6149. static struct job *
  6150. growjobtab(void)
  6151. {
  6152. size_t len;
  6153. ptrdiff_t offset;
  6154. struct job *jp, *jq;
  6155. len = njobs * sizeof(*jp);
  6156. jq = jobtab;
  6157. jp = ckrealloc(jq, len + 4 * sizeof(*jp));
  6158. offset = (char *)jp - (char *)jq;
  6159. if (offset) {
  6160. /* Relocate pointers */
  6161. size_t l = len;
  6162. jq = (struct job *)((char *)jq + l);
  6163. while (l) {
  6164. l -= sizeof(*jp);
  6165. jq--;
  6166. #define joff(p) ((struct job *)((char *)(p) + l))
  6167. #define jmove(p) (p) = (void *)((char *)(p) + offset)
  6168. if (xlikely(joff(jp)->ps == &jq->ps0))
  6169. jmove(joff(jp)->ps);
  6170. if (joff(jp)->prev_job)
  6171. jmove(joff(jp)->prev_job);
  6172. }
  6173. if (curjob)
  6174. jmove(curjob);
  6175. #undef joff
  6176. #undef jmove
  6177. }
  6178. njobs += 4;
  6179. jobtab = jp;
  6180. jp = (struct job *)((char *)jp + len);
  6181. jq = jp + 3;
  6182. do {
  6183. jq->used = 0;
  6184. } while (--jq >= jp);
  6185. return jp;
  6186. }
  6187. /*
  6188. * Fork off a subshell. If we are doing job control, give the subshell its
  6189. * own process group. Jp is a job structure that the job is to be added to.
  6190. * N is the command that will be evaluated by the child. Both jp and n may
  6191. * be NULL. The mode parameter can be one of the following:
  6192. * FORK_FG - Fork off a foreground process.
  6193. * FORK_BG - Fork off a background process.
  6194. * FORK_NOJOB - Like FORK_FG, but don't give the process its own
  6195. * process group even if job control is on.
  6196. *
  6197. * When job control is turned off, background processes have their standard
  6198. * input redirected to /dev/null (except for the second and later processes
  6199. * in a pipeline).
  6200. *
  6201. * Called with interrupts off.
  6202. */
  6203. static inline void
  6204. forkchild(struct job *jp, union node *n, int mode)
  6205. {
  6206. int wasroot;
  6207. TRACE(("Child shell %d\n", getpid()));
  6208. wasroot = rootshell;
  6209. rootshell = 0;
  6210. closescript();
  6211. clear_traps();
  6212. #if JOBS
  6213. /* do job control only in root shell */
  6214. jobctl = 0;
  6215. if (mode != FORK_NOJOB && jp->jobctl && wasroot) {
  6216. pid_t pgrp;
  6217. if (jp->nprocs == 0)
  6218. pgrp = getpid();
  6219. else
  6220. pgrp = jp->ps[0].pid;
  6221. /* This can fail because we are doing it in the parent also */
  6222. (void)setpgid(0, pgrp);
  6223. if (mode == FORK_FG)
  6224. xtcsetpgrp(ttyfd, pgrp);
  6225. setsignal(SIGTSTP);
  6226. setsignal(SIGTTOU);
  6227. } else
  6228. #endif
  6229. if (mode == FORK_BG) {
  6230. ignoresig(SIGINT);
  6231. ignoresig(SIGQUIT);
  6232. if (jp->nprocs == 0) {
  6233. close(0);
  6234. if (open(_PATH_DEVNULL, O_RDONLY) != 0)
  6235. error("Can't open %s", _PATH_DEVNULL);
  6236. }
  6237. }
  6238. if (wasroot && iflag) {
  6239. setsignal(SIGINT);
  6240. setsignal(SIGQUIT);
  6241. setsignal(SIGTERM);
  6242. }
  6243. for (jp = curjob; jp; jp = jp->prev_job)
  6244. freejob(jp);
  6245. jobless = 0;
  6246. }
  6247. static inline void
  6248. forkparent(struct job *jp, union node *n, int mode, pid_t pid)
  6249. {
  6250. TRACE(("In parent shell: child = %d\n", pid));
  6251. if (!jp) {
  6252. while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
  6253. jobless++;
  6254. return;
  6255. }
  6256. #if JOBS
  6257. if (mode != FORK_NOJOB && jp->jobctl) {
  6258. int pgrp;
  6259. if (jp->nprocs == 0)
  6260. pgrp = pid;
  6261. else
  6262. pgrp = jp->ps[0].pid;
  6263. /* This can fail because we are doing it in the child also */
  6264. (void)setpgid(pid, pgrp);
  6265. }
  6266. #endif
  6267. if (mode == FORK_BG) {
  6268. backgndpid = pid; /* set $! */
  6269. set_curjob(jp, CUR_RUNNING);
  6270. }
  6271. if (jp) {
  6272. struct procstat *ps = &jp->ps[jp->nprocs++];
  6273. ps->pid = pid;
  6274. ps->status = -1;
  6275. ps->cmd = nullstr;
  6276. #if JOBS
  6277. if (jobctl && n)
  6278. ps->cmd = commandtext(n);
  6279. #endif
  6280. }
  6281. }
  6282. static int
  6283. forkshell(struct job *jp, union node *n, int mode)
  6284. {
  6285. int pid;
  6286. TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
  6287. pid = fork();
  6288. if (pid < 0) {
  6289. TRACE(("Fork failed, errno=%d", errno));
  6290. if (jp)
  6291. freejob(jp);
  6292. error("Cannot fork");
  6293. }
  6294. if (pid == 0)
  6295. forkchild(jp, n, mode);
  6296. else
  6297. forkparent(jp, n, mode, pid);
  6298. return pid;
  6299. }
  6300. /*
  6301. * Wait for job to finish.
  6302. *
  6303. * Under job control we have the problem that while a child process is
  6304. * running interrupts generated by the user are sent to the child but not
  6305. * to the shell. This means that an infinite loop started by an inter-
  6306. * active user may be hard to kill. With job control turned off, an
  6307. * interactive user may place an interactive program inside a loop. If
  6308. * the interactive program catches interrupts, the user doesn't want
  6309. * these interrupts to also abort the loop. The approach we take here
  6310. * is to have the shell ignore interrupt signals while waiting for a
  6311. * foreground process to terminate, and then send itself an interrupt
  6312. * signal if the child process was terminated by an interrupt signal.
  6313. * Unfortunately, some programs want to do a bit of cleanup and then
  6314. * exit on interrupt; unless these processes terminate themselves by
  6315. * sending a signal to themselves (instead of calling exit) they will
  6316. * confuse this approach.
  6317. *
  6318. * Called with interrupts off.
  6319. */
  6320. int
  6321. waitforjob(struct job *jp)
  6322. {
  6323. int st;
  6324. TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
  6325. while (jp->state == JOBRUNNING) {
  6326. dowait(DOWAIT_BLOCK, jp);
  6327. }
  6328. st = getstatus(jp);
  6329. #if JOBS
  6330. if (jp->jobctl) {
  6331. xtcsetpgrp(ttyfd, rootpid);
  6332. /*
  6333. * This is truly gross.
  6334. * If we're doing job control, then we did a TIOCSPGRP which
  6335. * caused us (the shell) to no longer be in the controlling
  6336. * session -- so we wouldn't have seen any ^C/SIGINT. So, we
  6337. * intuit from the subprocess exit status whether a SIGINT
  6338. * occurred, and if so interrupt ourselves. Yuck. - mycroft
  6339. */
  6340. if (jp->sigint)
  6341. raise(SIGINT);
  6342. }
  6343. if (jp->state == JOBDONE)
  6344. #endif
  6345. freejob(jp);
  6346. return st;
  6347. }
  6348. /*
  6349. * Do a wait system call. If job control is compiled in, we accept
  6350. * stopped processes. If block is zero, we return a value of zero
  6351. * rather than blocking.
  6352. *
  6353. * System V doesn't have a non-blocking wait system call. It does
  6354. * have a SIGCLD signal that is sent to a process when one of it's
  6355. * children dies. The obvious way to use SIGCLD would be to install
  6356. * a handler for SIGCLD which simply bumped a counter when a SIGCLD
  6357. * was received, and have waitproc bump another counter when it got
  6358. * the status of a process. Waitproc would then know that a wait
  6359. * system call would not block if the two counters were different.
  6360. * This approach doesn't work because if a process has children that
  6361. * have not been waited for, System V will send it a SIGCLD when it
  6362. * installs a signal handler for SIGCLD. What this means is that when
  6363. * a child exits, the shell will be sent SIGCLD signals continuously
  6364. * until is runs out of stack space, unless it does a wait call before
  6365. * restoring the signal handler. The code below takes advantage of
  6366. * this (mis)feature by installing a signal handler for SIGCLD and
  6367. * then checking to see whether it was called. If there are any
  6368. * children to be waited for, it will be.
  6369. *
  6370. * If neither SYSV nor BSD is defined, we don't implement nonblocking
  6371. * waits at all. In this case, the user will not be informed when
  6372. * a background process until the next time she runs a real program
  6373. * (as opposed to running a builtin command or just typing return),
  6374. * and the jobs command may give out of date information.
  6375. */
  6376. static inline int
  6377. waitproc(int block, int *status)
  6378. {
  6379. int flags = 0;
  6380. #if JOBS
  6381. if (jobctl)
  6382. flags |= WUNTRACED;
  6383. #endif
  6384. if (block == 0)
  6385. flags |= WNOHANG;
  6386. return wait3(status, flags, (struct rusage *)NULL);
  6387. }
  6388. /*
  6389. * Wait for a process to terminate.
  6390. */
  6391. static int
  6392. dowait(int block, struct job *job)
  6393. {
  6394. int pid;
  6395. int status;
  6396. struct job *jp;
  6397. struct job *thisjob;
  6398. int state;
  6399. TRACE(("dowait(%d) called\n", block));
  6400. pid = waitproc(block, &status);
  6401. TRACE(("wait returns pid %d, status=%d\n", pid, status));
  6402. if (pid <= 0)
  6403. return pid;
  6404. INTOFF;
  6405. thisjob = NULL;
  6406. for (jp = curjob; jp; jp = jp->prev_job) {
  6407. struct procstat *sp;
  6408. struct procstat *spend;
  6409. if (jp->state == JOBDONE)
  6410. continue;
  6411. state = JOBDONE;
  6412. spend = jp->ps + jp->nprocs;
  6413. sp = jp->ps;
  6414. do {
  6415. if (sp->pid == pid) {
  6416. TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
  6417. sp->status = status;
  6418. thisjob = jp;
  6419. }
  6420. if (sp->status == -1)
  6421. state = JOBRUNNING;
  6422. #ifdef JOBS
  6423. if (state == JOBRUNNING)
  6424. continue;
  6425. if (WIFSTOPPED(sp->status)) {
  6426. jp->stopstatus = sp->status;
  6427. state = JOBSTOPPED;
  6428. }
  6429. #endif
  6430. } while (++sp < spend);
  6431. if (thisjob)
  6432. goto gotjob;
  6433. }
  6434. #ifdef JOBS
  6435. if (!WIFSTOPPED(status))
  6436. #endif
  6437. jobless--;
  6438. goto out;
  6439. gotjob:
  6440. if (state != JOBRUNNING) {
  6441. thisjob->changed = 1;
  6442. if (thisjob->state != state) {
  6443. TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
  6444. thisjob->state = state;
  6445. #ifdef JOBS
  6446. if (state == JOBSTOPPED) {
  6447. set_curjob(thisjob, CUR_STOPPED);
  6448. }
  6449. #endif
  6450. }
  6451. }
  6452. out:
  6453. INTON;
  6454. if (thisjob && thisjob == job) {
  6455. char s[48 + 1];
  6456. int len;
  6457. len = sprint_status(s, status, 1);
  6458. if (len) {
  6459. s[len] = '\n';
  6460. s[len + 1] = 0;
  6461. out2str(s);
  6462. }
  6463. }
  6464. return pid;
  6465. }
  6466. /*
  6467. * return 1 if there are stopped jobs, otherwise 0
  6468. */
  6469. int
  6470. stoppedjobs(void)
  6471. {
  6472. struct job *jp;
  6473. int retval;
  6474. retval = 0;
  6475. if (job_warning)
  6476. goto out;
  6477. jp = curjob;
  6478. if (jp && jp->state == JOBSTOPPED) {
  6479. out2str("You have stopped jobs.\n");
  6480. job_warning = 2;
  6481. retval++;
  6482. }
  6483. out:
  6484. return retval;
  6485. }
  6486. /*
  6487. * Return a string identifying a command (to be printed by the
  6488. * jobs command).
  6489. */
  6490. #if JOBS
  6491. static char *cmdnextc;
  6492. static char *
  6493. commandtext(union node *n)
  6494. {
  6495. char *name;
  6496. STARTSTACKSTR(cmdnextc);
  6497. cmdtxt(n);
  6498. name = stackblock();
  6499. TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
  6500. name, cmdnextc, cmdnextc));
  6501. return savestr(name);
  6502. }
  6503. static void
  6504. cmdtxt(union node *n)
  6505. {
  6506. union node *np;
  6507. struct nodelist *lp;
  6508. const char *p;
  6509. char s[2];
  6510. if (!n)
  6511. return;
  6512. switch (n->type) {
  6513. default:
  6514. #if DEBUG
  6515. abort();
  6516. #endif
  6517. case NPIPE:
  6518. lp = n->npipe.cmdlist;
  6519. for (;;) {
  6520. cmdtxt(lp->n);
  6521. lp = lp->next;
  6522. if (!lp)
  6523. break;
  6524. cmdputs(" | ");
  6525. }
  6526. break;
  6527. case NSEMI:
  6528. p = "; ";
  6529. goto binop;
  6530. case NAND:
  6531. p = " && ";
  6532. goto binop;
  6533. case NOR:
  6534. p = " || ";
  6535. binop:
  6536. cmdtxt(n->nbinary.ch1);
  6537. cmdputs(p);
  6538. n = n->nbinary.ch2;
  6539. goto donode;
  6540. case NREDIR:
  6541. case NBACKGND:
  6542. n = n->nredir.n;
  6543. goto donode;
  6544. case NNOT:
  6545. cmdputs("!");
  6546. n = n->nnot.com;
  6547. donode:
  6548. cmdtxt(n);
  6549. break;
  6550. case NIF:
  6551. cmdputs("if ");
  6552. cmdtxt(n->nif.test);
  6553. cmdputs("; then ");
  6554. n = n->nif.ifpart;
  6555. if (n->nif.elsepart) {
  6556. cmdtxt(n);
  6557. cmdputs("; else ");
  6558. n = n->nif.elsepart;
  6559. }
  6560. p = "; fi";
  6561. goto dotail;
  6562. case NSUBSHELL:
  6563. cmdputs("(");
  6564. n = n->nredir.n;
  6565. p = ")";
  6566. goto dotail;
  6567. case NWHILE:
  6568. p = "while ";
  6569. goto until;
  6570. case NUNTIL:
  6571. p = "until ";
  6572. until:
  6573. cmdputs(p);
  6574. cmdtxt(n->nbinary.ch1);
  6575. n = n->nbinary.ch2;
  6576. p = "; done";
  6577. dodo:
  6578. cmdputs("; do ");
  6579. dotail:
  6580. cmdtxt(n);
  6581. goto dotail2;
  6582. case NFOR:
  6583. cmdputs("for ");
  6584. cmdputs(n->nfor.var);
  6585. cmdputs(" in ");
  6586. cmdlist(n->nfor.args, 1);
  6587. n = n->nfor.body;
  6588. p = "; done";
  6589. goto dodo;
  6590. case NDEFUN:
  6591. cmdputs(n->narg.text);
  6592. p = "() { ... }";
  6593. goto dotail2;
  6594. case NCMD:
  6595. cmdlist(n->ncmd.args, 1);
  6596. cmdlist(n->ncmd.redirect, 0);
  6597. break;
  6598. case NARG:
  6599. p = n->narg.text;
  6600. dotail2:
  6601. cmdputs(p);
  6602. break;
  6603. case NHERE:
  6604. case NXHERE:
  6605. p = "<<...";
  6606. goto dotail2;
  6607. case NCASE:
  6608. cmdputs("case ");
  6609. cmdputs(n->ncase.expr->narg.text);
  6610. cmdputs(" in ");
  6611. for (np = n->ncase.cases; np; np = np->nclist.next) {
  6612. cmdtxt(np->nclist.pattern);
  6613. cmdputs(") ");
  6614. cmdtxt(np->nclist.body);
  6615. cmdputs(";; ");
  6616. }
  6617. p = "esac";
  6618. goto dotail2;
  6619. case NTO:
  6620. p = ">";
  6621. goto redir;
  6622. case NCLOBBER:
  6623. p = ">|";
  6624. goto redir;
  6625. case NAPPEND:
  6626. p = ">>";
  6627. goto redir;
  6628. case NTOFD:
  6629. p = ">&";
  6630. goto redir;
  6631. case NFROM:
  6632. p = "<";
  6633. goto redir;
  6634. case NFROMFD:
  6635. p = "<&";
  6636. goto redir;
  6637. case NFROMTO:
  6638. p = "<>";
  6639. redir:
  6640. s[0] = n->nfile.fd + '0';
  6641. s[1] = '\0';
  6642. cmdputs(s);
  6643. cmdputs(p);
  6644. if (n->type == NTOFD || n->type == NFROMFD) {
  6645. s[0] = n->ndup.dupfd + '0';
  6646. p = s;
  6647. goto dotail2;
  6648. } else {
  6649. n = n->nfile.fname;
  6650. goto donode;
  6651. }
  6652. }
  6653. }
  6654. static void
  6655. cmdlist(union node *np, int sep)
  6656. {
  6657. for (; np; np = np->narg.next) {
  6658. if (!sep)
  6659. cmdputs(spcstr);
  6660. cmdtxt(np);
  6661. if (sep && np->narg.next)
  6662. cmdputs(spcstr);
  6663. }
  6664. }
  6665. static void
  6666. cmdputs(const char *s)
  6667. {
  6668. const char *p, *str;
  6669. char c, cc[2] = " ";
  6670. char *nextc;
  6671. int subtype = 0;
  6672. int quoted = 0;
  6673. static const char *const vstype[16] = {
  6674. nullstr, "}", "-", "+", "?", "=",
  6675. "%", "%%", "#", "##", nullstr
  6676. };
  6677. nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
  6678. p = s;
  6679. while ((c = *p++) != 0) {
  6680. str = 0;
  6681. switch (c) {
  6682. case CTLESC:
  6683. c = *p++;
  6684. break;
  6685. case CTLVAR:
  6686. subtype = *p++;
  6687. if ((subtype & VSTYPE) == VSLENGTH)
  6688. str = "${#";
  6689. else
  6690. str = "${";
  6691. if (!(subtype & VSQUOTE) != !(quoted & 1)) {
  6692. quoted ^= 1;
  6693. c = '"';
  6694. } else
  6695. goto dostr;
  6696. break;
  6697. case CTLENDVAR:
  6698. quoted >>= 1;
  6699. subtype = 0;
  6700. if (quoted & 1) {
  6701. str = "\"}";
  6702. goto dostr;
  6703. }
  6704. c = '}';
  6705. break;
  6706. case CTLBACKQ:
  6707. str = "$(...)";
  6708. goto dostr;
  6709. case CTLBACKQ+CTLQUOTE:
  6710. str = "\"$(...)\"";
  6711. goto dostr;
  6712. #ifdef CONFIG_ASH_MATH_SUPPORT
  6713. case CTLARI:
  6714. str = "$((";
  6715. goto dostr;
  6716. case CTLENDARI:
  6717. str = "))";
  6718. goto dostr;
  6719. #endif
  6720. case CTLQUOTEMARK:
  6721. quoted ^= 1;
  6722. c = '"';
  6723. break;
  6724. case '=':
  6725. if (subtype == 0)
  6726. break;
  6727. str = vstype[subtype & VSTYPE];
  6728. if (subtype & VSNUL)
  6729. c = ':';
  6730. else
  6731. c = *str++;
  6732. if (c != '}')
  6733. quoted <<= 1;
  6734. break;
  6735. case '\'':
  6736. case '\\':
  6737. case '"':
  6738. case '$':
  6739. /* These can only happen inside quotes */
  6740. cc[0] = c;
  6741. str = cc;
  6742. c = '\\';
  6743. break;
  6744. default:
  6745. break;
  6746. }
  6747. USTPUTC(c, nextc);
  6748. if (!str)
  6749. continue;
  6750. dostr:
  6751. while ((c = *str++)) {
  6752. USTPUTC(c, nextc);
  6753. }
  6754. }
  6755. if (quoted & 1) {
  6756. USTPUTC('"', nextc);
  6757. }
  6758. *nextc = 0;
  6759. cmdnextc = nextc;
  6760. }
  6761. static void
  6762. showpipe(struct job *jp, FILE *out)
  6763. {
  6764. struct procstat *sp;
  6765. struct procstat *spend;
  6766. spend = jp->ps + jp->nprocs;
  6767. for (sp = jp->ps + 1; sp < spend; sp++)
  6768. fprintf(out, " | %s", sp->cmd);
  6769. outcslow('\n', out);
  6770. flushall();
  6771. }
  6772. static void
  6773. xtcsetpgrp(int fd, pid_t pgrp)
  6774. {
  6775. if (tcsetpgrp(fd, pgrp))
  6776. error("Cannot set tty process group (%m)");
  6777. }
  6778. #endif /* JOBS */
  6779. static int
  6780. getstatus(struct job *job) {
  6781. int status;
  6782. int retval;
  6783. status = job->ps[job->nprocs - 1].status;
  6784. retval = WEXITSTATUS(status);
  6785. if (!WIFEXITED(status)) {
  6786. #if JOBS
  6787. retval = WSTOPSIG(status);
  6788. if (!WIFSTOPPED(status))
  6789. #endif
  6790. {
  6791. /* XXX: limits number of signals */
  6792. retval = WTERMSIG(status);
  6793. #if JOBS
  6794. if (retval == SIGINT)
  6795. job->sigint = 1;
  6796. #endif
  6797. }
  6798. retval += 128;
  6799. }
  6800. TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
  6801. jobno(job), job->nprocs, status, retval));
  6802. return retval;
  6803. }
  6804. #ifdef CONFIG_ASH_MAIL
  6805. /* $NetBSD: mail.c,v 1.15 2002/11/24 22:35:40 christos Exp $ */
  6806. /*
  6807. * Routines to check for mail. (Perhaps make part of main.c?)
  6808. */
  6809. #define MAXMBOXES 10
  6810. /* times of mailboxes */
  6811. static time_t mailtime[MAXMBOXES];
  6812. /* Set if MAIL or MAILPATH is changed. */
  6813. static int mail_var_path_changed;
  6814. /*
  6815. * Print appropriate message(s) if mail has arrived.
  6816. * If mail_var_path_changed is set,
  6817. * then the value of MAIL has mail_var_path_changed,
  6818. * so we just update the values.
  6819. */
  6820. static void
  6821. chkmail(void)
  6822. {
  6823. const char *mpath;
  6824. char *p;
  6825. char *q;
  6826. time_t *mtp;
  6827. struct stackmark smark;
  6828. struct stat statb;
  6829. setstackmark(&smark);
  6830. mpath = mpathset() ? mpathval() : mailval();
  6831. for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
  6832. p = padvance(&mpath, nullstr);
  6833. if (p == NULL)
  6834. break;
  6835. if (*p == '\0')
  6836. continue;
  6837. for (q = p ; *q ; q++);
  6838. #ifdef DEBUG
  6839. if (q[-1] != '/')
  6840. abort();
  6841. #endif
  6842. q[-1] = '\0'; /* delete trailing '/' */
  6843. if (stat(p, &statb) < 0) {
  6844. *mtp = 0;
  6845. continue;
  6846. }
  6847. if (!mail_var_path_changed && statb.st_mtime != *mtp) {
  6848. fprintf(
  6849. stderr, snlfmt,
  6850. pathopt ? pathopt : "you have mail"
  6851. );
  6852. }
  6853. *mtp = statb.st_mtime;
  6854. }
  6855. mail_var_path_changed = 0;
  6856. popstackmark(&smark);
  6857. }
  6858. static void
  6859. changemail(const char *val)
  6860. {
  6861. mail_var_path_changed++;
  6862. }
  6863. #endif /* CONFIG_ASH_MAIL */
  6864. /* $NetBSD: main.c,v 1.46 2002/12/11 19:12:18 christos Exp $ */
  6865. #if PROFILE
  6866. static short profile_buf[16384];
  6867. extern int etext();
  6868. #endif
  6869. static int isloginsh;
  6870. static void read_profile(const char *);
  6871. /*
  6872. * Main routine. We initialize things, parse the arguments, execute
  6873. * profiles if we're a login shell, and then call cmdloop to execute
  6874. * commands. The setjmp call sets up the location to jump to when an
  6875. * exception occurs. When an exception occurs the variable "state"
  6876. * is used to figure out how far we had gotten.
  6877. */
  6878. int
  6879. ash_main(int argc, char **argv)
  6880. {
  6881. char *shinit;
  6882. volatile int state;
  6883. struct jmploc jmploc;
  6884. struct stackmark smark;
  6885. #ifdef __GLIBC__
  6886. dash_errno = __errno_location();
  6887. #endif
  6888. #if PROFILE
  6889. monitor(4, etext, profile_buf, sizeof profile_buf, 50);
  6890. #endif
  6891. state = 0;
  6892. if (setjmp(jmploc.loc)) {
  6893. int status;
  6894. int e;
  6895. reset();
  6896. e = exception;
  6897. switch (exception) {
  6898. case EXEXEC:
  6899. status = exerrno;
  6900. break;
  6901. case EXERROR:
  6902. status = 2;
  6903. break;
  6904. default:
  6905. status = exitstatus;
  6906. break;
  6907. }
  6908. exitstatus = status;
  6909. if (e == EXEXIT || state == 0 || iflag == 0 || ! rootshell)
  6910. exitshell();
  6911. if (e == EXINT) {
  6912. outcslow('\n', stderr);
  6913. }
  6914. popstackmark(&smark);
  6915. FORCEINTON; /* enable interrupts */
  6916. if (state == 1)
  6917. goto state1;
  6918. else if (state == 2)
  6919. goto state2;
  6920. else if (state == 3)
  6921. goto state3;
  6922. else
  6923. goto state4;
  6924. }
  6925. handler = &jmploc;
  6926. #ifdef DEBUG
  6927. opentrace();
  6928. trputs("Shell args: "); trargs(argv);
  6929. #endif
  6930. rootpid = getpid();
  6931. #ifdef CONFIG_ASH_RANDOM_SUPPORT
  6932. rseed = rootpid + ((time_t)time((time_t *)0));
  6933. #endif
  6934. rootshell = 1;
  6935. init();
  6936. setstackmark(&smark);
  6937. procargs(argc, argv);
  6938. #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
  6939. if ( iflag ) {
  6940. const char *hp = lookupvar("HISTFILE");
  6941. if(hp == NULL ) {
  6942. hp = lookupvar("HOME");
  6943. if(hp != NULL) {
  6944. char *defhp = concat_path_file(hp, ".ash_history");
  6945. setvar("HISTFILE", defhp, 0);
  6946. free(defhp);
  6947. }
  6948. }
  6949. }
  6950. #endif
  6951. if (argv[0] && argv[0][0] == '-')
  6952. isloginsh = 1;
  6953. if (isloginsh) {
  6954. state = 1;
  6955. read_profile("/etc/profile");
  6956. state1:
  6957. state = 2;
  6958. read_profile(".profile");
  6959. }
  6960. state2:
  6961. state = 3;
  6962. if (
  6963. #ifndef linux
  6964. getuid() == geteuid() && getgid() == getegid() &&
  6965. #endif
  6966. iflag
  6967. ) {
  6968. if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
  6969. read_profile(shinit);
  6970. }
  6971. }
  6972. state3:
  6973. state = 4;
  6974. if (minusc)
  6975. evalstring(minusc);
  6976. if (sflag || minusc == NULL) {
  6977. #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
  6978. if ( iflag ) {
  6979. const char *hp = lookupvar("HISTFILE");
  6980. if(hp != NULL )
  6981. load_history ( hp );
  6982. }
  6983. #endif
  6984. state4: /* XXX ??? - why isn't this before the "if" statement */
  6985. cmdloop(1);
  6986. }
  6987. #if PROFILE
  6988. monitor(0);
  6989. #endif
  6990. #if GPROF
  6991. {
  6992. extern void _mcleanup(void);
  6993. _mcleanup();
  6994. }
  6995. #endif
  6996. exitshell();
  6997. /* NOTREACHED */
  6998. }
  6999. /*
  7000. * Read and execute commands. "Top" is nonzero for the top level command
  7001. * loop; it turns on prompting if the shell is interactive.
  7002. */
  7003. static void
  7004. cmdloop(int top)
  7005. {
  7006. union node *n;
  7007. struct stackmark smark;
  7008. int inter;
  7009. int numeof = 0;
  7010. TRACE(("cmdloop(%d) called\n", top));
  7011. for (;;) {
  7012. setstackmark(&smark);
  7013. if (pendingsigs)
  7014. dotrap();
  7015. #if JOBS
  7016. if (jobctl)
  7017. showjobs(stderr, SHOW_CHANGED);
  7018. #endif
  7019. inter = 0;
  7020. if (iflag && top) {
  7021. inter++;
  7022. #ifdef CONFIG_ASH_MAIL
  7023. chkmail();
  7024. #endif
  7025. }
  7026. n = parsecmd(inter);
  7027. /* showtree(n); DEBUG */
  7028. if (n == NEOF) {
  7029. if (!top || numeof >= 50)
  7030. break;
  7031. if (!stoppedjobs()) {
  7032. if (!Iflag)
  7033. break;
  7034. out2str("\nUse \"exit\" to leave shell.\n");
  7035. }
  7036. numeof++;
  7037. } else if (n != NULL && nflag == 0) {
  7038. job_warning = (job_warning == 2) ? 1 : 0;
  7039. numeof = 0;
  7040. evaltree(n, 0);
  7041. }
  7042. popstackmark(&smark);
  7043. if (evalskip) {
  7044. evalskip = 0;
  7045. break;
  7046. }
  7047. }
  7048. }
  7049. /*
  7050. * Read /etc/profile or .profile. Return on error.
  7051. */
  7052. static void
  7053. read_profile(const char *name)
  7054. {
  7055. int fd;
  7056. int xflag_set = 0;
  7057. int vflag_set = 0;
  7058. INTOFF;
  7059. if ((fd = open(name, O_RDONLY)) >= 0)
  7060. setinputfd(fd, 1);
  7061. INTON;
  7062. if (fd < 0)
  7063. return;
  7064. /* -q turns off -x and -v just when executing init files */
  7065. if (qflag) {
  7066. if (xflag)
  7067. xflag = 0, xflag_set = 1;
  7068. if (vflag)
  7069. vflag = 0, vflag_set = 1;
  7070. }
  7071. cmdloop(0);
  7072. if (qflag) {
  7073. if (xflag_set)
  7074. xflag = 1;
  7075. if (vflag_set)
  7076. vflag = 1;
  7077. }
  7078. popfile();
  7079. }
  7080. /*
  7081. * Read a file containing shell functions.
  7082. */
  7083. static void
  7084. readcmdfile(char *name)
  7085. {
  7086. int fd;
  7087. INTOFF;
  7088. if ((fd = open(name, O_RDONLY)) >= 0)
  7089. setinputfd(fd, 1);
  7090. else
  7091. error("Can't open %s", name);
  7092. INTON;
  7093. cmdloop(0);
  7094. popfile();
  7095. }
  7096. /*
  7097. * Take commands from a file. To be compatible we should do a path
  7098. * search for the file, which is necessary to find sub-commands.
  7099. */
  7100. static inline char *
  7101. find_dot_file(char *name)
  7102. {
  7103. char *fullname;
  7104. const char *path = pathval();
  7105. struct stat statb;
  7106. /* don't try this for absolute or relative paths */
  7107. if (strchr(name, '/'))
  7108. return name;
  7109. while ((fullname = padvance(&path, name)) != NULL) {
  7110. if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
  7111. /*
  7112. * Don't bother freeing here, since it will
  7113. * be freed by the caller.
  7114. */
  7115. return fullname;
  7116. }
  7117. stunalloc(fullname);
  7118. }
  7119. /* not found in the PATH */
  7120. error(not_found_msg, name);
  7121. /* NOTREACHED */
  7122. }
  7123. static int dotcmd(int argc, char **argv)
  7124. {
  7125. struct strlist *sp;
  7126. volatile struct shparam saveparam;
  7127. exitstatus = 0;
  7128. for (sp = cmdenviron; sp; sp = sp->next)
  7129. setvareq(bb_xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
  7130. if (argc >= 2) { /* That's what SVR2 does */
  7131. char *fullname;
  7132. struct stackmark smark;
  7133. setstackmark(&smark);
  7134. fullname = find_dot_file(argv[1]);
  7135. if (argc > 2) {
  7136. saveparam = shellparam;
  7137. shellparam.malloc = 0;
  7138. shellparam.nparam = argc - 2;
  7139. shellparam.p = argv + 2;
  7140. };
  7141. setinputfile(fullname, 1);
  7142. commandname = fullname;
  7143. cmdloop(0);
  7144. popfile();
  7145. if (argc > 2) {
  7146. freeparam(&shellparam);
  7147. shellparam = saveparam;
  7148. };
  7149. popstackmark(&smark);
  7150. }
  7151. return exitstatus;
  7152. }
  7153. static int
  7154. exitcmd(int argc, char **argv)
  7155. {
  7156. if (stoppedjobs())
  7157. return 0;
  7158. if (argc > 1)
  7159. exitstatus = number(argv[1]);
  7160. exraise(EXEXIT);
  7161. /* NOTREACHED */
  7162. }
  7163. /* $NetBSD: memalloc.c,v 1.27 2003/01/22 20:36:04 dsl Exp $ */
  7164. /*
  7165. * Same for malloc, realloc, but returns an error when out of space.
  7166. */
  7167. static pointer
  7168. ckrealloc(pointer p, size_t nbytes)
  7169. {
  7170. p = realloc(p, nbytes);
  7171. if (p == NULL)
  7172. error(bb_msg_memory_exhausted);
  7173. return p;
  7174. }
  7175. static pointer
  7176. ckmalloc(size_t nbytes)
  7177. {
  7178. return ckrealloc(NULL, nbytes);
  7179. }
  7180. /*
  7181. * Make a copy of a string in safe storage.
  7182. */
  7183. static char *
  7184. savestr(const char *s)
  7185. {
  7186. char *p = strdup(s);
  7187. if (!p)
  7188. error(bb_msg_memory_exhausted);
  7189. return p;
  7190. }
  7191. /*
  7192. * Parse trees for commands are allocated in lifo order, so we use a stack
  7193. * to make this more efficient, and also to avoid all sorts of exception
  7194. * handling code to handle interrupts in the middle of a parse.
  7195. *
  7196. * The size 504 was chosen because the Ultrix malloc handles that size
  7197. * well.
  7198. */
  7199. static pointer
  7200. stalloc(size_t nbytes)
  7201. {
  7202. char *p;
  7203. size_t aligned;
  7204. aligned = SHELL_ALIGN(nbytes);
  7205. if (aligned > stacknleft) {
  7206. size_t len;
  7207. size_t blocksize;
  7208. struct stack_block *sp;
  7209. blocksize = aligned;
  7210. if (blocksize < MINSIZE)
  7211. blocksize = MINSIZE;
  7212. len = sizeof(struct stack_block) - MINSIZE + blocksize;
  7213. if (len < blocksize)
  7214. error(bb_msg_memory_exhausted);
  7215. INTOFF;
  7216. sp = ckmalloc(len);
  7217. sp->prev = stackp;
  7218. stacknxt = sp->space;
  7219. stacknleft = blocksize;
  7220. sstrend = stacknxt + blocksize;
  7221. stackp = sp;
  7222. INTON;
  7223. }
  7224. p = stacknxt;
  7225. stacknxt += aligned;
  7226. stacknleft -= aligned;
  7227. return p;
  7228. }
  7229. void
  7230. stunalloc(pointer p)
  7231. {
  7232. #ifdef DEBUG
  7233. if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
  7234. write(2, "stunalloc\n", 10);
  7235. abort();
  7236. }
  7237. #endif
  7238. stacknleft += stacknxt - (char *)p;
  7239. stacknxt = p;
  7240. }
  7241. void
  7242. setstackmark(struct stackmark *mark)
  7243. {
  7244. mark->stackp = stackp;
  7245. mark->stacknxt = stacknxt;
  7246. mark->stacknleft = stacknleft;
  7247. mark->marknext = markp;
  7248. markp = mark;
  7249. }
  7250. void
  7251. popstackmark(struct stackmark *mark)
  7252. {
  7253. struct stack_block *sp;
  7254. INTOFF;
  7255. markp = mark->marknext;
  7256. while (stackp != mark->stackp) {
  7257. sp = stackp;
  7258. stackp = sp->prev;
  7259. ckfree(sp);
  7260. }
  7261. stacknxt = mark->stacknxt;
  7262. stacknleft = mark->stacknleft;
  7263. sstrend = mark->stacknxt + mark->stacknleft;
  7264. INTON;
  7265. }
  7266. /*
  7267. * When the parser reads in a string, it wants to stick the string on the
  7268. * stack and only adjust the stack pointer when it knows how big the
  7269. * string is. Stackblock (defined in stack.h) returns a pointer to a block
  7270. * of space on top of the stack and stackblocklen returns the length of
  7271. * this block. Growstackblock will grow this space by at least one byte,
  7272. * possibly moving it (like realloc). Grabstackblock actually allocates the
  7273. * part of the block that has been used.
  7274. */
  7275. void
  7276. growstackblock(void)
  7277. {
  7278. size_t newlen;
  7279. newlen = stacknleft * 2;
  7280. if (newlen < stacknleft)
  7281. error(bb_msg_memory_exhausted);
  7282. if (newlen < 128)
  7283. newlen += 128;
  7284. if (stacknxt == stackp->space && stackp != &stackbase) {
  7285. struct stack_block *oldstackp;
  7286. struct stackmark *xmark;
  7287. struct stack_block *sp;
  7288. struct stack_block *prevstackp;
  7289. size_t grosslen;
  7290. INTOFF;
  7291. oldstackp = stackp;
  7292. sp = stackp;
  7293. prevstackp = sp->prev;
  7294. grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
  7295. sp = ckrealloc((pointer)sp, grosslen);
  7296. sp->prev = prevstackp;
  7297. stackp = sp;
  7298. stacknxt = sp->space;
  7299. stacknleft = newlen;
  7300. sstrend = sp->space + newlen;
  7301. /*
  7302. * Stack marks pointing to the start of the old block
  7303. * must be relocated to point to the new block
  7304. */
  7305. xmark = markp;
  7306. while (xmark != NULL && xmark->stackp == oldstackp) {
  7307. xmark->stackp = stackp;
  7308. xmark->stacknxt = stacknxt;
  7309. xmark->stacknleft = stacknleft;
  7310. xmark = xmark->marknext;
  7311. }
  7312. INTON;
  7313. } else {
  7314. char *oldspace = stacknxt;
  7315. int oldlen = stacknleft;
  7316. char *p = stalloc(newlen);
  7317. /* free the space we just allocated */
  7318. stacknxt = memcpy(p, oldspace, oldlen);
  7319. stacknleft += newlen;
  7320. }
  7321. }
  7322. static inline void
  7323. grabstackblock(size_t len)
  7324. {
  7325. len = SHELL_ALIGN(len);
  7326. stacknxt += len;
  7327. stacknleft -= len;
  7328. }
  7329. /*
  7330. * The following routines are somewhat easier to use than the above.
  7331. * The user declares a variable of type STACKSTR, which may be declared
  7332. * to be a register. The macro STARTSTACKSTR initializes things. Then
  7333. * the user uses the macro STPUTC to add characters to the string. In
  7334. * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
  7335. * grown as necessary. When the user is done, she can just leave the
  7336. * string there and refer to it using stackblock(). Or she can allocate
  7337. * the space for it using grabstackstr(). If it is necessary to allow
  7338. * someone else to use the stack temporarily and then continue to grow
  7339. * the string, the user should use grabstack to allocate the space, and
  7340. * then call ungrabstr(p) to return to the previous mode of operation.
  7341. *
  7342. * USTPUTC is like STPUTC except that it doesn't check for overflow.
  7343. * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
  7344. * is space for at least one character.
  7345. */
  7346. void *
  7347. growstackstr(void)
  7348. {
  7349. size_t len = stackblocksize();
  7350. if (herefd >= 0 && len >= 1024) {
  7351. bb_full_write(herefd, stackblock(), len);
  7352. return stackblock();
  7353. }
  7354. growstackblock();
  7355. return stackblock() + len;
  7356. }
  7357. /*
  7358. * Called from CHECKSTRSPACE.
  7359. */
  7360. char *
  7361. makestrspace(size_t newlen, char *p)
  7362. {
  7363. size_t len = p - stacknxt;
  7364. size_t size = stackblocksize();
  7365. for (;;) {
  7366. size_t nleft;
  7367. size = stackblocksize();
  7368. nleft = size - len;
  7369. if (nleft >= newlen)
  7370. break;
  7371. growstackblock();
  7372. }
  7373. return stackblock() + len;
  7374. }
  7375. char *
  7376. stnputs(const char *s, size_t n, char *p)
  7377. {
  7378. p = makestrspace(n, p);
  7379. p = mempcpy(p, s, n);
  7380. return p;
  7381. }
  7382. char *
  7383. stputs(const char *s, char *p)
  7384. {
  7385. return stnputs(s, strlen(s), p);
  7386. }
  7387. /* $NetBSD: mystring.c,v 1.15 2002/11/24 22:35:42 christos Exp $ */
  7388. /*
  7389. * String functions.
  7390. *
  7391. * number(s) Convert a string of digits to an integer.
  7392. * is_number(s) Return true if s is a string of digits.
  7393. */
  7394. /*
  7395. * prefix -- see if pfx is a prefix of string.
  7396. */
  7397. char *
  7398. prefix(const char *string, const char *pfx)
  7399. {
  7400. while (*pfx) {
  7401. if (*pfx++ != *string++)
  7402. return 0;
  7403. }
  7404. return (char *) string;
  7405. }
  7406. /*
  7407. * Convert a string of digits to an integer, printing an error message on
  7408. * failure.
  7409. */
  7410. int
  7411. number(const char *s)
  7412. {
  7413. if (! is_number(s))
  7414. error(illnum, s);
  7415. return atoi(s);
  7416. }
  7417. /*
  7418. * Check for a valid number. This should be elsewhere.
  7419. */
  7420. int
  7421. is_number(const char *p)
  7422. {
  7423. do {
  7424. if (! is_digit(*p))
  7425. return 0;
  7426. } while (*++p != '\0');
  7427. return 1;
  7428. }
  7429. /*
  7430. * Produce a possibly single quoted string suitable as input to the shell.
  7431. * The return string is allocated on the stack.
  7432. */
  7433. char *
  7434. single_quote(const char *s) {
  7435. char *p;
  7436. STARTSTACKSTR(p);
  7437. do {
  7438. char *q;
  7439. size_t len;
  7440. len = strchrnul(s, '\'') - s;
  7441. q = p = makestrspace(len + 3, p);
  7442. *q++ = '\'';
  7443. q = mempcpy(q, s, len);
  7444. *q++ = '\'';
  7445. s += len;
  7446. STADJUST(q - p, p);
  7447. len = strspn(s, "'");
  7448. if (!len)
  7449. break;
  7450. q = p = makestrspace(len + 3, p);
  7451. *q++ = '"';
  7452. q = mempcpy(q, s, len);
  7453. *q++ = '"';
  7454. s += len;
  7455. STADJUST(q - p, p);
  7456. } while (*s);
  7457. USTPUTC(0, p);
  7458. return stackblock();
  7459. }
  7460. /*
  7461. * Like strdup but works with the ash stack.
  7462. */
  7463. char *
  7464. sstrdup(const char *p)
  7465. {
  7466. size_t len = strlen(p) + 1;
  7467. return memcpy(stalloc(len), p, len);
  7468. }
  7469. static void
  7470. calcsize(union node *n)
  7471. {
  7472. if (n == NULL)
  7473. return;
  7474. funcblocksize += nodesize[n->type];
  7475. switch (n->type) {
  7476. case NCMD:
  7477. calcsize(n->ncmd.redirect);
  7478. calcsize(n->ncmd.args);
  7479. calcsize(n->ncmd.assign);
  7480. break;
  7481. case NPIPE:
  7482. sizenodelist(n->npipe.cmdlist);
  7483. break;
  7484. case NREDIR:
  7485. case NBACKGND:
  7486. case NSUBSHELL:
  7487. calcsize(n->nredir.redirect);
  7488. calcsize(n->nredir.n);
  7489. break;
  7490. case NAND:
  7491. case NOR:
  7492. case NSEMI:
  7493. case NWHILE:
  7494. case NUNTIL:
  7495. calcsize(n->nbinary.ch2);
  7496. calcsize(n->nbinary.ch1);
  7497. break;
  7498. case NIF:
  7499. calcsize(n->nif.elsepart);
  7500. calcsize(n->nif.ifpart);
  7501. calcsize(n->nif.test);
  7502. break;
  7503. case NFOR:
  7504. funcstringsize += strlen(n->nfor.var) + 1;
  7505. calcsize(n->nfor.body);
  7506. calcsize(n->nfor.args);
  7507. break;
  7508. case NCASE:
  7509. calcsize(n->ncase.cases);
  7510. calcsize(n->ncase.expr);
  7511. break;
  7512. case NCLIST:
  7513. calcsize(n->nclist.body);
  7514. calcsize(n->nclist.pattern);
  7515. calcsize(n->nclist.next);
  7516. break;
  7517. case NDEFUN:
  7518. case NARG:
  7519. sizenodelist(n->narg.backquote);
  7520. funcstringsize += strlen(n->narg.text) + 1;
  7521. calcsize(n->narg.next);
  7522. break;
  7523. case NTO:
  7524. case NCLOBBER:
  7525. case NFROM:
  7526. case NFROMTO:
  7527. case NAPPEND:
  7528. calcsize(n->nfile.fname);
  7529. calcsize(n->nfile.next);
  7530. break;
  7531. case NTOFD:
  7532. case NFROMFD:
  7533. calcsize(n->ndup.vname);
  7534. calcsize(n->ndup.next);
  7535. break;
  7536. case NHERE:
  7537. case NXHERE:
  7538. calcsize(n->nhere.doc);
  7539. calcsize(n->nhere.next);
  7540. break;
  7541. case NNOT:
  7542. calcsize(n->nnot.com);
  7543. break;
  7544. };
  7545. }
  7546. static void
  7547. sizenodelist(struct nodelist *lp)
  7548. {
  7549. while (lp) {
  7550. funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
  7551. calcsize(lp->n);
  7552. lp = lp->next;
  7553. }
  7554. }
  7555. static union node *
  7556. copynode(union node *n)
  7557. {
  7558. union node *new;
  7559. if (n == NULL)
  7560. return NULL;
  7561. new = funcblock;
  7562. funcblock = (char *) funcblock + nodesize[n->type];
  7563. switch (n->type) {
  7564. case NCMD:
  7565. new->ncmd.redirect = copynode(n->ncmd.redirect);
  7566. new->ncmd.args = copynode(n->ncmd.args);
  7567. new->ncmd.assign = copynode(n->ncmd.assign);
  7568. break;
  7569. case NPIPE:
  7570. new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
  7571. new->npipe.backgnd = n->npipe.backgnd;
  7572. break;
  7573. case NREDIR:
  7574. case NBACKGND:
  7575. case NSUBSHELL:
  7576. new->nredir.redirect = copynode(n->nredir.redirect);
  7577. new->nredir.n = copynode(n->nredir.n);
  7578. break;
  7579. case NAND:
  7580. case NOR:
  7581. case NSEMI:
  7582. case NWHILE:
  7583. case NUNTIL:
  7584. new->nbinary.ch2 = copynode(n->nbinary.ch2);
  7585. new->nbinary.ch1 = copynode(n->nbinary.ch1);
  7586. break;
  7587. case NIF:
  7588. new->nif.elsepart = copynode(n->nif.elsepart);
  7589. new->nif.ifpart = copynode(n->nif.ifpart);
  7590. new->nif.test = copynode(n->nif.test);
  7591. break;
  7592. case NFOR:
  7593. new->nfor.var = nodesavestr(n->nfor.var);
  7594. new->nfor.body = copynode(n->nfor.body);
  7595. new->nfor.args = copynode(n->nfor.args);
  7596. break;
  7597. case NCASE:
  7598. new->ncase.cases = copynode(n->ncase.cases);
  7599. new->ncase.expr = copynode(n->ncase.expr);
  7600. break;
  7601. case NCLIST:
  7602. new->nclist.body = copynode(n->nclist.body);
  7603. new->nclist.pattern = copynode(n->nclist.pattern);
  7604. new->nclist.next = copynode(n->nclist.next);
  7605. break;
  7606. case NDEFUN:
  7607. case NARG:
  7608. new->narg.backquote = copynodelist(n->narg.backquote);
  7609. new->narg.text = nodesavestr(n->narg.text);
  7610. new->narg.next = copynode(n->narg.next);
  7611. break;
  7612. case NTO:
  7613. case NCLOBBER:
  7614. case NFROM:
  7615. case NFROMTO:
  7616. case NAPPEND:
  7617. new->nfile.fname = copynode(n->nfile.fname);
  7618. new->nfile.fd = n->nfile.fd;
  7619. new->nfile.next = copynode(n->nfile.next);
  7620. break;
  7621. case NTOFD:
  7622. case NFROMFD:
  7623. new->ndup.vname = copynode(n->ndup.vname);
  7624. new->ndup.dupfd = n->ndup.dupfd;
  7625. new->ndup.fd = n->ndup.fd;
  7626. new->ndup.next = copynode(n->ndup.next);
  7627. break;
  7628. case NHERE:
  7629. case NXHERE:
  7630. new->nhere.doc = copynode(n->nhere.doc);
  7631. new->nhere.fd = n->nhere.fd;
  7632. new->nhere.next = copynode(n->nhere.next);
  7633. break;
  7634. case NNOT:
  7635. new->nnot.com = copynode(n->nnot.com);
  7636. break;
  7637. };
  7638. new->type = n->type;
  7639. return new;
  7640. }
  7641. static struct nodelist *
  7642. copynodelist(struct nodelist *lp)
  7643. {
  7644. struct nodelist *start;
  7645. struct nodelist **lpp;
  7646. lpp = &start;
  7647. while (lp) {
  7648. *lpp = funcblock;
  7649. funcblock = (char *) funcblock +
  7650. SHELL_ALIGN(sizeof(struct nodelist));
  7651. (*lpp)->n = copynode(lp->n);
  7652. lp = lp->next;
  7653. lpp = &(*lpp)->next;
  7654. }
  7655. *lpp = NULL;
  7656. return start;
  7657. }
  7658. static char *
  7659. nodesavestr(char *s)
  7660. {
  7661. char *rtn = funcstring;
  7662. funcstring = stpcpy(funcstring, s) + 1;
  7663. return rtn;
  7664. }
  7665. /*
  7666. * Free a parse tree.
  7667. */
  7668. static void
  7669. freefunc(struct funcnode *f)
  7670. {
  7671. if (f && --f->count < 0)
  7672. ckfree(f);
  7673. }
  7674. static void options(int);
  7675. static void setoption(int, int);
  7676. /*
  7677. * Process the shell command line arguments.
  7678. */
  7679. void
  7680. procargs(int argc, char **argv)
  7681. {
  7682. int i;
  7683. const char *xminusc;
  7684. char **xargv;
  7685. xargv = argv;
  7686. arg0 = xargv[0];
  7687. if (argc > 0)
  7688. xargv++;
  7689. for (i = 0; i < NOPTS; i++)
  7690. optlist[i] = 2;
  7691. argptr = xargv;
  7692. options(1);
  7693. xargv = argptr;
  7694. xminusc = minusc;
  7695. if (*xargv == NULL) {
  7696. if (xminusc)
  7697. error("-c requires an argument");
  7698. sflag = 1;
  7699. }
  7700. if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
  7701. iflag = 1;
  7702. if (mflag == 2)
  7703. mflag = iflag;
  7704. for (i = 0; i < NOPTS; i++)
  7705. if (optlist[i] == 2)
  7706. optlist[i] = 0;
  7707. #if DEBUG == 2
  7708. debug = 1;
  7709. #endif
  7710. /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
  7711. if (xminusc) {
  7712. minusc = *xargv++;
  7713. if (*xargv)
  7714. goto setarg0;
  7715. } else if (!sflag) {
  7716. setinputfile(*xargv, 0);
  7717. setarg0:
  7718. arg0 = *xargv++;
  7719. commandname = arg0;
  7720. }
  7721. shellparam.p = xargv;
  7722. #ifdef CONFIG_ASH_GETOPTS
  7723. shellparam.optind = 1;
  7724. shellparam.optoff = -1;
  7725. #endif
  7726. /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
  7727. while (*xargv) {
  7728. shellparam.nparam++;
  7729. xargv++;
  7730. }
  7731. optschanged();
  7732. }
  7733. void
  7734. optschanged(void)
  7735. {
  7736. #ifdef DEBUG
  7737. opentrace();
  7738. #endif
  7739. setinteractive(iflag);
  7740. setjobctl(mflag);
  7741. }
  7742. static inline void
  7743. minus_o(char *name, int val)
  7744. {
  7745. int i;
  7746. if (name == NULL) {
  7747. out1str("Current option settings\n");
  7748. for (i = 0; i < NOPTS; i++)
  7749. out1fmt("%-16s%s\n", optnames(i),
  7750. optlist[i] ? "on" : "off");
  7751. } else {
  7752. for (i = 0; i < NOPTS; i++)
  7753. if (equal(name, optnames(i))) {
  7754. optlist[i] = val;
  7755. return;
  7756. }
  7757. error("Illegal option -o %s", name);
  7758. }
  7759. }
  7760. /*
  7761. * Process shell options. The global variable argptr contains a pointer
  7762. * to the argument list; we advance it past the options.
  7763. */
  7764. static void
  7765. options(int cmdline)
  7766. {
  7767. char *p;
  7768. int val;
  7769. int c;
  7770. if (cmdline)
  7771. minusc = NULL;
  7772. while ((p = *argptr) != NULL) {
  7773. argptr++;
  7774. if ((c = *p++) == '-') {
  7775. val = 1;
  7776. if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
  7777. if (!cmdline) {
  7778. /* "-" means turn off -x and -v */
  7779. if (p[0] == '\0')
  7780. xflag = vflag = 0;
  7781. /* "--" means reset params */
  7782. else if (*argptr == NULL)
  7783. setparam(argptr);
  7784. }
  7785. break; /* "-" or "--" terminates options */
  7786. }
  7787. } else if (c == '+') {
  7788. val = 0;
  7789. } else {
  7790. argptr--;
  7791. break;
  7792. }
  7793. while ((c = *p++) != '\0') {
  7794. if (c == 'c' && cmdline) {
  7795. minusc = p; /* command is after shell args*/
  7796. } else if (c == 'o') {
  7797. minus_o(*argptr, val);
  7798. if (*argptr)
  7799. argptr++;
  7800. } else if (cmdline && (c == '-')) { // long options
  7801. if (strcmp(p, "login") == 0)
  7802. isloginsh = 1;
  7803. break;
  7804. } else {
  7805. setoption(c, val);
  7806. }
  7807. }
  7808. }
  7809. }
  7810. static void
  7811. setoption(int flag, int val)
  7812. {
  7813. int i;
  7814. for (i = 0; i < NOPTS; i++)
  7815. if (optletters(i) == flag) {
  7816. optlist[i] = val;
  7817. return;
  7818. }
  7819. error("Illegal option -%c", flag);
  7820. /* NOTREACHED */
  7821. }
  7822. /*
  7823. * Set the shell parameters.
  7824. */
  7825. void
  7826. setparam(char **argv)
  7827. {
  7828. char **newparam;
  7829. char **ap;
  7830. int nparam;
  7831. for (nparam = 0 ; argv[nparam] ; nparam++);
  7832. ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
  7833. while (*argv) {
  7834. *ap++ = savestr(*argv++);
  7835. }
  7836. *ap = NULL;
  7837. freeparam(&shellparam);
  7838. shellparam.malloc = 1;
  7839. shellparam.nparam = nparam;
  7840. shellparam.p = newparam;
  7841. #ifdef CONFIG_ASH_GETOPTS
  7842. shellparam.optind = 1;
  7843. shellparam.optoff = -1;
  7844. #endif
  7845. }
  7846. /*
  7847. * Free the list of positional parameters.
  7848. */
  7849. void
  7850. freeparam(volatile struct shparam *param)
  7851. {
  7852. char **ap;
  7853. if (param->malloc) {
  7854. for (ap = param->p ; *ap ; ap++)
  7855. ckfree(*ap);
  7856. ckfree(param->p);
  7857. }
  7858. }
  7859. /*
  7860. * The shift builtin command.
  7861. */
  7862. int
  7863. shiftcmd(int argc, char **argv)
  7864. {
  7865. int n;
  7866. char **ap1, **ap2;
  7867. n = 1;
  7868. if (argc > 1)
  7869. n = number(argv[1]);
  7870. if (n > shellparam.nparam)
  7871. error("can't shift that many");
  7872. INTOFF;
  7873. shellparam.nparam -= n;
  7874. for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
  7875. if (shellparam.malloc)
  7876. ckfree(*ap1);
  7877. }
  7878. ap2 = shellparam.p;
  7879. while ((*ap2++ = *ap1++) != NULL);
  7880. #ifdef CONFIG_ASH_GETOPTS
  7881. shellparam.optind = 1;
  7882. shellparam.optoff = -1;
  7883. #endif
  7884. INTON;
  7885. return 0;
  7886. }
  7887. /*
  7888. * The set command builtin.
  7889. */
  7890. int
  7891. setcmd(int argc, char **argv)
  7892. {
  7893. if (argc == 1)
  7894. return showvars(nullstr, 0, VUNSET);
  7895. INTOFF;
  7896. options(0);
  7897. optschanged();
  7898. if (*argptr != NULL) {
  7899. setparam(argptr);
  7900. }
  7901. INTON;
  7902. return 0;
  7903. }
  7904. #ifdef CONFIG_ASH_GETOPTS
  7905. static void
  7906. getoptsreset(value)
  7907. const char *value;
  7908. {
  7909. shellparam.optind = number(value);
  7910. shellparam.optoff = -1;
  7911. }
  7912. #endif
  7913. #ifdef CONFIG_LOCALE_SUPPORT
  7914. static void change_lc_all(const char *value)
  7915. {
  7916. if (value != 0 && *value != 0)
  7917. setlocale(LC_ALL, value);
  7918. }
  7919. static void change_lc_ctype(const char *value)
  7920. {
  7921. if (value != 0 && *value != 0)
  7922. setlocale(LC_CTYPE, value);
  7923. }
  7924. #endif
  7925. #ifdef CONFIG_ASH_RANDOM_SUPPORT
  7926. /* Roughly copied from bash.. */
  7927. static void change_random(const char *value)
  7928. {
  7929. if(value == NULL) {
  7930. /* "get", generate */
  7931. char buf[16];
  7932. rseed = rseed * 1103515245 + 12345;
  7933. sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
  7934. /* set without recursion */
  7935. setvar(vrandom.text, buf, VNOFUNC);
  7936. vrandom.flags &= ~VNOFUNC;
  7937. } else {
  7938. /* set/reset */
  7939. rseed = strtoul(value, (char **)NULL, 10);
  7940. }
  7941. }
  7942. #endif
  7943. #ifdef CONFIG_ASH_GETOPTS
  7944. static int
  7945. getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
  7946. {
  7947. char *p, *q;
  7948. char c = '?';
  7949. int done = 0;
  7950. int err = 0;
  7951. char s[12];
  7952. char **optnext;
  7953. if(*param_optind < 1)
  7954. return 1;
  7955. optnext = optfirst + *param_optind - 1;
  7956. if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
  7957. p = NULL;
  7958. else
  7959. p = optnext[-1] + *optoff;
  7960. if (p == NULL || *p == '\0') {
  7961. /* Current word is done, advance */
  7962. p = *optnext;
  7963. if (p == NULL || *p != '-' || *++p == '\0') {
  7964. atend:
  7965. p = NULL;
  7966. done = 1;
  7967. goto out;
  7968. }
  7969. optnext++;
  7970. if (p[0] == '-' && p[1] == '\0') /* check for "--" */
  7971. goto atend;
  7972. }
  7973. c = *p++;
  7974. for (q = optstr; *q != c; ) {
  7975. if (*q == '\0') {
  7976. if (optstr[0] == ':') {
  7977. s[0] = c;
  7978. s[1] = '\0';
  7979. err |= setvarsafe("OPTARG", s, 0);
  7980. } else {
  7981. fprintf(stderr, "Illegal option -%c\n", c);
  7982. (void) unsetvar("OPTARG");
  7983. }
  7984. c = '?';
  7985. goto out;
  7986. }
  7987. if (*++q == ':')
  7988. q++;
  7989. }
  7990. if (*++q == ':') {
  7991. if (*p == '\0' && (p = *optnext) == NULL) {
  7992. if (optstr[0] == ':') {
  7993. s[0] = c;
  7994. s[1] = '\0';
  7995. err |= setvarsafe("OPTARG", s, 0);
  7996. c = ':';
  7997. } else {
  7998. fprintf(stderr, "No arg for -%c option\n", c);
  7999. (void) unsetvar("OPTARG");
  8000. c = '?';
  8001. }
  8002. goto out;
  8003. }
  8004. if (p == *optnext)
  8005. optnext++;
  8006. err |= setvarsafe("OPTARG", p, 0);
  8007. p = NULL;
  8008. } else
  8009. err |= setvarsafe("OPTARG", nullstr, 0);
  8010. out:
  8011. *optoff = p ? p - *(optnext - 1) : -1;
  8012. *param_optind = optnext - optfirst + 1;
  8013. fmtstr(s, sizeof(s), "%d", *param_optind);
  8014. err |= setvarsafe("OPTIND", s, VNOFUNC);
  8015. s[0] = c;
  8016. s[1] = '\0';
  8017. err |= setvarsafe(optvar, s, 0);
  8018. if (err) {
  8019. *param_optind = 1;
  8020. *optoff = -1;
  8021. flushall();
  8022. exraise(EXERROR);
  8023. }
  8024. return done;
  8025. }
  8026. /*
  8027. * The getopts builtin. Shellparam.optnext points to the next argument
  8028. * to be processed. Shellparam.optptr points to the next character to
  8029. * be processed in the current argument. If shellparam.optnext is NULL,
  8030. * then it's the first time getopts has been called.
  8031. */
  8032. int
  8033. getoptscmd(int argc, char **argv)
  8034. {
  8035. char **optbase;
  8036. if (argc < 3)
  8037. error("Usage: getopts optstring var [arg]");
  8038. else if (argc == 3) {
  8039. optbase = shellparam.p;
  8040. if (shellparam.optind > shellparam.nparam + 1) {
  8041. shellparam.optind = 1;
  8042. shellparam.optoff = -1;
  8043. }
  8044. }
  8045. else {
  8046. optbase = &argv[3];
  8047. if (shellparam.optind > argc - 2) {
  8048. shellparam.optind = 1;
  8049. shellparam.optoff = -1;
  8050. }
  8051. }
  8052. return getopts(argv[1], argv[2], optbase, &shellparam.optind,
  8053. &shellparam.optoff);
  8054. }
  8055. #endif /* CONFIG_ASH_GETOPTS */
  8056. /*
  8057. * XXX - should get rid of. have all builtins use getopt(3). the
  8058. * library getopt must have the BSD extension static variable "optreset"
  8059. * otherwise it can't be used within the shell safely.
  8060. *
  8061. * Standard option processing (a la getopt) for builtin routines. The
  8062. * only argument that is passed to nextopt is the option string; the
  8063. * other arguments are unnecessary. It return the character, or '\0' on
  8064. * end of input.
  8065. */
  8066. static int
  8067. nextopt(const char *optstring)
  8068. {
  8069. char *p;
  8070. const char *q;
  8071. char c;
  8072. if ((p = optptr) == NULL || *p == '\0') {
  8073. p = *argptr;
  8074. if (p == NULL || *p != '-' || *++p == '\0')
  8075. return '\0';
  8076. argptr++;
  8077. if (p[0] == '-' && p[1] == '\0') /* check for "--" */
  8078. return '\0';
  8079. }
  8080. c = *p++;
  8081. for (q = optstring ; *q != c ; ) {
  8082. if (*q == '\0')
  8083. error("Illegal option -%c", c);
  8084. if (*++q == ':')
  8085. q++;
  8086. }
  8087. if (*++q == ':') {
  8088. if (*p == '\0' && (p = *argptr++) == NULL)
  8089. error("No arg for -%c option", c);
  8090. optionarg = p;
  8091. p = NULL;
  8092. }
  8093. optptr = p;
  8094. return c;
  8095. }
  8096. /* $NetBSD: output.c,v 1.27 2002/11/24 22:35:42 christos Exp $ */
  8097. void
  8098. outstr(const char *p, FILE *file)
  8099. {
  8100. INTOFF;
  8101. fputs(p, file);
  8102. INTON;
  8103. }
  8104. void
  8105. flushall(void)
  8106. {
  8107. INTOFF;
  8108. fflush(stdout);
  8109. fflush(stderr);
  8110. INTON;
  8111. }
  8112. void
  8113. flusherr(void)
  8114. {
  8115. INTOFF;
  8116. fflush(stderr);
  8117. INTON;
  8118. }
  8119. static void
  8120. outcslow(int c, FILE *dest)
  8121. {
  8122. INTOFF;
  8123. putc(c, dest);
  8124. fflush(dest);
  8125. INTON;
  8126. }
  8127. static int
  8128. out1fmt(const char *fmt, ...)
  8129. {
  8130. va_list ap;
  8131. int r;
  8132. INTOFF;
  8133. va_start(ap, fmt);
  8134. r = vprintf(fmt, ap);
  8135. va_end(ap);
  8136. INTON;
  8137. return r;
  8138. }
  8139. int
  8140. fmtstr(char *outbuf, size_t length, const char *fmt, ...)
  8141. {
  8142. va_list ap;
  8143. int ret;
  8144. va_start(ap, fmt);
  8145. INTOFF;
  8146. ret = vsnprintf(outbuf, length, fmt, ap);
  8147. va_end(ap);
  8148. INTON;
  8149. return ret;
  8150. }
  8151. /* $NetBSD: parser.c,v 1.54 2002/11/24 22:35:42 christos Exp $ */
  8152. /*
  8153. * Shell command parser.
  8154. */
  8155. #define EOFMARKLEN 79
  8156. struct heredoc {
  8157. struct heredoc *next; /* next here document in list */
  8158. union node *here; /* redirection node */
  8159. char *eofmark; /* string indicating end of input */
  8160. int striptabs; /* if set, strip leading tabs */
  8161. };
  8162. static struct heredoc *heredoclist; /* list of here documents to read */
  8163. static union node *list(int);
  8164. static union node *andor(void);
  8165. static union node *pipeline(void);
  8166. static union node *command(void);
  8167. static union node *simplecmd(void);
  8168. static union node *makename(void);
  8169. static void parsefname(void);
  8170. static void parseheredoc(void);
  8171. static char peektoken(void);
  8172. static int readtoken(void);
  8173. static int xxreadtoken(void);
  8174. static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
  8175. static int noexpand(char *);
  8176. static void synexpect(int) __attribute__((__noreturn__));
  8177. static void synerror(const char *) __attribute__((__noreturn__));
  8178. static void setprompt(int);
  8179. static inline int
  8180. isassignment(const char *p)
  8181. {
  8182. const char *q = endofname(p);
  8183. if (p == q)
  8184. return 0;
  8185. return *q == '=';
  8186. }
  8187. /*
  8188. * Read and parse a command. Returns NEOF on end of file. (NULL is a
  8189. * valid parse tree indicating a blank line.)
  8190. */
  8191. union node *
  8192. parsecmd(int interact)
  8193. {
  8194. int t;
  8195. tokpushback = 0;
  8196. doprompt = interact;
  8197. if (doprompt)
  8198. setprompt(doprompt);
  8199. needprompt = 0;
  8200. t = readtoken();
  8201. if (t == TEOF)
  8202. return NEOF;
  8203. if (t == TNL)
  8204. return NULL;
  8205. tokpushback++;
  8206. return list(1);
  8207. }
  8208. static union node *
  8209. list(int nlflag)
  8210. {
  8211. union node *n1, *n2, *n3;
  8212. int tok;
  8213. checkkwd = CHKNL | CHKKWD | CHKALIAS;
  8214. if (nlflag == 2 && peektoken())
  8215. return NULL;
  8216. n1 = NULL;
  8217. for (;;) {
  8218. n2 = andor();
  8219. tok = readtoken();
  8220. if (tok == TBACKGND) {
  8221. if (n2->type == NPIPE) {
  8222. n2->npipe.backgnd = 1;
  8223. } else {
  8224. if (n2->type != NREDIR) {
  8225. n3 = stalloc(sizeof(struct nredir));
  8226. n3->nredir.n = n2;
  8227. n3->nredir.redirect = NULL;
  8228. n2 = n3;
  8229. }
  8230. n2->type = NBACKGND;
  8231. }
  8232. }
  8233. if (n1 == NULL) {
  8234. n1 = n2;
  8235. }
  8236. else {
  8237. n3 = (union node *)stalloc(sizeof (struct nbinary));
  8238. n3->type = NSEMI;
  8239. n3->nbinary.ch1 = n1;
  8240. n3->nbinary.ch2 = n2;
  8241. n1 = n3;
  8242. }
  8243. switch (tok) {
  8244. case TBACKGND:
  8245. case TSEMI:
  8246. tok = readtoken();
  8247. /* fall through */
  8248. case TNL:
  8249. if (tok == TNL) {
  8250. parseheredoc();
  8251. if (nlflag == 1)
  8252. return n1;
  8253. } else {
  8254. tokpushback++;
  8255. }
  8256. checkkwd = CHKNL | CHKKWD | CHKALIAS;
  8257. if (peektoken())
  8258. return n1;
  8259. break;
  8260. case TEOF:
  8261. if (heredoclist)
  8262. parseheredoc();
  8263. else
  8264. pungetc(); /* push back EOF on input */
  8265. return n1;
  8266. default:
  8267. if (nlflag == 1)
  8268. synexpect(-1);
  8269. tokpushback++;
  8270. return n1;
  8271. }
  8272. }
  8273. }
  8274. static union node *
  8275. andor(void)
  8276. {
  8277. union node *n1, *n2, *n3;
  8278. int t;
  8279. n1 = pipeline();
  8280. for (;;) {
  8281. if ((t = readtoken()) == TAND) {
  8282. t = NAND;
  8283. } else if (t == TOR) {
  8284. t = NOR;
  8285. } else {
  8286. tokpushback++;
  8287. return n1;
  8288. }
  8289. checkkwd = CHKNL | CHKKWD | CHKALIAS;
  8290. n2 = pipeline();
  8291. n3 = (union node *)stalloc(sizeof (struct nbinary));
  8292. n3->type = t;
  8293. n3->nbinary.ch1 = n1;
  8294. n3->nbinary.ch2 = n2;
  8295. n1 = n3;
  8296. }
  8297. }
  8298. static union node *
  8299. pipeline(void)
  8300. {
  8301. union node *n1, *n2, *pipenode;
  8302. struct nodelist *lp, *prev;
  8303. int negate;
  8304. negate = 0;
  8305. TRACE(("pipeline: entered\n"));
  8306. if (readtoken() == TNOT) {
  8307. negate = !negate;
  8308. checkkwd = CHKKWD | CHKALIAS;
  8309. } else
  8310. tokpushback++;
  8311. n1 = command();
  8312. if (readtoken() == TPIPE) {
  8313. pipenode = (union node *)stalloc(sizeof (struct npipe));
  8314. pipenode->type = NPIPE;
  8315. pipenode->npipe.backgnd = 0;
  8316. lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
  8317. pipenode->npipe.cmdlist = lp;
  8318. lp->n = n1;
  8319. do {
  8320. prev = lp;
  8321. lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
  8322. checkkwd = CHKNL | CHKKWD | CHKALIAS;
  8323. lp->n = command();
  8324. prev->next = lp;
  8325. } while (readtoken() == TPIPE);
  8326. lp->next = NULL;
  8327. n1 = pipenode;
  8328. }
  8329. tokpushback++;
  8330. if (negate) {
  8331. n2 = (union node *)stalloc(sizeof (struct nnot));
  8332. n2->type = NNOT;
  8333. n2->nnot.com = n1;
  8334. return n2;
  8335. } else
  8336. return n1;
  8337. }
  8338. static union node *
  8339. command(void)
  8340. {
  8341. union node *n1, *n2;
  8342. union node *ap, **app;
  8343. union node *cp, **cpp;
  8344. union node *redir, **rpp;
  8345. union node **rpp2;
  8346. int t;
  8347. redir = NULL;
  8348. rpp2 = &redir;
  8349. switch (readtoken()) {
  8350. default:
  8351. synexpect(-1);
  8352. /* NOTREACHED */
  8353. case TIF:
  8354. n1 = (union node *)stalloc(sizeof (struct nif));
  8355. n1->type = NIF;
  8356. n1->nif.test = list(0);
  8357. if (readtoken() != TTHEN)
  8358. synexpect(TTHEN);
  8359. n1->nif.ifpart = list(0);
  8360. n2 = n1;
  8361. while (readtoken() == TELIF) {
  8362. n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
  8363. n2 = n2->nif.elsepart;
  8364. n2->type = NIF;
  8365. n2->nif.test = list(0);
  8366. if (readtoken() != TTHEN)
  8367. synexpect(TTHEN);
  8368. n2->nif.ifpart = list(0);
  8369. }
  8370. if (lasttoken == TELSE)
  8371. n2->nif.elsepart = list(0);
  8372. else {
  8373. n2->nif.elsepart = NULL;
  8374. tokpushback++;
  8375. }
  8376. t = TFI;
  8377. break;
  8378. case TWHILE:
  8379. case TUNTIL: {
  8380. int got;
  8381. n1 = (union node *)stalloc(sizeof (struct nbinary));
  8382. n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
  8383. n1->nbinary.ch1 = list(0);
  8384. if ((got=readtoken()) != TDO) {
  8385. TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
  8386. synexpect(TDO);
  8387. }
  8388. n1->nbinary.ch2 = list(0);
  8389. t = TDONE;
  8390. break;
  8391. }
  8392. case TFOR:
  8393. if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
  8394. synerror("Bad for loop variable");
  8395. n1 = (union node *)stalloc(sizeof (struct nfor));
  8396. n1->type = NFOR;
  8397. n1->nfor.var = wordtext;
  8398. checkkwd = CHKKWD | CHKALIAS;
  8399. if (readtoken() == TIN) {
  8400. app = &ap;
  8401. while (readtoken() == TWORD) {
  8402. n2 = (union node *)stalloc(sizeof (struct narg));
  8403. n2->type = NARG;
  8404. n2->narg.text = wordtext;
  8405. n2->narg.backquote = backquotelist;
  8406. *app = n2;
  8407. app = &n2->narg.next;
  8408. }
  8409. *app = NULL;
  8410. n1->nfor.args = ap;
  8411. if (lasttoken != TNL && lasttoken != TSEMI)
  8412. synexpect(-1);
  8413. } else {
  8414. n2 = (union node *)stalloc(sizeof (struct narg));
  8415. n2->type = NARG;
  8416. n2->narg.text = (char *)dolatstr;
  8417. n2->narg.backquote = NULL;
  8418. n2->narg.next = NULL;
  8419. n1->nfor.args = n2;
  8420. /*
  8421. * Newline or semicolon here is optional (but note
  8422. * that the original Bourne shell only allowed NL).
  8423. */
  8424. if (lasttoken != TNL && lasttoken != TSEMI)
  8425. tokpushback++;
  8426. }
  8427. checkkwd = CHKNL | CHKKWD | CHKALIAS;
  8428. if (readtoken() != TDO)
  8429. synexpect(TDO);
  8430. n1->nfor.body = list(0);
  8431. t = TDONE;
  8432. break;
  8433. case TCASE:
  8434. n1 = (union node *)stalloc(sizeof (struct ncase));
  8435. n1->type = NCASE;
  8436. if (readtoken() != TWORD)
  8437. synexpect(TWORD);
  8438. n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
  8439. n2->type = NARG;
  8440. n2->narg.text = wordtext;
  8441. n2->narg.backquote = backquotelist;
  8442. n2->narg.next = NULL;
  8443. do {
  8444. checkkwd = CHKKWD | CHKALIAS;
  8445. } while (readtoken() == TNL);
  8446. if (lasttoken != TIN)
  8447. synexpect(TIN);
  8448. cpp = &n1->ncase.cases;
  8449. next_case:
  8450. checkkwd = CHKNL | CHKKWD;
  8451. t = readtoken();
  8452. while(t != TESAC) {
  8453. if (lasttoken == TLP)
  8454. readtoken();
  8455. *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
  8456. cp->type = NCLIST;
  8457. app = &cp->nclist.pattern;
  8458. for (;;) {
  8459. *app = ap = (union node *)stalloc(sizeof (struct narg));
  8460. ap->type = NARG;
  8461. ap->narg.text = wordtext;
  8462. ap->narg.backquote = backquotelist;
  8463. if (readtoken() != TPIPE)
  8464. break;
  8465. app = &ap->narg.next;
  8466. readtoken();
  8467. }
  8468. ap->narg.next = NULL;
  8469. if (lasttoken != TRP)
  8470. synexpect(TRP);
  8471. cp->nclist.body = list(2);
  8472. cpp = &cp->nclist.next;
  8473. checkkwd = CHKNL | CHKKWD;
  8474. if ((t = readtoken()) != TESAC) {
  8475. if (t != TENDCASE)
  8476. synexpect(TENDCASE);
  8477. else
  8478. goto next_case;
  8479. }
  8480. }
  8481. *cpp = NULL;
  8482. goto redir;
  8483. case TLP:
  8484. n1 = (union node *)stalloc(sizeof (struct nredir));
  8485. n1->type = NSUBSHELL;
  8486. n1->nredir.n = list(0);
  8487. n1->nredir.redirect = NULL;
  8488. t = TRP;
  8489. break;
  8490. case TBEGIN:
  8491. n1 = list(0);
  8492. t = TEND;
  8493. break;
  8494. case TWORD:
  8495. case TREDIR:
  8496. tokpushback++;
  8497. return simplecmd();
  8498. }
  8499. if (readtoken() != t)
  8500. synexpect(t);
  8501. redir:
  8502. /* Now check for redirection which may follow command */
  8503. checkkwd = CHKKWD | CHKALIAS;
  8504. rpp = rpp2;
  8505. while (readtoken() == TREDIR) {
  8506. *rpp = n2 = redirnode;
  8507. rpp = &n2->nfile.next;
  8508. parsefname();
  8509. }
  8510. tokpushback++;
  8511. *rpp = NULL;
  8512. if (redir) {
  8513. if (n1->type != NSUBSHELL) {
  8514. n2 = (union node *)stalloc(sizeof (struct nredir));
  8515. n2->type = NREDIR;
  8516. n2->nredir.n = n1;
  8517. n1 = n2;
  8518. }
  8519. n1->nredir.redirect = redir;
  8520. }
  8521. return n1;
  8522. }
  8523. static union node *
  8524. simplecmd(void) {
  8525. union node *args, **app;
  8526. union node *n = NULL;
  8527. union node *vars, **vpp;
  8528. union node **rpp, *redir;
  8529. int savecheckkwd;
  8530. args = NULL;
  8531. app = &args;
  8532. vars = NULL;
  8533. vpp = &vars;
  8534. redir = NULL;
  8535. rpp = &redir;
  8536. savecheckkwd = CHKALIAS;
  8537. for (;;) {
  8538. checkkwd = savecheckkwd;
  8539. switch (readtoken()) {
  8540. case TWORD:
  8541. n = (union node *)stalloc(sizeof (struct narg));
  8542. n->type = NARG;
  8543. n->narg.text = wordtext;
  8544. n->narg.backquote = backquotelist;
  8545. if (savecheckkwd && isassignment(wordtext)) {
  8546. *vpp = n;
  8547. vpp = &n->narg.next;
  8548. } else {
  8549. *app = n;
  8550. app = &n->narg.next;
  8551. savecheckkwd = 0;
  8552. }
  8553. break;
  8554. case TREDIR:
  8555. *rpp = n = redirnode;
  8556. rpp = &n->nfile.next;
  8557. parsefname(); /* read name of redirection file */
  8558. break;
  8559. case TLP:
  8560. if (
  8561. args && app == &args->narg.next &&
  8562. !vars && !redir
  8563. ) {
  8564. struct builtincmd *bcmd;
  8565. const char *name;
  8566. /* We have a function */
  8567. if (readtoken() != TRP)
  8568. synexpect(TRP);
  8569. name = n->narg.text;
  8570. if (
  8571. !goodname(name) || (
  8572. (bcmd = find_builtin(name)) &&
  8573. IS_BUILTIN_SPECIAL(bcmd)
  8574. )
  8575. )
  8576. synerror("Bad function name");
  8577. n->type = NDEFUN;
  8578. checkkwd = CHKNL | CHKKWD | CHKALIAS;
  8579. n->narg.next = command();
  8580. return n;
  8581. }
  8582. /* fall through */
  8583. default:
  8584. tokpushback++;
  8585. goto out;
  8586. }
  8587. }
  8588. out:
  8589. *app = NULL;
  8590. *vpp = NULL;
  8591. *rpp = NULL;
  8592. n = (union node *)stalloc(sizeof (struct ncmd));
  8593. n->type = NCMD;
  8594. n->ncmd.args = args;
  8595. n->ncmd.assign = vars;
  8596. n->ncmd.redirect = redir;
  8597. return n;
  8598. }
  8599. static union node *
  8600. makename(void)
  8601. {
  8602. union node *n;
  8603. n = (union node *)stalloc(sizeof (struct narg));
  8604. n->type = NARG;
  8605. n->narg.next = NULL;
  8606. n->narg.text = wordtext;
  8607. n->narg.backquote = backquotelist;
  8608. return n;
  8609. }
  8610. void fixredir(union node *n, const char *text, int err)
  8611. {
  8612. TRACE(("Fix redir %s %d\n", text, err));
  8613. if (!err)
  8614. n->ndup.vname = NULL;
  8615. if (is_digit(text[0]) && text[1] == '\0')
  8616. n->ndup.dupfd = digit_val(text[0]);
  8617. else if (text[0] == '-' && text[1] == '\0')
  8618. n->ndup.dupfd = -1;
  8619. else {
  8620. if (err)
  8621. synerror("Bad fd number");
  8622. else
  8623. n->ndup.vname = makename();
  8624. }
  8625. }
  8626. static void
  8627. parsefname(void)
  8628. {
  8629. union node *n = redirnode;
  8630. if (readtoken() != TWORD)
  8631. synexpect(-1);
  8632. if (n->type == NHERE) {
  8633. struct heredoc *here = heredoc;
  8634. struct heredoc *p;
  8635. int i;
  8636. if (quoteflag == 0)
  8637. n->type = NXHERE;
  8638. TRACE(("Here document %d\n", n->type));
  8639. if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
  8640. synerror("Illegal eof marker for << redirection");
  8641. rmescapes(wordtext);
  8642. here->eofmark = wordtext;
  8643. here->next = NULL;
  8644. if (heredoclist == NULL)
  8645. heredoclist = here;
  8646. else {
  8647. for (p = heredoclist ; p->next ; p = p->next);
  8648. p->next = here;
  8649. }
  8650. } else if (n->type == NTOFD || n->type == NFROMFD) {
  8651. fixredir(n, wordtext, 0);
  8652. } else {
  8653. n->nfile.fname = makename();
  8654. }
  8655. }
  8656. /*
  8657. * Input any here documents.
  8658. */
  8659. static void
  8660. parseheredoc(void)
  8661. {
  8662. struct heredoc *here;
  8663. union node *n;
  8664. here = heredoclist;
  8665. heredoclist = 0;
  8666. while (here) {
  8667. if (needprompt) {
  8668. setprompt(2);
  8669. needprompt = 0;
  8670. }
  8671. readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
  8672. here->eofmark, here->striptabs);
  8673. n = (union node *)stalloc(sizeof (struct narg));
  8674. n->narg.type = NARG;
  8675. n->narg.next = NULL;
  8676. n->narg.text = wordtext;
  8677. n->narg.backquote = backquotelist;
  8678. here->here->nhere.doc = n;
  8679. here = here->next;
  8680. }
  8681. }
  8682. static char peektoken(void)
  8683. {
  8684. int t;
  8685. t = readtoken();
  8686. tokpushback++;
  8687. return tokname_array[t][0];
  8688. }
  8689. static int
  8690. readtoken(void)
  8691. {
  8692. int t;
  8693. #ifdef DEBUG
  8694. int alreadyseen = tokpushback;
  8695. #endif
  8696. #ifdef CONFIG_ASH_ALIAS
  8697. top:
  8698. #endif
  8699. t = xxreadtoken();
  8700. /*
  8701. * eat newlines
  8702. */
  8703. if (checkkwd & CHKNL) {
  8704. while (t == TNL) {
  8705. parseheredoc();
  8706. t = xxreadtoken();
  8707. }
  8708. }
  8709. if (t != TWORD || quoteflag) {
  8710. goto out;
  8711. }
  8712. /*
  8713. * check for keywords
  8714. */
  8715. if (checkkwd & CHKKWD) {
  8716. const char *const *pp;
  8717. if ((pp = findkwd(wordtext))) {
  8718. lasttoken = t = pp - tokname_array;
  8719. TRACE(("keyword %s recognized\n", tokname(t)));
  8720. goto out;
  8721. }
  8722. }
  8723. if (checkkwd & CHKALIAS) {
  8724. #ifdef CONFIG_ASH_ALIAS
  8725. struct alias *ap;
  8726. if ((ap = lookupalias(wordtext, 1)) != NULL) {
  8727. if (*ap->val) {
  8728. pushstring(ap->val, ap);
  8729. }
  8730. goto top;
  8731. }
  8732. #endif
  8733. }
  8734. out:
  8735. checkkwd = 0;
  8736. #ifdef DEBUG
  8737. if (!alreadyseen)
  8738. TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
  8739. else
  8740. TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
  8741. #endif
  8742. return (t);
  8743. }
  8744. /*
  8745. * Read the next input token.
  8746. * If the token is a word, we set backquotelist to the list of cmds in
  8747. * backquotes. We set quoteflag to true if any part of the word was
  8748. * quoted.
  8749. * If the token is TREDIR, then we set redirnode to a structure containing
  8750. * the redirection.
  8751. * In all cases, the variable startlinno is set to the number of the line
  8752. * on which the token starts.
  8753. *
  8754. * [Change comment: here documents and internal procedures]
  8755. * [Readtoken shouldn't have any arguments. Perhaps we should make the
  8756. * word parsing code into a separate routine. In this case, readtoken
  8757. * doesn't need to have any internal procedures, but parseword does.
  8758. * We could also make parseoperator in essence the main routine, and
  8759. * have parseword (readtoken1?) handle both words and redirection.]
  8760. */
  8761. #define NEW_xxreadtoken
  8762. #ifdef NEW_xxreadtoken
  8763. /* singles must be first! */
  8764. static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
  8765. static const char xxreadtoken_tokens[] = {
  8766. TNL, TLP, TRP, /* only single occurrence allowed */
  8767. TBACKGND, TPIPE, TSEMI, /* if single occurrence */
  8768. TEOF, /* corresponds to trailing nul */
  8769. TAND, TOR, TENDCASE, /* if double occurrence */
  8770. };
  8771. #define xxreadtoken_doubles \
  8772. (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
  8773. #define xxreadtoken_singles \
  8774. (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
  8775. static int xxreadtoken()
  8776. {
  8777. int c;
  8778. if (tokpushback) {
  8779. tokpushback = 0;
  8780. return lasttoken;
  8781. }
  8782. if (needprompt) {
  8783. setprompt(2);
  8784. needprompt = 0;
  8785. }
  8786. startlinno = plinno;
  8787. for (;;) { /* until token or start of word found */
  8788. c = pgetc_macro();
  8789. if ((c != ' ') && (c != '\t')
  8790. #ifdef CONFIG_ASH_ALIAS
  8791. && (c != PEOA)
  8792. #endif
  8793. ) {
  8794. if (c == '#') {
  8795. while ((c = pgetc()) != '\n' && c != PEOF);
  8796. pungetc();
  8797. } else if (c == '\\') {
  8798. if (pgetc() != '\n') {
  8799. pungetc();
  8800. goto READTOKEN1;
  8801. }
  8802. startlinno = ++plinno;
  8803. if (doprompt)
  8804. setprompt(2);
  8805. } else {
  8806. const char *p
  8807. = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
  8808. if (c != PEOF) {
  8809. if (c == '\n') {
  8810. plinno++;
  8811. needprompt = doprompt;
  8812. }
  8813. p = strchr(xxreadtoken_chars, c);
  8814. if (p == NULL) {
  8815. READTOKEN1:
  8816. return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
  8817. }
  8818. if (p - xxreadtoken_chars >= xxreadtoken_singles) {
  8819. if (pgetc() == *p) { /* double occurrence? */
  8820. p += xxreadtoken_doubles + 1;
  8821. } else {
  8822. pungetc();
  8823. }
  8824. }
  8825. }
  8826. return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
  8827. }
  8828. }
  8829. }
  8830. }
  8831. #else
  8832. #define RETURN(token) return lasttoken = token
  8833. static int
  8834. xxreadtoken(void)
  8835. {
  8836. int c;
  8837. if (tokpushback) {
  8838. tokpushback = 0;
  8839. return lasttoken;
  8840. }
  8841. if (needprompt) {
  8842. setprompt(2);
  8843. needprompt = 0;
  8844. }
  8845. startlinno = plinno;
  8846. for (;;) { /* until token or start of word found */
  8847. c = pgetc_macro();
  8848. switch (c) {
  8849. case ' ': case '\t':
  8850. #ifdef CONFIG_ASH_ALIAS
  8851. case PEOA:
  8852. #endif
  8853. continue;
  8854. case '#':
  8855. while ((c = pgetc()) != '\n' && c != PEOF);
  8856. pungetc();
  8857. continue;
  8858. case '\\':
  8859. if (pgetc() == '\n') {
  8860. startlinno = ++plinno;
  8861. if (doprompt)
  8862. setprompt(2);
  8863. continue;
  8864. }
  8865. pungetc();
  8866. goto breakloop;
  8867. case '\n':
  8868. plinno++;
  8869. needprompt = doprompt;
  8870. RETURN(TNL);
  8871. case PEOF:
  8872. RETURN(TEOF);
  8873. case '&':
  8874. if (pgetc() == '&')
  8875. RETURN(TAND);
  8876. pungetc();
  8877. RETURN(TBACKGND);
  8878. case '|':
  8879. if (pgetc() == '|')
  8880. RETURN(TOR);
  8881. pungetc();
  8882. RETURN(TPIPE);
  8883. case ';':
  8884. if (pgetc() == ';')
  8885. RETURN(TENDCASE);
  8886. pungetc();
  8887. RETURN(TSEMI);
  8888. case '(':
  8889. RETURN(TLP);
  8890. case ')':
  8891. RETURN(TRP);
  8892. default:
  8893. goto breakloop;
  8894. }
  8895. }
  8896. breakloop:
  8897. return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
  8898. #undef RETURN
  8899. }
  8900. #endif /* NEW_xxreadtoken */
  8901. /*
  8902. * If eofmark is NULL, read a word or a redirection symbol. If eofmark
  8903. * is not NULL, read a here document. In the latter case, eofmark is the
  8904. * word which marks the end of the document and striptabs is true if
  8905. * leading tabs should be stripped from the document. The argument firstc
  8906. * is the first character of the input token or document.
  8907. *
  8908. * Because C does not have internal subroutines, I have simulated them
  8909. * using goto's to implement the subroutine linkage. The following macros
  8910. * will run code that appears at the end of readtoken1.
  8911. */
  8912. #define CHECKEND() {goto checkend; checkend_return:;}
  8913. #define PARSEREDIR() {goto parseredir; parseredir_return:;}
  8914. #define PARSESUB() {goto parsesub; parsesub_return:;}
  8915. #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
  8916. #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
  8917. #define PARSEARITH() {goto parsearith; parsearith_return:;}
  8918. static int
  8919. readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
  8920. {
  8921. int c = firstc;
  8922. char *out;
  8923. int len;
  8924. char line[EOFMARKLEN + 1];
  8925. struct nodelist *bqlist;
  8926. int quotef;
  8927. int dblquote;
  8928. int varnest; /* levels of variables expansion */
  8929. int arinest; /* levels of arithmetic expansion */
  8930. int parenlevel; /* levels of parens in arithmetic */
  8931. int dqvarnest; /* levels of variables expansion within double quotes */
  8932. int oldstyle;
  8933. int prevsyntax; /* syntax before arithmetic */
  8934. #if __GNUC__
  8935. /* Avoid longjmp clobbering */
  8936. (void) &out;
  8937. (void) &quotef;
  8938. (void) &dblquote;
  8939. (void) &varnest;
  8940. (void) &arinest;
  8941. (void) &parenlevel;
  8942. (void) &dqvarnest;
  8943. (void) &oldstyle;
  8944. (void) &prevsyntax;
  8945. (void) &syntax;
  8946. #endif
  8947. startlinno = plinno;
  8948. dblquote = 0;
  8949. if (syntax == DQSYNTAX)
  8950. dblquote = 1;
  8951. quotef = 0;
  8952. bqlist = NULL;
  8953. varnest = 0;
  8954. arinest = 0;
  8955. parenlevel = 0;
  8956. dqvarnest = 0;
  8957. STARTSTACKSTR(out);
  8958. loop: { /* for each line, until end of word */
  8959. CHECKEND(); /* set c to PEOF if at end of here document */
  8960. for (;;) { /* until end of line or end of word */
  8961. CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
  8962. switch(SIT(c, syntax)) {
  8963. case CNL: /* '\n' */
  8964. if (syntax == BASESYNTAX)
  8965. goto endword; /* exit outer loop */
  8966. USTPUTC(c, out);
  8967. plinno++;
  8968. if (doprompt)
  8969. setprompt(2);
  8970. c = pgetc();
  8971. goto loop; /* continue outer loop */
  8972. case CWORD:
  8973. USTPUTC(c, out);
  8974. break;
  8975. case CCTL:
  8976. if (eofmark == NULL || dblquote)
  8977. USTPUTC(CTLESC, out);
  8978. USTPUTC(c, out);
  8979. break;
  8980. case CBACK: /* backslash */
  8981. c = pgetc2();
  8982. if (c == PEOF) {
  8983. USTPUTC(CTLESC, out);
  8984. USTPUTC('\\', out);
  8985. pungetc();
  8986. } else if (c == '\n') {
  8987. if (doprompt)
  8988. setprompt(2);
  8989. } else {
  8990. if (
  8991. dblquote &&
  8992. c != '\\' && c != '`' &&
  8993. c != '$' && (
  8994. c != '"' ||
  8995. eofmark != NULL
  8996. )
  8997. ) {
  8998. USTPUTC(CTLESC, out);
  8999. USTPUTC('\\', out);
  9000. }
  9001. if (SIT(c, SQSYNTAX) == CCTL)
  9002. USTPUTC(CTLESC, out);
  9003. USTPUTC(c, out);
  9004. quotef++;
  9005. }
  9006. break;
  9007. case CSQUOTE:
  9008. syntax = SQSYNTAX;
  9009. quotemark:
  9010. if (eofmark == NULL) {
  9011. USTPUTC(CTLQUOTEMARK, out);
  9012. }
  9013. break;
  9014. case CDQUOTE:
  9015. syntax = DQSYNTAX;
  9016. dblquote = 1;
  9017. goto quotemark;
  9018. case CENDQUOTE:
  9019. if (eofmark != NULL && arinest == 0 &&
  9020. varnest == 0) {
  9021. USTPUTC(c, out);
  9022. } else {
  9023. if (dqvarnest == 0) {
  9024. syntax = BASESYNTAX;
  9025. dblquote = 0;
  9026. }
  9027. quotef++;
  9028. goto quotemark;
  9029. }
  9030. break;
  9031. case CVAR: /* '$' */
  9032. PARSESUB(); /* parse substitution */
  9033. break;
  9034. case CENDVAR: /* '}' */
  9035. if (varnest > 0) {
  9036. varnest--;
  9037. if (dqvarnest > 0) {
  9038. dqvarnest--;
  9039. }
  9040. USTPUTC(CTLENDVAR, out);
  9041. } else {
  9042. USTPUTC(c, out);
  9043. }
  9044. break;
  9045. #ifdef CONFIG_ASH_MATH_SUPPORT
  9046. case CLP: /* '(' in arithmetic */
  9047. parenlevel++;
  9048. USTPUTC(c, out);
  9049. break;
  9050. case CRP: /* ')' in arithmetic */
  9051. if (parenlevel > 0) {
  9052. USTPUTC(c, out);
  9053. --parenlevel;
  9054. } else {
  9055. if (pgetc() == ')') {
  9056. if (--arinest == 0) {
  9057. USTPUTC(CTLENDARI, out);
  9058. syntax = prevsyntax;
  9059. if (syntax == DQSYNTAX)
  9060. dblquote = 1;
  9061. else
  9062. dblquote = 0;
  9063. } else
  9064. USTPUTC(')', out);
  9065. } else {
  9066. /*
  9067. * unbalanced parens
  9068. * (don't 2nd guess - no error)
  9069. */
  9070. pungetc();
  9071. USTPUTC(')', out);
  9072. }
  9073. }
  9074. break;
  9075. #endif
  9076. case CBQUOTE: /* '`' */
  9077. PARSEBACKQOLD();
  9078. break;
  9079. case CENDFILE:
  9080. goto endword; /* exit outer loop */
  9081. case CIGN:
  9082. break;
  9083. default:
  9084. if (varnest == 0)
  9085. goto endword; /* exit outer loop */
  9086. #ifdef CONFIG_ASH_ALIAS
  9087. if (c != PEOA)
  9088. #endif
  9089. USTPUTC(c, out);
  9090. }
  9091. c = pgetc_macro();
  9092. }
  9093. }
  9094. endword:
  9095. #ifdef CONFIG_ASH_MATH_SUPPORT
  9096. if (syntax == ARISYNTAX)
  9097. synerror("Missing '))'");
  9098. #endif
  9099. if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
  9100. synerror("Unterminated quoted string");
  9101. if (varnest != 0) {
  9102. startlinno = plinno;
  9103. /* { */
  9104. synerror("Missing '}'");
  9105. }
  9106. USTPUTC('\0', out);
  9107. len = out - (char *)stackblock();
  9108. out = stackblock();
  9109. if (eofmark == NULL) {
  9110. if ((c == '>' || c == '<')
  9111. && quotef == 0
  9112. && len <= 2
  9113. && (*out == '\0' || is_digit(*out))) {
  9114. PARSEREDIR();
  9115. return lasttoken = TREDIR;
  9116. } else {
  9117. pungetc();
  9118. }
  9119. }
  9120. quoteflag = quotef;
  9121. backquotelist = bqlist;
  9122. grabstackblock(len);
  9123. wordtext = out;
  9124. return lasttoken = TWORD;
  9125. /* end of readtoken routine */
  9126. /*
  9127. * Check to see whether we are at the end of the here document. When this
  9128. * is called, c is set to the first character of the next input line. If
  9129. * we are at the end of the here document, this routine sets the c to PEOF.
  9130. */
  9131. checkend: {
  9132. if (eofmark) {
  9133. #ifdef CONFIG_ASH_ALIAS
  9134. if (c == PEOA) {
  9135. c = pgetc2();
  9136. }
  9137. #endif
  9138. if (striptabs) {
  9139. while (c == '\t') {
  9140. c = pgetc2();
  9141. }
  9142. }
  9143. if (c == *eofmark) {
  9144. if (pfgets(line, sizeof line) != NULL) {
  9145. char *p, *q;
  9146. p = line;
  9147. for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
  9148. if (*p == '\n' && *q == '\0') {
  9149. c = PEOF;
  9150. plinno++;
  9151. needprompt = doprompt;
  9152. } else {
  9153. pushstring(line, NULL);
  9154. }
  9155. }
  9156. }
  9157. }
  9158. goto checkend_return;
  9159. }
  9160. /*
  9161. * Parse a redirection operator. The variable "out" points to a string
  9162. * specifying the fd to be redirected. The variable "c" contains the
  9163. * first character of the redirection operator.
  9164. */
  9165. parseredir: {
  9166. char fd = *out;
  9167. union node *np;
  9168. np = (union node *)stalloc(sizeof (struct nfile));
  9169. if (c == '>') {
  9170. np->nfile.fd = 1;
  9171. c = pgetc();
  9172. if (c == '>')
  9173. np->type = NAPPEND;
  9174. else if (c == '|')
  9175. np->type = NCLOBBER;
  9176. else if (c == '&')
  9177. np->type = NTOFD;
  9178. else {
  9179. np->type = NTO;
  9180. pungetc();
  9181. }
  9182. } else { /* c == '<' */
  9183. np->nfile.fd = 0;
  9184. switch (c = pgetc()) {
  9185. case '<':
  9186. if (sizeof (struct nfile) != sizeof (struct nhere)) {
  9187. np = (union node *)stalloc(sizeof (struct nhere));
  9188. np->nfile.fd = 0;
  9189. }
  9190. np->type = NHERE;
  9191. heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
  9192. heredoc->here = np;
  9193. if ((c = pgetc()) == '-') {
  9194. heredoc->striptabs = 1;
  9195. } else {
  9196. heredoc->striptabs = 0;
  9197. pungetc();
  9198. }
  9199. break;
  9200. case '&':
  9201. np->type = NFROMFD;
  9202. break;
  9203. case '>':
  9204. np->type = NFROMTO;
  9205. break;
  9206. default:
  9207. np->type = NFROM;
  9208. pungetc();
  9209. break;
  9210. }
  9211. }
  9212. if (fd != '\0')
  9213. np->nfile.fd = digit_val(fd);
  9214. redirnode = np;
  9215. goto parseredir_return;
  9216. }
  9217. /*
  9218. * Parse a substitution. At this point, we have read the dollar sign
  9219. * and nothing else.
  9220. */
  9221. parsesub: {
  9222. int subtype;
  9223. int typeloc;
  9224. int flags;
  9225. char *p;
  9226. static const char types[] = "}-+?=";
  9227. c = pgetc();
  9228. if (
  9229. c <= PEOA_OR_PEOF ||
  9230. (c != '(' && c != '{' && !is_name(c) && !is_special(c))
  9231. ) {
  9232. USTPUTC('$', out);
  9233. pungetc();
  9234. } else if (c == '(') { /* $(command) or $((arith)) */
  9235. if (pgetc() == '(') {
  9236. #ifdef CONFIG_ASH_MATH_SUPPORT
  9237. PARSEARITH();
  9238. #else
  9239. synerror("We unsupport $((arith))");
  9240. #endif
  9241. } else {
  9242. pungetc();
  9243. PARSEBACKQNEW();
  9244. }
  9245. } else {
  9246. USTPUTC(CTLVAR, out);
  9247. typeloc = out - (char *)stackblock();
  9248. USTPUTC(VSNORMAL, out);
  9249. subtype = VSNORMAL;
  9250. if (c == '{') {
  9251. c = pgetc();
  9252. if (c == '#') {
  9253. if ((c = pgetc()) == '}')
  9254. c = '#';
  9255. else
  9256. subtype = VSLENGTH;
  9257. }
  9258. else
  9259. subtype = 0;
  9260. }
  9261. if (c > PEOA_OR_PEOF && is_name(c)) {
  9262. do {
  9263. STPUTC(c, out);
  9264. c = pgetc();
  9265. } while (c > PEOA_OR_PEOF && is_in_name(c));
  9266. } else if (is_digit(c)) {
  9267. do {
  9268. STPUTC(c, out);
  9269. c = pgetc();
  9270. } while (is_digit(c));
  9271. }
  9272. else if (is_special(c)) {
  9273. USTPUTC(c, out);
  9274. c = pgetc();
  9275. }
  9276. else
  9277. badsub: synerror("Bad substitution");
  9278. STPUTC('=', out);
  9279. flags = 0;
  9280. if (subtype == 0) {
  9281. switch (c) {
  9282. case ':':
  9283. flags = VSNUL;
  9284. c = pgetc();
  9285. /*FALLTHROUGH*/
  9286. default:
  9287. p = strchr(types, c);
  9288. if (p == NULL)
  9289. goto badsub;
  9290. subtype = p - types + VSNORMAL;
  9291. break;
  9292. case '%':
  9293. case '#':
  9294. {
  9295. int cc = c;
  9296. subtype = c == '#' ? VSTRIMLEFT :
  9297. VSTRIMRIGHT;
  9298. c = pgetc();
  9299. if (c == cc)
  9300. subtype++;
  9301. else
  9302. pungetc();
  9303. break;
  9304. }
  9305. }
  9306. } else {
  9307. pungetc();
  9308. }
  9309. if (dblquote || arinest)
  9310. flags |= VSQUOTE;
  9311. *((char *)stackblock() + typeloc) = subtype | flags;
  9312. if (subtype != VSNORMAL) {
  9313. varnest++;
  9314. if (dblquote || arinest) {
  9315. dqvarnest++;
  9316. }
  9317. }
  9318. }
  9319. goto parsesub_return;
  9320. }
  9321. /*
  9322. * Called to parse command substitutions. Newstyle is set if the command
  9323. * is enclosed inside $(...); nlpp is a pointer to the head of the linked
  9324. * list of commands (passed by reference), and savelen is the number of
  9325. * characters on the top of the stack which must be preserved.
  9326. */
  9327. parsebackq: {
  9328. struct nodelist **nlpp;
  9329. int savepbq;
  9330. union node *n;
  9331. char *volatile str;
  9332. struct jmploc jmploc;
  9333. struct jmploc *volatile savehandler;
  9334. size_t savelen;
  9335. int saveprompt;
  9336. #ifdef __GNUC__
  9337. (void) &saveprompt;
  9338. #endif
  9339. savepbq = parsebackquote;
  9340. if (setjmp(jmploc.loc)) {
  9341. if (str)
  9342. ckfree(str);
  9343. parsebackquote = 0;
  9344. handler = savehandler;
  9345. longjmp(handler->loc, 1);
  9346. }
  9347. INTOFF;
  9348. str = NULL;
  9349. savelen = out - (char *)stackblock();
  9350. if (savelen > 0) {
  9351. str = ckmalloc(savelen);
  9352. memcpy(str, stackblock(), savelen);
  9353. }
  9354. savehandler = handler;
  9355. handler = &jmploc;
  9356. INTON;
  9357. if (oldstyle) {
  9358. /* We must read until the closing backquote, giving special
  9359. treatment to some slashes, and then push the string and
  9360. reread it as input, interpreting it normally. */
  9361. char *pout;
  9362. int pc;
  9363. size_t psavelen;
  9364. char *pstr;
  9365. STARTSTACKSTR(pout);
  9366. for (;;) {
  9367. if (needprompt) {
  9368. setprompt(2);
  9369. needprompt = 0;
  9370. }
  9371. switch (pc = pgetc()) {
  9372. case '`':
  9373. goto done;
  9374. case '\\':
  9375. if ((pc = pgetc()) == '\n') {
  9376. plinno++;
  9377. if (doprompt)
  9378. setprompt(2);
  9379. /*
  9380. * If eating a newline, avoid putting
  9381. * the newline into the new character
  9382. * stream (via the STPUTC after the
  9383. * switch).
  9384. */
  9385. continue;
  9386. }
  9387. if (pc != '\\' && pc != '`' && pc != '$'
  9388. && (!dblquote || pc != '"'))
  9389. STPUTC('\\', pout);
  9390. if (pc > PEOA_OR_PEOF) {
  9391. break;
  9392. }
  9393. /* fall through */
  9394. case PEOF:
  9395. #ifdef CONFIG_ASH_ALIAS
  9396. case PEOA:
  9397. #endif
  9398. startlinno = plinno;
  9399. synerror("EOF in backquote substitution");
  9400. case '\n':
  9401. plinno++;
  9402. needprompt = doprompt;
  9403. break;
  9404. default:
  9405. break;
  9406. }
  9407. STPUTC(pc, pout);
  9408. }
  9409. done:
  9410. STPUTC('\0', pout);
  9411. psavelen = pout - (char *)stackblock();
  9412. if (psavelen > 0) {
  9413. pstr = grabstackstr(pout);
  9414. setinputstring(pstr);
  9415. }
  9416. }
  9417. nlpp = &bqlist;
  9418. while (*nlpp)
  9419. nlpp = &(*nlpp)->next;
  9420. *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
  9421. (*nlpp)->next = NULL;
  9422. parsebackquote = oldstyle;
  9423. if (oldstyle) {
  9424. saveprompt = doprompt;
  9425. doprompt = 0;
  9426. }
  9427. n = list(2);
  9428. if (oldstyle)
  9429. doprompt = saveprompt;
  9430. else {
  9431. if (readtoken() != TRP)
  9432. synexpect(TRP);
  9433. }
  9434. (*nlpp)->n = n;
  9435. if (oldstyle) {
  9436. /*
  9437. * Start reading from old file again, ignoring any pushed back
  9438. * tokens left from the backquote parsing
  9439. */
  9440. popfile();
  9441. tokpushback = 0;
  9442. }
  9443. while (stackblocksize() <= savelen)
  9444. growstackblock();
  9445. STARTSTACKSTR(out);
  9446. if (str) {
  9447. memcpy(out, str, savelen);
  9448. STADJUST(savelen, out);
  9449. INTOFF;
  9450. ckfree(str);
  9451. str = NULL;
  9452. INTON;
  9453. }
  9454. parsebackquote = savepbq;
  9455. handler = savehandler;
  9456. if (arinest || dblquote)
  9457. USTPUTC(CTLBACKQ | CTLQUOTE, out);
  9458. else
  9459. USTPUTC(CTLBACKQ, out);
  9460. if (oldstyle)
  9461. goto parsebackq_oldreturn;
  9462. else
  9463. goto parsebackq_newreturn;
  9464. }
  9465. #ifdef CONFIG_ASH_MATH_SUPPORT
  9466. /*
  9467. * Parse an arithmetic expansion (indicate start of one and set state)
  9468. */
  9469. parsearith: {
  9470. if (++arinest == 1) {
  9471. prevsyntax = syntax;
  9472. syntax = ARISYNTAX;
  9473. USTPUTC(CTLARI, out);
  9474. if (dblquote)
  9475. USTPUTC('"',out);
  9476. else
  9477. USTPUTC(' ',out);
  9478. } else {
  9479. /*
  9480. * we collapse embedded arithmetic expansion to
  9481. * parenthesis, which should be equivalent
  9482. */
  9483. USTPUTC('(', out);
  9484. }
  9485. goto parsearith_return;
  9486. }
  9487. #endif
  9488. } /* end of readtoken */
  9489. /*
  9490. * Returns true if the text contains nothing to expand (no dollar signs
  9491. * or backquotes).
  9492. */
  9493. static int
  9494. noexpand(char *text)
  9495. {
  9496. char *p;
  9497. char c;
  9498. p = text;
  9499. while ((c = *p++) != '\0') {
  9500. if (c == CTLQUOTEMARK)
  9501. continue;
  9502. if (c == CTLESC)
  9503. p++;
  9504. else if (SIT(c, BASESYNTAX) == CCTL)
  9505. return 0;
  9506. }
  9507. return 1;
  9508. }
  9509. /*
  9510. * Return of a legal variable name (a letter or underscore followed by zero or
  9511. * more letters, underscores, and digits).
  9512. */
  9513. static char *
  9514. endofname(const char *name)
  9515. {
  9516. char *p;
  9517. p = (char *) name;
  9518. if (! is_name(*p))
  9519. return p;
  9520. while (*++p) {
  9521. if (! is_in_name(*p))
  9522. break;
  9523. }
  9524. return p;
  9525. }
  9526. /*
  9527. * Called when an unexpected token is read during the parse. The argument
  9528. * is the token that is expected, or -1 if more than one type of token can
  9529. * occur at this point.
  9530. */
  9531. static void synexpect(int token)
  9532. {
  9533. char msg[64];
  9534. int l;
  9535. l = sprintf(msg, "%s unexpected", tokname(lasttoken));
  9536. if (token >= 0)
  9537. sprintf(msg + l, " (expecting %s)", tokname(token));
  9538. synerror(msg);
  9539. /* NOTREACHED */
  9540. }
  9541. static void
  9542. synerror(const char *msg)
  9543. {
  9544. error("Syntax error: %s", msg);
  9545. /* NOTREACHED */
  9546. }
  9547. /*
  9548. * called by editline -- any expansions to the prompt
  9549. * should be added here.
  9550. */
  9551. static void setprompt(int whichprompt)
  9552. {
  9553. const char *prompt;
  9554. switch (whichprompt) {
  9555. case 1:
  9556. prompt = ps1val();
  9557. break;
  9558. case 2:
  9559. prompt = ps2val();
  9560. break;
  9561. default: /* 0 */
  9562. prompt = nullstr;
  9563. }
  9564. putprompt(prompt);
  9565. }
  9566. static const char *const *findkwd(const char *s)
  9567. {
  9568. return bsearch(s, tokname_array + KWDOFFSET,
  9569. (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
  9570. sizeof(const char *), pstrcmp);
  9571. }
  9572. /* $NetBSD: redir.c,v 1.27 2002/11/24 22:35:42 christos Exp $ */
  9573. /*
  9574. * Code for dealing with input/output redirection.
  9575. */
  9576. #define EMPTY -2 /* marks an unused slot in redirtab */
  9577. #ifndef PIPE_BUF
  9578. # define PIPESIZE 4096 /* amount of buffering in a pipe */
  9579. #else
  9580. # define PIPESIZE PIPE_BUF
  9581. #endif
  9582. /*
  9583. * Open a file in noclobber mode.
  9584. * The code was copied from bash.
  9585. */
  9586. static inline int
  9587. noclobberopen(const char *fname)
  9588. {
  9589. int r, fd;
  9590. struct stat finfo, finfo2;
  9591. /*
  9592. * If the file exists and is a regular file, return an error
  9593. * immediately.
  9594. */
  9595. r = stat(fname, &finfo);
  9596. if (r == 0 && S_ISREG(finfo.st_mode)) {
  9597. errno = EEXIST;
  9598. return -1;
  9599. }
  9600. /*
  9601. * If the file was not present (r != 0), make sure we open it
  9602. * exclusively so that if it is created before we open it, our open
  9603. * will fail. Make sure that we do not truncate an existing file.
  9604. * Note that we don't turn on O_EXCL unless the stat failed -- if the
  9605. * file was not a regular file, we leave O_EXCL off.
  9606. */
  9607. if (r != 0)
  9608. return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
  9609. fd = open(fname, O_WRONLY|O_CREAT, 0666);
  9610. /* If the open failed, return the file descriptor right away. */
  9611. if (fd < 0)
  9612. return fd;
  9613. /*
  9614. * OK, the open succeeded, but the file may have been changed from a
  9615. * non-regular file to a regular file between the stat and the open.
  9616. * We are assuming that the O_EXCL open handles the case where FILENAME
  9617. * did not exist and is symlinked to an existing file between the stat
  9618. * and open.
  9619. */
  9620. /*
  9621. * If we can open it and fstat the file descriptor, and neither check
  9622. * revealed that it was a regular file, and the file has not been
  9623. * replaced, return the file descriptor.
  9624. */
  9625. if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
  9626. finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
  9627. return fd;
  9628. /* The file has been replaced. badness. */
  9629. close(fd);
  9630. errno = EEXIST;
  9631. return -1;
  9632. }
  9633. /*
  9634. * Handle here documents. Normally we fork off a process to write the
  9635. * data to a pipe. If the document is short, we can stuff the data in
  9636. * the pipe without forking.
  9637. */
  9638. static inline int
  9639. openhere(union node *redir)
  9640. {
  9641. int pip[2];
  9642. size_t len = 0;
  9643. if (pipe(pip) < 0)
  9644. error("Pipe call failed");
  9645. if (redir->type == NHERE) {
  9646. len = strlen(redir->nhere.doc->narg.text);
  9647. if (len <= PIPESIZE) {
  9648. bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
  9649. goto out;
  9650. }
  9651. }
  9652. if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
  9653. close(pip[0]);
  9654. signal(SIGINT, SIG_IGN);
  9655. signal(SIGQUIT, SIG_IGN);
  9656. signal(SIGHUP, SIG_IGN);
  9657. #ifdef SIGTSTP
  9658. signal(SIGTSTP, SIG_IGN);
  9659. #endif
  9660. signal(SIGPIPE, SIG_DFL);
  9661. if (redir->type == NHERE)
  9662. bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
  9663. else
  9664. expandhere(redir->nhere.doc, pip[1]);
  9665. _exit(0);
  9666. }
  9667. out:
  9668. close(pip[1]);
  9669. return pip[0];
  9670. }
  9671. static int
  9672. openredirect(union node *redir)
  9673. {
  9674. char *fname;
  9675. int f;
  9676. switch (redir->nfile.type) {
  9677. case NFROM:
  9678. fname = redir->nfile.expfname;
  9679. if ((f = open(fname, O_RDONLY)) < 0)
  9680. goto eopen;
  9681. break;
  9682. case NFROMTO:
  9683. fname = redir->nfile.expfname;
  9684. if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
  9685. goto ecreate;
  9686. break;
  9687. case NTO:
  9688. /* Take care of noclobber mode. */
  9689. if (Cflag) {
  9690. fname = redir->nfile.expfname;
  9691. if ((f = noclobberopen(fname)) < 0)
  9692. goto ecreate;
  9693. break;
  9694. }
  9695. /* FALLTHROUGH */
  9696. case NCLOBBER:
  9697. fname = redir->nfile.expfname;
  9698. if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
  9699. goto ecreate;
  9700. break;
  9701. case NAPPEND:
  9702. fname = redir->nfile.expfname;
  9703. if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
  9704. goto ecreate;
  9705. break;
  9706. default:
  9707. #ifdef DEBUG
  9708. abort();
  9709. #endif
  9710. /* Fall through to eliminate warning. */
  9711. case NTOFD:
  9712. case NFROMFD:
  9713. f = -1;
  9714. break;
  9715. case NHERE:
  9716. case NXHERE:
  9717. f = openhere(redir);
  9718. break;
  9719. }
  9720. return f;
  9721. ecreate:
  9722. error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
  9723. eopen:
  9724. error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
  9725. }
  9726. static inline void
  9727. dupredirect(union node *redir, int f)
  9728. {
  9729. int fd = redir->nfile.fd;
  9730. if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
  9731. if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
  9732. copyfd(redir->ndup.dupfd, fd);
  9733. }
  9734. return;
  9735. }
  9736. if (f != fd) {
  9737. copyfd(f, fd);
  9738. close(f);
  9739. }
  9740. return;
  9741. }
  9742. /*
  9743. * Process a list of redirection commands. If the REDIR_PUSH flag is set,
  9744. * old file descriptors are stashed away so that the redirection can be
  9745. * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
  9746. * standard output, and the standard error if it becomes a duplicate of
  9747. * stdout, is saved in memory.
  9748. */
  9749. static void
  9750. redirect(union node *redir, int flags)
  9751. {
  9752. union node *n;
  9753. struct redirtab *sv;
  9754. int i;
  9755. int fd;
  9756. int newfd;
  9757. int *p;
  9758. nullredirs++;
  9759. if (!redir) {
  9760. return;
  9761. }
  9762. sv = NULL;
  9763. INTOFF;
  9764. if (flags & REDIR_PUSH) {
  9765. struct redirtab *q;
  9766. q = ckmalloc(sizeof (struct redirtab));
  9767. q->next = redirlist;
  9768. redirlist = q;
  9769. q->nullredirs = nullredirs - 1;
  9770. for (i = 0 ; i < 10 ; i++)
  9771. q->renamed[i] = EMPTY;
  9772. nullredirs = 0;
  9773. sv = q;
  9774. }
  9775. n = redir;
  9776. do {
  9777. fd = n->nfile.fd;
  9778. if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
  9779. n->ndup.dupfd == fd)
  9780. continue; /* redirect from/to same file descriptor */
  9781. newfd = openredirect(n);
  9782. if (fd == newfd)
  9783. continue;
  9784. if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
  9785. i = fcntl(fd, F_DUPFD, 10);
  9786. if (i == -1) {
  9787. i = errno;
  9788. if (i != EBADF) {
  9789. close(newfd);
  9790. errno = i;
  9791. error("%d: %m", fd);
  9792. /* NOTREACHED */
  9793. }
  9794. } else {
  9795. *p = i;
  9796. close(fd);
  9797. }
  9798. } else {
  9799. close(fd);
  9800. }
  9801. dupredirect(n, newfd);
  9802. } while ((n = n->nfile.next));
  9803. INTON;
  9804. if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
  9805. preverrout_fd = sv->renamed[2];
  9806. }
  9807. /*
  9808. * Undo the effects of the last redirection.
  9809. */
  9810. void
  9811. popredir(int drop)
  9812. {
  9813. struct redirtab *rp;
  9814. int i;
  9815. if (--nullredirs >= 0)
  9816. return;
  9817. INTOFF;
  9818. rp = redirlist;
  9819. for (i = 0 ; i < 10 ; i++) {
  9820. if (rp->renamed[i] != EMPTY) {
  9821. if (!drop) {
  9822. close(i);
  9823. copyfd(rp->renamed[i], i);
  9824. }
  9825. close(rp->renamed[i]);
  9826. }
  9827. }
  9828. redirlist = rp->next;
  9829. nullredirs = rp->nullredirs;
  9830. ckfree(rp);
  9831. INTON;
  9832. }
  9833. /*
  9834. * Undo all redirections. Called on error or interrupt.
  9835. */
  9836. /*
  9837. * Discard all saved file descriptors.
  9838. */
  9839. void
  9840. clearredir(int drop)
  9841. {
  9842. for (;;) {
  9843. nullredirs = 0;
  9844. if (!redirlist)
  9845. break;
  9846. popredir(drop);
  9847. }
  9848. }
  9849. /*
  9850. * Copy a file descriptor to be >= to. Returns -1
  9851. * if the source file descriptor is closed, EMPTY if there are no unused
  9852. * file descriptors left.
  9853. */
  9854. int
  9855. copyfd(int from, int to)
  9856. {
  9857. int newfd;
  9858. newfd = fcntl(from, F_DUPFD, to);
  9859. if (newfd < 0) {
  9860. if (errno == EMFILE)
  9861. return EMPTY;
  9862. else
  9863. error("%d: %m", from);
  9864. }
  9865. return newfd;
  9866. }
  9867. int
  9868. redirectsafe(union node *redir, int flags)
  9869. {
  9870. int err;
  9871. volatile int saveint;
  9872. struct jmploc *volatile savehandler = handler;
  9873. struct jmploc jmploc;
  9874. SAVEINT(saveint);
  9875. if (!(err = setjmp(jmploc.loc) * 2)) {
  9876. handler = &jmploc;
  9877. redirect(redir, flags);
  9878. }
  9879. handler = savehandler;
  9880. if (err && exception != EXERROR)
  9881. longjmp(handler->loc, 1);
  9882. RESTOREINT(saveint);
  9883. return err;
  9884. }
  9885. /* $NetBSD: show.c,v 1.24 2003/01/22 20:36:04 dsl Exp $ */
  9886. #ifdef DEBUG
  9887. static void shtree(union node *, int, char *, FILE*);
  9888. static void shcmd(union node *, FILE *);
  9889. static void sharg(union node *, FILE *);
  9890. static void indent(int, char *, FILE *);
  9891. static void trstring(char *);
  9892. void
  9893. showtree(union node *n)
  9894. {
  9895. trputs("showtree called\n");
  9896. shtree(n, 1, NULL, stdout);
  9897. }
  9898. static void
  9899. shtree(union node *n, int ind, char *pfx, FILE *fp)
  9900. {
  9901. struct nodelist *lp;
  9902. const char *s;
  9903. if (n == NULL)
  9904. return;
  9905. indent(ind, pfx, fp);
  9906. switch(n->type) {
  9907. case NSEMI:
  9908. s = "; ";
  9909. goto binop;
  9910. case NAND:
  9911. s = " && ";
  9912. goto binop;
  9913. case NOR:
  9914. s = " || ";
  9915. binop:
  9916. shtree(n->nbinary.ch1, ind, NULL, fp);
  9917. /* if (ind < 0) */
  9918. fputs(s, fp);
  9919. shtree(n->nbinary.ch2, ind, NULL, fp);
  9920. break;
  9921. case NCMD:
  9922. shcmd(n, fp);
  9923. if (ind >= 0)
  9924. putc('\n', fp);
  9925. break;
  9926. case NPIPE:
  9927. for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
  9928. shcmd(lp->n, fp);
  9929. if (lp->next)
  9930. fputs(" | ", fp);
  9931. }
  9932. if (n->npipe.backgnd)
  9933. fputs(" &", fp);
  9934. if (ind >= 0)
  9935. putc('\n', fp);
  9936. break;
  9937. default:
  9938. fprintf(fp, "<node type %d>", n->type);
  9939. if (ind >= 0)
  9940. putc('\n', fp);
  9941. break;
  9942. }
  9943. }
  9944. static void
  9945. shcmd(union node *cmd, FILE *fp)
  9946. {
  9947. union node *np;
  9948. int first;
  9949. const char *s;
  9950. int dftfd;
  9951. first = 1;
  9952. for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
  9953. if (! first)
  9954. putchar(' ');
  9955. sharg(np, fp);
  9956. first = 0;
  9957. }
  9958. for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
  9959. if (! first)
  9960. putchar(' ');
  9961. switch (np->nfile.type) {
  9962. case NTO: s = ">"; dftfd = 1; break;
  9963. case NCLOBBER: s = ">|"; dftfd = 1; break;
  9964. case NAPPEND: s = ">>"; dftfd = 1; break;
  9965. case NTOFD: s = ">&"; dftfd = 1; break;
  9966. case NFROM: s = "<"; dftfd = 0; break;
  9967. case NFROMFD: s = "<&"; dftfd = 0; break;
  9968. case NFROMTO: s = "<>"; dftfd = 0; break;
  9969. default: s = "*error*"; dftfd = 0; break;
  9970. }
  9971. if (np->nfile.fd != dftfd)
  9972. fprintf(fp, "%d", np->nfile.fd);
  9973. fputs(s, fp);
  9974. if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
  9975. fprintf(fp, "%d", np->ndup.dupfd);
  9976. } else {
  9977. sharg(np->nfile.fname, fp);
  9978. }
  9979. first = 0;
  9980. }
  9981. }
  9982. static void
  9983. sharg(union node *arg, FILE *fp)
  9984. {
  9985. char *p;
  9986. struct nodelist *bqlist;
  9987. int subtype;
  9988. if (arg->type != NARG) {
  9989. out1fmt("<node type %d>\n", arg->type);
  9990. abort();
  9991. }
  9992. bqlist = arg->narg.backquote;
  9993. for (p = arg->narg.text ; *p ; p++) {
  9994. switch (*p) {
  9995. case CTLESC:
  9996. putc(*++p, fp);
  9997. break;
  9998. case CTLVAR:
  9999. putc('$', fp);
  10000. putc('{', fp);
  10001. subtype = *++p;
  10002. if (subtype == VSLENGTH)
  10003. putc('#', fp);
  10004. while (*p != '=')
  10005. putc(*p++, fp);
  10006. if (subtype & VSNUL)
  10007. putc(':', fp);
  10008. switch (subtype & VSTYPE) {
  10009. case VSNORMAL:
  10010. putc('}', fp);
  10011. break;
  10012. case VSMINUS:
  10013. putc('-', fp);
  10014. break;
  10015. case VSPLUS:
  10016. putc('+', fp);
  10017. break;
  10018. case VSQUESTION:
  10019. putc('?', fp);
  10020. break;
  10021. case VSASSIGN:
  10022. putc('=', fp);
  10023. break;
  10024. case VSTRIMLEFT:
  10025. putc('#', fp);
  10026. break;
  10027. case VSTRIMLEFTMAX:
  10028. putc('#', fp);
  10029. putc('#', fp);
  10030. break;
  10031. case VSTRIMRIGHT:
  10032. putc('%', fp);
  10033. break;
  10034. case VSTRIMRIGHTMAX:
  10035. putc('%', fp);
  10036. putc('%', fp);
  10037. break;
  10038. case VSLENGTH:
  10039. break;
  10040. default:
  10041. out1fmt("<subtype %d>", subtype);
  10042. }
  10043. break;
  10044. case CTLENDVAR:
  10045. putc('}', fp);
  10046. break;
  10047. case CTLBACKQ:
  10048. case CTLBACKQ|CTLQUOTE:
  10049. putc('$', fp);
  10050. putc('(', fp);
  10051. shtree(bqlist->n, -1, NULL, fp);
  10052. putc(')', fp);
  10053. break;
  10054. default:
  10055. putc(*p, fp);
  10056. break;
  10057. }
  10058. }
  10059. }
  10060. static void
  10061. indent(int amount, char *pfx, FILE *fp)
  10062. {
  10063. int i;
  10064. for (i = 0 ; i < amount ; i++) {
  10065. if (pfx && i == amount - 1)
  10066. fputs(pfx, fp);
  10067. putc('\t', fp);
  10068. }
  10069. }
  10070. /*
  10071. * Debugging stuff.
  10072. */
  10073. FILE *tracefile;
  10074. void
  10075. trputc(int c)
  10076. {
  10077. if (debug != 1)
  10078. return;
  10079. putc(c, tracefile);
  10080. }
  10081. void
  10082. trace(const char *fmt, ...)
  10083. {
  10084. va_list va;
  10085. if (debug != 1)
  10086. return;
  10087. va_start(va, fmt);
  10088. (void) vfprintf(tracefile, fmt, va);
  10089. va_end(va);
  10090. }
  10091. void
  10092. tracev(const char *fmt, va_list va)
  10093. {
  10094. if (debug != 1)
  10095. return;
  10096. (void) vfprintf(tracefile, fmt, va);
  10097. }
  10098. void
  10099. trputs(const char *s)
  10100. {
  10101. if (debug != 1)
  10102. return;
  10103. fputs(s, tracefile);
  10104. }
  10105. static void
  10106. trstring(char *s)
  10107. {
  10108. char *p;
  10109. char c;
  10110. if (debug != 1)
  10111. return;
  10112. putc('"', tracefile);
  10113. for (p = s ; *p ; p++) {
  10114. switch (*p) {
  10115. case '\n': c = 'n'; goto backslash;
  10116. case '\t': c = 't'; goto backslash;
  10117. case '\r': c = 'r'; goto backslash;
  10118. case '"': c = '"'; goto backslash;
  10119. case '\\': c = '\\'; goto backslash;
  10120. case CTLESC: c = 'e'; goto backslash;
  10121. case CTLVAR: c = 'v'; goto backslash;
  10122. case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
  10123. case CTLBACKQ: c = 'q'; goto backslash;
  10124. case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
  10125. backslash: putc('\\', tracefile);
  10126. putc(c, tracefile);
  10127. break;
  10128. default:
  10129. if (*p >= ' ' && *p <= '~')
  10130. putc(*p, tracefile);
  10131. else {
  10132. putc('\\', tracefile);
  10133. putc(*p >> 6 & 03, tracefile);
  10134. putc(*p >> 3 & 07, tracefile);
  10135. putc(*p & 07, tracefile);
  10136. }
  10137. break;
  10138. }
  10139. }
  10140. putc('"', tracefile);
  10141. }
  10142. void
  10143. trargs(char **ap)
  10144. {
  10145. if (debug != 1)
  10146. return;
  10147. while (*ap) {
  10148. trstring(*ap++);
  10149. if (*ap)
  10150. putc(' ', tracefile);
  10151. else
  10152. putc('\n', tracefile);
  10153. }
  10154. }
  10155. void
  10156. opentrace(void)
  10157. {
  10158. char s[100];
  10159. #ifdef O_APPEND
  10160. int flags;
  10161. #endif
  10162. if (debug != 1) {
  10163. if (tracefile)
  10164. fflush(tracefile);
  10165. /* leave open because libedit might be using it */
  10166. return;
  10167. }
  10168. scopy("./trace", s);
  10169. if (tracefile) {
  10170. if (!freopen(s, "a", tracefile)) {
  10171. fprintf(stderr, "Can't re-open %s\n", s);
  10172. debug = 0;
  10173. return;
  10174. }
  10175. } else {
  10176. if ((tracefile = fopen(s, "a")) == NULL) {
  10177. fprintf(stderr, "Can't open %s\n", s);
  10178. debug = 0;
  10179. return;
  10180. }
  10181. }
  10182. #ifdef O_APPEND
  10183. if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
  10184. fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
  10185. #endif
  10186. setlinebuf(tracefile);
  10187. fputs("\nTracing started.\n", tracefile);
  10188. }
  10189. #endif /* DEBUG */
  10190. /* $NetBSD: trap.c,v 1.28 2002/11/24 22:35:43 christos Exp $ */
  10191. /*
  10192. * Sigmode records the current value of the signal handlers for the various
  10193. * modes. A value of zero means that the current handler is not known.
  10194. * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
  10195. */
  10196. #define S_DFL 1 /* default signal handling (SIG_DFL) */
  10197. #define S_CATCH 2 /* signal is caught */
  10198. #define S_IGN 3 /* signal is ignored (SIG_IGN) */
  10199. #define S_HARD_IGN 4 /* signal is ignored permenantly */
  10200. #define S_RESET 5 /* temporary - to reset a hard ignored sig */
  10201. /*
  10202. * The trap builtin.
  10203. */
  10204. int
  10205. trapcmd(int argc, char **argv)
  10206. {
  10207. char *action;
  10208. char **ap;
  10209. int signo;
  10210. nextopt(nullstr);
  10211. ap = argptr;
  10212. if (!*ap) {
  10213. for (signo = 0 ; signo < NSIG ; signo++) {
  10214. if (trap[signo] != NULL) {
  10215. const char *sn;
  10216. sn = u_signal_names(0, &signo, 0);
  10217. if (sn == NULL)
  10218. sn = "???";
  10219. out1fmt("trap -- %s %s\n",
  10220. single_quote(trap[signo]), sn);
  10221. }
  10222. }
  10223. return 0;
  10224. }
  10225. if (!ap[1])
  10226. action = NULL;
  10227. else
  10228. action = *ap++;
  10229. while (*ap) {
  10230. if ((signo = decode_signal(*ap, 0)) < 0)
  10231. error("%s: bad trap", *ap);
  10232. INTOFF;
  10233. if (action) {
  10234. if (action[0] == '-' && action[1] == '\0')
  10235. action = NULL;
  10236. else
  10237. action = savestr(action);
  10238. }
  10239. if (trap[signo])
  10240. ckfree(trap[signo]);
  10241. trap[signo] = action;
  10242. if (signo != 0)
  10243. setsignal(signo);
  10244. INTON;
  10245. ap++;
  10246. }
  10247. return 0;
  10248. }
  10249. /*
  10250. * Clear traps on a fork.
  10251. */
  10252. void
  10253. clear_traps(void)
  10254. {
  10255. char **tp;
  10256. for (tp = trap ; tp < &trap[NSIG] ; tp++) {
  10257. if (*tp && **tp) { /* trap not NULL or SIG_IGN */
  10258. INTOFF;
  10259. ckfree(*tp);
  10260. *tp = NULL;
  10261. if (tp != &trap[0])
  10262. setsignal(tp - trap);
  10263. INTON;
  10264. }
  10265. }
  10266. }
  10267. /*
  10268. * Set the signal handler for the specified signal. The routine figures
  10269. * out what it should be set to.
  10270. */
  10271. void
  10272. setsignal(int signo)
  10273. {
  10274. int action;
  10275. char *t, tsig;
  10276. struct sigaction act;
  10277. if ((t = trap[signo]) == NULL)
  10278. action = S_DFL;
  10279. else if (*t != '\0')
  10280. action = S_CATCH;
  10281. else
  10282. action = S_IGN;
  10283. if (rootshell && action == S_DFL) {
  10284. switch (signo) {
  10285. case SIGINT:
  10286. if (iflag || minusc || sflag == 0)
  10287. action = S_CATCH;
  10288. break;
  10289. case SIGQUIT:
  10290. #ifdef DEBUG
  10291. if (debug)
  10292. break;
  10293. #endif
  10294. /* FALLTHROUGH */
  10295. case SIGTERM:
  10296. if (iflag)
  10297. action = S_IGN;
  10298. break;
  10299. #if JOBS
  10300. case SIGTSTP:
  10301. case SIGTTOU:
  10302. if (mflag)
  10303. action = S_IGN;
  10304. break;
  10305. #endif
  10306. }
  10307. }
  10308. t = &sigmode[signo - 1];
  10309. tsig = *t;
  10310. if (tsig == 0) {
  10311. /*
  10312. * current setting unknown
  10313. */
  10314. if (sigaction(signo, 0, &act) == -1) {
  10315. /*
  10316. * Pretend it worked; maybe we should give a warning
  10317. * here, but other shells don't. We don't alter
  10318. * sigmode, so that we retry every time.
  10319. */
  10320. return;
  10321. }
  10322. if (act.sa_handler == SIG_IGN) {
  10323. if (mflag && (signo == SIGTSTP ||
  10324. signo == SIGTTIN || signo == SIGTTOU)) {
  10325. tsig = S_IGN; /* don't hard ignore these */
  10326. } else
  10327. tsig = S_HARD_IGN;
  10328. } else {
  10329. tsig = S_RESET; /* force to be set */
  10330. }
  10331. }
  10332. if (tsig == S_HARD_IGN || tsig == action)
  10333. return;
  10334. switch (action) {
  10335. case S_CATCH:
  10336. act.sa_handler = onsig;
  10337. break;
  10338. case S_IGN:
  10339. act.sa_handler = SIG_IGN;
  10340. break;
  10341. default:
  10342. act.sa_handler = SIG_DFL;
  10343. }
  10344. *t = action;
  10345. act.sa_flags = 0;
  10346. sigfillset(&act.sa_mask);
  10347. sigaction(signo, &act, 0);
  10348. }
  10349. /*
  10350. * Ignore a signal.
  10351. */
  10352. void
  10353. ignoresig(int signo)
  10354. {
  10355. if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
  10356. signal(signo, SIG_IGN);
  10357. }
  10358. sigmode[signo - 1] = S_HARD_IGN;
  10359. }
  10360. /*
  10361. * Signal handler.
  10362. */
  10363. void
  10364. onsig(int signo)
  10365. {
  10366. gotsig[signo - 1] = 1;
  10367. pendingsigs = signo;
  10368. if (exsig || (signo == SIGINT && !trap[SIGINT])) {
  10369. if (!suppressint)
  10370. onint();
  10371. intpending = 1;
  10372. }
  10373. }
  10374. /*
  10375. * Called to execute a trap. Perhaps we should avoid entering new trap
  10376. * handlers while we are executing a trap handler.
  10377. */
  10378. void
  10379. dotrap(void)
  10380. {
  10381. char *p;
  10382. char *q;
  10383. int savestatus;
  10384. savestatus = exitstatus;
  10385. q = gotsig;
  10386. while (pendingsigs = 0, xbarrier(), (p = memchr(q, 1, NSIG - 1))) {
  10387. *p = 0;
  10388. p = trap[p - q + 1];
  10389. if (!p)
  10390. continue;
  10391. evalstring(p);
  10392. exitstatus = savestatus;
  10393. }
  10394. }
  10395. /*
  10396. * Controls whether the shell is interactive or not.
  10397. */
  10398. void
  10399. setinteractive(int on)
  10400. {
  10401. static int is_interactive;
  10402. if (++on == is_interactive)
  10403. return;
  10404. is_interactive = on;
  10405. setsignal(SIGINT);
  10406. setsignal(SIGQUIT);
  10407. setsignal(SIGTERM);
  10408. #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
  10409. if(is_interactive > 1) {
  10410. /* Looks like they want an interactive shell */
  10411. static int do_banner;
  10412. if(!do_banner) {
  10413. out1fmt(
  10414. "\n\n" BB_BANNER " Built-in shell (ash)\n"
  10415. "Enter 'help' for a list of built-in commands.\n\n");
  10416. do_banner++;
  10417. }
  10418. }
  10419. #endif
  10420. }
  10421. #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
  10422. /*** List the available builtins ***/
  10423. static int helpcmd(int argc, char **argv)
  10424. {
  10425. int col, i;
  10426. out1fmt("\nBuilt-in commands:\n-------------------\n");
  10427. for (col = 0, i = 0; i < NUMBUILTINS; i++) {
  10428. col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
  10429. builtincmd[i].name + 1);
  10430. if (col > 60) {
  10431. out1fmt("\n");
  10432. col = 0;
  10433. }
  10434. }
  10435. #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
  10436. {
  10437. extern const struct BB_applet applets[];
  10438. extern const size_t NUM_APPLETS;
  10439. for (i = 0; i < NUM_APPLETS; i++) {
  10440. col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
  10441. if (col > 60) {
  10442. out1fmt("\n");
  10443. col = 0;
  10444. }
  10445. }
  10446. }
  10447. #endif
  10448. out1fmt("\n\n");
  10449. return EXIT_SUCCESS;
  10450. }
  10451. #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
  10452. /*
  10453. * Called to exit the shell.
  10454. */
  10455. void
  10456. exitshell(void)
  10457. {
  10458. struct jmploc loc;
  10459. char *p;
  10460. int status;
  10461. int jmp;
  10462. jmp = setjmp(loc.loc);
  10463. status = exitstatus;
  10464. TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
  10465. if (jmp)
  10466. goto out;
  10467. handler = &loc;
  10468. if ((p = trap[0]) != NULL && *p != '\0') {
  10469. trap[0] = NULL;
  10470. evalstring(p);
  10471. }
  10472. flushall();
  10473. setjobctl(0);
  10474. #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
  10475. if (iflag && rootshell) {
  10476. const char *hp = lookupvar("HISTFILE");
  10477. if(hp != NULL )
  10478. save_history ( hp );
  10479. }
  10480. #endif
  10481. out:
  10482. _exit(status);
  10483. /* NOTREACHED */
  10484. }
  10485. static int decode_signal(const char *string, int minsig)
  10486. {
  10487. int signo;
  10488. const char *name = u_signal_names(string, &signo, minsig);
  10489. return name ? signo : -1;
  10490. }
  10491. /* $NetBSD: var.c,v 1.32 2003/01/22 20:36:04 dsl Exp $ */
  10492. static struct var *vartab[VTABSIZE];
  10493. static int vpcmp(const void *, const void *);
  10494. static struct var **findvar(struct var **, const char *);
  10495. /*
  10496. * Initialize the variable symbol tables and import the environment
  10497. */
  10498. #ifdef CONFIG_ASH_GETOPTS
  10499. /*
  10500. * Safe version of setvar, returns 1 on success 0 on failure.
  10501. */
  10502. int
  10503. setvarsafe(const char *name, const char *val, int flags)
  10504. {
  10505. int err;
  10506. volatile int saveint;
  10507. struct jmploc *volatile savehandler = handler;
  10508. struct jmploc jmploc;
  10509. SAVEINT(saveint);
  10510. if (setjmp(jmploc.loc))
  10511. err = 1;
  10512. else {
  10513. handler = &jmploc;
  10514. setvar(name, val, flags);
  10515. err = 0;
  10516. }
  10517. handler = savehandler;
  10518. RESTOREINT(saveint);
  10519. return err;
  10520. }
  10521. #endif
  10522. /*
  10523. * Set the value of a variable. The flags argument is ored with the
  10524. * flags of the variable. If val is NULL, the variable is unset.
  10525. */
  10526. static void
  10527. setvar(const char *name, const char *val, int flags)
  10528. {
  10529. char *p, *q;
  10530. size_t namelen;
  10531. char *nameeq;
  10532. size_t vallen;
  10533. q = endofname(name);
  10534. p = strchrnul(q, '=');
  10535. namelen = p - name;
  10536. if (!namelen || p != q)
  10537. error("%.*s: bad variable name", namelen, name);
  10538. vallen = 0;
  10539. if (val == NULL) {
  10540. flags |= VUNSET;
  10541. } else {
  10542. vallen = strlen(val);
  10543. }
  10544. INTOFF;
  10545. p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
  10546. *p++ = '\0';
  10547. if (vallen) {
  10548. p[-1] = '=';
  10549. p = mempcpy(p, val, vallen);
  10550. }
  10551. *p = '\0';
  10552. setvareq(nameeq, flags | VNOSAVE);
  10553. INTON;
  10554. }
  10555. /*
  10556. * Same as setvar except that the variable and value are passed in
  10557. * the first argument as name=value. Since the first argument will
  10558. * be actually stored in the table, it should not be a string that
  10559. * will go away.
  10560. * Called with interrupts off.
  10561. */
  10562. void
  10563. setvareq(char *s, int flags)
  10564. {
  10565. struct var *vp, **vpp;
  10566. vpp = hashvar(s);
  10567. flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
  10568. vp = *findvar(vpp, s);
  10569. if (vp) {
  10570. if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
  10571. const char *n;
  10572. if (flags & VNOSAVE)
  10573. free(s);
  10574. n = vp->text;
  10575. error("%.*s: is read only", strchrnul(n, '=') - n, n);
  10576. }
  10577. if (flags & VNOSET)
  10578. return;
  10579. if (vp->func && (flags & VNOFUNC) == 0)
  10580. (*vp->func)(strchrnul(s, '=') + 1);
  10581. if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
  10582. ckfree(vp->text);
  10583. flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
  10584. } else {
  10585. if (flags & VNOSET)
  10586. return;
  10587. /* not found */
  10588. vp = ckmalloc(sizeof (*vp));
  10589. vp->next = *vpp;
  10590. vp->func = NULL;
  10591. *vpp = vp;
  10592. }
  10593. if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
  10594. s = savestr(s);
  10595. vp->text = s;
  10596. vp->flags = flags;
  10597. }
  10598. /*
  10599. * Process a linked list of variable assignments.
  10600. */
  10601. static void
  10602. listsetvar(struct strlist *list_set_var, int flags)
  10603. {
  10604. struct strlist *lp = list_set_var;
  10605. if (!lp)
  10606. return;
  10607. INTOFF;
  10608. do {
  10609. setvareq(lp->text, flags);
  10610. } while ((lp = lp->next));
  10611. INTON;
  10612. }
  10613. /*
  10614. * Find the value of a variable. Returns NULL if not set.
  10615. */
  10616. static char *
  10617. lookupvar(const char *name)
  10618. {
  10619. struct var *v;
  10620. if ((v = *findvar(hashvar(name), name))) {
  10621. #ifdef DYNAMIC_VAR
  10622. /*
  10623. * Dynamic variables are implemented roughly the same way they are
  10624. * in bash. Namely, they're "special" so long as they aren't unset.
  10625. * As soon as they're unset, they're no longer dynamic, and dynamic
  10626. * lookup will no longer happen at that point. -- PFM.
  10627. */
  10628. if((v->flags & VDYNAMIC))
  10629. (*v->func)(NULL);
  10630. #endif
  10631. if(!(v->flags & VUNSET))
  10632. return strchrnul(v->text, '=') + 1;
  10633. }
  10634. return NULL;
  10635. }
  10636. /*
  10637. * Search the environment of a builtin command.
  10638. */
  10639. static char *
  10640. bltinlookup(const char *name)
  10641. {
  10642. struct strlist *sp;
  10643. for (sp = cmdenviron ; sp ; sp = sp->next) {
  10644. if (varequal(sp->text, name))
  10645. return strchrnul(sp->text, '=') + 1;
  10646. }
  10647. return lookupvar(name);
  10648. }
  10649. /*
  10650. * Generate a list of variables satisfying the given conditions.
  10651. */
  10652. static char **
  10653. listvars(int on, int off, char ***end)
  10654. {
  10655. struct var **vpp;
  10656. struct var *vp;
  10657. char **ep;
  10658. int mask;
  10659. STARTSTACKSTR(ep);
  10660. vpp = vartab;
  10661. mask = on | off;
  10662. do {
  10663. for (vp = *vpp ; vp ; vp = vp->next)
  10664. if ((vp->flags & mask) == on) {
  10665. if (ep == stackstrend())
  10666. ep = growstackstr();
  10667. *ep++ = (char *) vp->text;
  10668. }
  10669. } while (++vpp < vartab + VTABSIZE);
  10670. if (ep == stackstrend())
  10671. ep = growstackstr();
  10672. if (end)
  10673. *end = ep;
  10674. *ep++ = NULL;
  10675. return grabstackstr(ep);
  10676. }
  10677. /*
  10678. * POSIX requires that 'set' (but not export or readonly) output the
  10679. * variables in lexicographic order - by the locale's collating order (sigh).
  10680. * Maybe we could keep them in an ordered balanced binary tree
  10681. * instead of hashed lists.
  10682. * For now just roll 'em through qsort for printing...
  10683. */
  10684. static int
  10685. showvars(const char *sep_prefix, int on, int off)
  10686. {
  10687. const char *sep;
  10688. char **ep, **epend;
  10689. ep = listvars(on, off, &epend);
  10690. qsort(ep, epend - ep, sizeof(char *), vpcmp);
  10691. sep = *sep_prefix ? spcstr : sep_prefix;
  10692. for (; ep < epend; ep++) {
  10693. const char *p;
  10694. const char *q;
  10695. p = strchrnul(*ep, '=');
  10696. q = nullstr;
  10697. if (*p)
  10698. q = single_quote(++p);
  10699. out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
  10700. }
  10701. return 0;
  10702. }
  10703. /*
  10704. * The export and readonly commands.
  10705. */
  10706. static int
  10707. exportcmd(int argc, char **argv)
  10708. {
  10709. struct var *vp;
  10710. char *name;
  10711. const char *p;
  10712. char **aptr;
  10713. int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
  10714. int notp;
  10715. notp = nextopt("p") - 'p';
  10716. if (notp && ((name = *(aptr = argptr)))) {
  10717. do {
  10718. if ((p = strchr(name, '=')) != NULL) {
  10719. p++;
  10720. } else {
  10721. if ((vp = *findvar(hashvar(name), name))) {
  10722. vp->flags |= flag;
  10723. continue;
  10724. }
  10725. }
  10726. setvar(name, p, flag);
  10727. } while ((name = *++aptr) != NULL);
  10728. } else {
  10729. showvars(argv[0], flag, 0);
  10730. }
  10731. return 0;
  10732. }
  10733. /*
  10734. * Make a variable a local variable. When a variable is made local, it's
  10735. * value and flags are saved in a localvar structure. The saved values
  10736. * will be restored when the shell function returns. We handle the name
  10737. * "-" as a special case.
  10738. */
  10739. static inline void
  10740. mklocal(char *name)
  10741. {
  10742. struct localvar *lvp;
  10743. struct var **vpp;
  10744. struct var *vp;
  10745. INTOFF;
  10746. lvp = ckmalloc(sizeof (struct localvar));
  10747. if (name[0] == '-' && name[1] == '\0') {
  10748. char *p;
  10749. p = ckmalloc(sizeof(optlist));
  10750. lvp->text = memcpy(p, optlist, sizeof(optlist));
  10751. vp = NULL;
  10752. } else {
  10753. char *eq;
  10754. vpp = hashvar(name);
  10755. vp = *findvar(vpp, name);
  10756. eq = strchr(name, '=');
  10757. if (vp == NULL) {
  10758. if (eq)
  10759. setvareq(name, VSTRFIXED);
  10760. else
  10761. setvar(name, NULL, VSTRFIXED);
  10762. vp = *vpp; /* the new variable */
  10763. lvp->flags = VUNSET;
  10764. } else {
  10765. lvp->text = vp->text;
  10766. lvp->flags = vp->flags;
  10767. vp->flags |= VSTRFIXED|VTEXTFIXED;
  10768. if (eq)
  10769. setvareq(name, 0);
  10770. }
  10771. }
  10772. lvp->vp = vp;
  10773. lvp->next = localvars;
  10774. localvars = lvp;
  10775. INTON;
  10776. }
  10777. /*
  10778. * The "local" command.
  10779. */
  10780. static int
  10781. localcmd(int argc, char **argv)
  10782. {
  10783. char *name;
  10784. argv = argptr;
  10785. while ((name = *argv++) != NULL) {
  10786. mklocal(name);
  10787. }
  10788. return 0;
  10789. }
  10790. /*
  10791. * Called after a function returns.
  10792. * Interrupts must be off.
  10793. */
  10794. static void
  10795. poplocalvars(void)
  10796. {
  10797. struct localvar *lvp;
  10798. struct var *vp;
  10799. while ((lvp = localvars) != NULL) {
  10800. localvars = lvp->next;
  10801. vp = lvp->vp;
  10802. TRACE(("poplocalvar %s", vp ? vp->text : "-"));
  10803. if (vp == NULL) { /* $- saved */
  10804. memcpy(optlist, lvp->text, sizeof(optlist));
  10805. ckfree(lvp->text);
  10806. optschanged();
  10807. } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
  10808. unsetvar(vp->text);
  10809. } else {
  10810. if (vp->func)
  10811. (*vp->func)(strchrnul(lvp->text, '=') + 1);
  10812. if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
  10813. ckfree(vp->text);
  10814. vp->flags = lvp->flags;
  10815. vp->text = lvp->text;
  10816. }
  10817. ckfree(lvp);
  10818. }
  10819. }
  10820. /*
  10821. * The unset builtin command. We unset the function before we unset the
  10822. * variable to allow a function to be unset when there is a readonly variable
  10823. * with the same name.
  10824. */
  10825. int
  10826. unsetcmd(int argc, char **argv)
  10827. {
  10828. char **ap;
  10829. int i;
  10830. int flag = 0;
  10831. int ret = 0;
  10832. while ((i = nextopt("vf")) != '\0') {
  10833. flag = i;
  10834. }
  10835. for (ap = argptr; *ap ; ap++) {
  10836. if (flag != 'f') {
  10837. i = unsetvar(*ap);
  10838. ret |= i;
  10839. if (!(i & 2))
  10840. continue;
  10841. }
  10842. if (flag != 'v')
  10843. unsetfunc(*ap);
  10844. }
  10845. return ret & 1;
  10846. }
  10847. /*
  10848. * Unset the specified variable.
  10849. */
  10850. int
  10851. unsetvar(const char *s)
  10852. {
  10853. struct var **vpp;
  10854. struct var *vp;
  10855. int retval;
  10856. vpp = findvar(hashvar(s), s);
  10857. vp = *vpp;
  10858. retval = 2;
  10859. if (vp) {
  10860. int flags = vp->flags;
  10861. retval = 1;
  10862. if (flags & VREADONLY)
  10863. goto out;
  10864. #ifdef DYNAMIC_VAR
  10865. vp->flags &= ~VDYNAMIC;
  10866. #endif
  10867. if (flags & VUNSET)
  10868. goto ok;
  10869. if ((flags & VSTRFIXED) == 0) {
  10870. INTOFF;
  10871. if ((flags & (VTEXTFIXED|VSTACK)) == 0)
  10872. ckfree(vp->text);
  10873. *vpp = vp->next;
  10874. ckfree(vp);
  10875. INTON;
  10876. } else {
  10877. setvar(s, 0, 0);
  10878. vp->flags &= ~VEXPORT;
  10879. }
  10880. ok:
  10881. retval = 0;
  10882. }
  10883. out:
  10884. return retval;
  10885. }
  10886. /*
  10887. * Find the appropriate entry in the hash table from the name.
  10888. */
  10889. static struct var **
  10890. hashvar(const char *p)
  10891. {
  10892. unsigned int hashval;
  10893. hashval = ((unsigned char) *p) << 4;
  10894. while (*p && *p != '=')
  10895. hashval += (unsigned char) *p++;
  10896. return &vartab[hashval % VTABSIZE];
  10897. }
  10898. /*
  10899. * Compares two strings up to the first = or '\0'. The first
  10900. * string must be terminated by '='; the second may be terminated by
  10901. * either '=' or '\0'.
  10902. */
  10903. int
  10904. varcmp(const char *p, const char *q)
  10905. {
  10906. int c, d;
  10907. while ((c = *p) == (d = *q)) {
  10908. if (!c || c == '=')
  10909. goto out;
  10910. p++;
  10911. q++;
  10912. }
  10913. if (c == '=')
  10914. c = 0;
  10915. if (d == '=')
  10916. d = 0;
  10917. out:
  10918. return c - d;
  10919. }
  10920. static int
  10921. vpcmp(const void *a, const void *b)
  10922. {
  10923. return varcmp(*(const char **)a, *(const char **)b);
  10924. }
  10925. static struct var **
  10926. findvar(struct var **vpp, const char *name)
  10927. {
  10928. for (; *vpp; vpp = &(*vpp)->next) {
  10929. if (varequal((*vpp)->text, name)) {
  10930. break;
  10931. }
  10932. }
  10933. return vpp;
  10934. }
  10935. /* $NetBSD: setmode.c,v 1.29 2003/01/15 23:58:03 kleink Exp $ */
  10936. #include <sys/times.h>
  10937. static const unsigned char timescmd_str[] = {
  10938. ' ', offsetof(struct tms, tms_utime),
  10939. '\n', offsetof(struct tms, tms_stime),
  10940. ' ', offsetof(struct tms, tms_cutime),
  10941. '\n', offsetof(struct tms, tms_cstime),
  10942. 0
  10943. };
  10944. static int timescmd(int ac, char **av)
  10945. {
  10946. long int clk_tck, s, t;
  10947. const unsigned char *p;
  10948. struct tms buf;
  10949. clk_tck = sysconf(_SC_CLK_TCK);
  10950. times(&buf);
  10951. p = timescmd_str;
  10952. do {
  10953. t = *(clock_t *)(((char *) &buf) + p[1]);
  10954. s = t / clk_tck;
  10955. out1fmt("%ldm%ld.%.3lds%c",
  10956. s/60, s%60,
  10957. ((t - s * clk_tck) * 1000) / clk_tck,
  10958. p[0]);
  10959. } while (*(p += 2));
  10960. return 0;
  10961. }
  10962. #ifdef CONFIG_ASH_MATH_SUPPORT
  10963. static arith_t
  10964. dash_arith(const char *s)
  10965. {
  10966. arith_t result;
  10967. int errcode = 0;
  10968. INTOFF;
  10969. result = arith(s, &errcode);
  10970. if (errcode < 0) {
  10971. if (errcode == -3)
  10972. error("exponent less than 0");
  10973. else if (errcode == -2)
  10974. error("divide by zero");
  10975. else if (errcode == -5)
  10976. error("expression recursion loop detected");
  10977. else
  10978. synerror(s);
  10979. }
  10980. INTON;
  10981. return (result);
  10982. }
  10983. /*
  10984. * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
  10985. * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
  10986. *
  10987. * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
  10988. */
  10989. static int
  10990. letcmd(int argc, char **argv)
  10991. {
  10992. char **ap;
  10993. arith_t i;
  10994. ap = argv + 1;
  10995. if(!*ap)
  10996. error("expression expected");
  10997. for (ap = argv + 1; *ap; ap++) {
  10998. i = dash_arith(*ap);
  10999. }
  11000. return (!i);
  11001. }
  11002. #endif /* CONFIG_ASH_MATH_SUPPORT */
  11003. /* $NetBSD: miscbltin.c,v 1.31 2002/11/24 22:35:41 christos Exp $ */
  11004. /*
  11005. * Miscellaneous builtins.
  11006. */
  11007. #undef rflag
  11008. #ifdef __GLIBC__
  11009. #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
  11010. typedef enum __rlimit_resource rlim_t;
  11011. #endif
  11012. #endif
  11013. /*
  11014. * The read builtin. The -e option causes backslashes to escape the
  11015. * following character.
  11016. *
  11017. * This uses unbuffered input, which may be avoidable in some cases.
  11018. */
  11019. static int
  11020. readcmd(int argc, char **argv)
  11021. {
  11022. char **ap;
  11023. int backslash;
  11024. char c;
  11025. int rflag;
  11026. char *prompt;
  11027. const char *ifs;
  11028. char *p;
  11029. #if defined(CONFIG_ASH_TIMEOUT)
  11030. fd_set set;
  11031. int timeout;
  11032. struct timeval timeout_struct;
  11033. struct termios tty, old_tty;
  11034. #endif
  11035. int startword;
  11036. int status;
  11037. int i;
  11038. rflag = 0;
  11039. prompt = NULL;
  11040. #if defined(CONFIG_ASH_TIMEOUT)
  11041. timeout = 0;
  11042. while ((i = nextopt("p:rt:")) != '\0')
  11043. #else
  11044. while ((i = nextopt("p:r")) != '\0')
  11045. #endif
  11046. {
  11047. if (i == 'p')
  11048. prompt = optionarg;
  11049. else if (i == 'r')
  11050. rflag = 1;
  11051. #if defined(CONFIG_ASH_TIMEOUT)
  11052. else
  11053. timeout = atoi(optionarg);
  11054. #endif
  11055. }
  11056. if (prompt && isatty(0)) {
  11057. out2str(prompt);
  11058. }
  11059. if (*(ap = argptr) == NULL)
  11060. error("arg count");
  11061. if ((ifs = bltinlookup("IFS")) == NULL)
  11062. ifs = defifs;
  11063. #if defined(CONFIG_ASH_TIMEOUT)
  11064. c = 0;
  11065. #endif
  11066. status = 0;
  11067. startword = 1;
  11068. backslash = 0;
  11069. STARTSTACKSTR(p);
  11070. #if defined(CONFIG_ASH_TIMEOUT)
  11071. if (timeout > 0) {
  11072. tcgetattr(0, &tty);
  11073. old_tty = tty;
  11074. /* cfmakeraw(...) disables too much; we just do this instead. */
  11075. tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
  11076. tcsetattr(0, TCSANOW, &tty);
  11077. FD_ZERO (&set);
  11078. FD_SET (0, &set);
  11079. timeout_struct.tv_sec = timeout;
  11080. timeout_struct.tv_usec = 0;
  11081. if ((i = select (FD_SETSIZE, &set, NULL, NULL, &timeout_struct)) == 1)
  11082. {
  11083. read(0, &c, 1);
  11084. if(c == '\n' || c == 4) /* Handle newlines and EOF */
  11085. i = 0; /* Don't read further... */
  11086. else
  11087. STPUTC(c, p); /* Keep reading... */
  11088. }
  11089. tcsetattr(0, TCSANOW, &old_tty);
  11090. /* Echo the character so the user knows it was read...
  11091. Yes, this can be done by setting the ECHO flag, but that
  11092. echoes ^D and other control characters at this state */
  11093. if(c != 0)
  11094. write(1, &c, 1);
  11095. } else
  11096. i = 1;
  11097. for (;i == 1;)
  11098. #else
  11099. for (;;)
  11100. #endif
  11101. {
  11102. if (read(0, &c, 1) != 1) {
  11103. status = 1;
  11104. break;
  11105. }
  11106. if (c == '\0')
  11107. continue;
  11108. if (backslash) {
  11109. backslash = 0;
  11110. if (c != '\n')
  11111. goto put;
  11112. continue;
  11113. }
  11114. if (!rflag && c == '\\') {
  11115. backslash++;
  11116. continue;
  11117. }
  11118. if (c == '\n')
  11119. break;
  11120. if (startword && *ifs == ' ' && strchr(ifs, c)) {
  11121. continue;
  11122. }
  11123. startword = 0;
  11124. if (ap[1] != NULL && strchr(ifs, c) != NULL) {
  11125. STACKSTRNUL(p);
  11126. setvar(*ap, stackblock(), 0);
  11127. ap++;
  11128. startword = 1;
  11129. STARTSTACKSTR(p);
  11130. } else {
  11131. put:
  11132. STPUTC(c, p);
  11133. }
  11134. }
  11135. STACKSTRNUL(p);
  11136. /* Remove trailing blanks */
  11137. while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
  11138. *p = '\0';
  11139. setvar(*ap, stackblock(), 0);
  11140. while (*++ap != NULL)
  11141. setvar(*ap, nullstr, 0);
  11142. return status;
  11143. }
  11144. static int umaskcmd(int argc, char **argv)
  11145. {
  11146. static const char permuser[3] = "ugo";
  11147. static const char permmode[3] = "rwx";
  11148. static const short int permmask[] = {
  11149. S_IRUSR, S_IWUSR, S_IXUSR,
  11150. S_IRGRP, S_IWGRP, S_IXGRP,
  11151. S_IROTH, S_IWOTH, S_IXOTH
  11152. };
  11153. char *ap;
  11154. mode_t mask;
  11155. int i;
  11156. int symbolic_mode = 0;
  11157. while (nextopt("S") != '\0') {
  11158. symbolic_mode = 1;
  11159. }
  11160. INTOFF;
  11161. mask = umask(0);
  11162. umask(mask);
  11163. INTON;
  11164. if ((ap = *argptr) == NULL) {
  11165. if (symbolic_mode) {
  11166. char buf[18];
  11167. char *p = buf;
  11168. for (i = 0; i < 3; i++) {
  11169. int j;
  11170. *p++ = permuser[i];
  11171. *p++ = '=';
  11172. for (j = 0; j < 3; j++) {
  11173. if ((mask & permmask[3 * i + j]) == 0) {
  11174. *p++ = permmode[j];
  11175. }
  11176. }
  11177. *p++ = ',';
  11178. }
  11179. *--p = 0;
  11180. puts(buf);
  11181. } else {
  11182. out1fmt("%.4o\n", mask);
  11183. }
  11184. } else {
  11185. if (is_digit((unsigned char) *ap)) {
  11186. mask = 0;
  11187. do {
  11188. if (*ap >= '8' || *ap < '0')
  11189. error(illnum, argv[1]);
  11190. mask = (mask << 3) + (*ap - '0');
  11191. } while (*++ap != '\0');
  11192. umask(mask);
  11193. } else {
  11194. mask = ~mask & 0777;
  11195. if (!bb_parse_mode(ap, &mask)) {
  11196. error("Illegal mode: %s", ap);
  11197. }
  11198. umask(~mask & 0777);
  11199. }
  11200. }
  11201. return 0;
  11202. }
  11203. /*
  11204. * ulimit builtin
  11205. *
  11206. * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
  11207. * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
  11208. * ash by J.T. Conklin.
  11209. *
  11210. * Public domain.
  11211. */
  11212. struct limits {
  11213. const char *name;
  11214. int cmd;
  11215. int factor; /* multiply by to get rlim_{cur,max} values */
  11216. char option;
  11217. };
  11218. static const struct limits limits[] = {
  11219. #ifdef RLIMIT_CPU
  11220. { "time(seconds)", RLIMIT_CPU, 1, 't' },
  11221. #endif
  11222. #ifdef RLIMIT_FSIZE
  11223. { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
  11224. #endif
  11225. #ifdef RLIMIT_DATA
  11226. { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
  11227. #endif
  11228. #ifdef RLIMIT_STACK
  11229. { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
  11230. #endif
  11231. #ifdef RLIMIT_CORE
  11232. { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
  11233. #endif
  11234. #ifdef RLIMIT_RSS
  11235. { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
  11236. #endif
  11237. #ifdef RLIMIT_MEMLOCK
  11238. { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
  11239. #endif
  11240. #ifdef RLIMIT_NPROC
  11241. { "process", RLIMIT_NPROC, 1, 'p' },
  11242. #endif
  11243. #ifdef RLIMIT_NOFILE
  11244. { "nofiles", RLIMIT_NOFILE, 1, 'n' },
  11245. #endif
  11246. #ifdef RLIMIT_AS
  11247. { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
  11248. #endif
  11249. #ifdef RLIMIT_LOCKS
  11250. { "locks", RLIMIT_LOCKS, 1, 'w' },
  11251. #endif
  11252. { (char *) 0, 0, 0, '\0' }
  11253. };
  11254. enum limtype { SOFT = 0x1, HARD = 0x2 };
  11255. static void printlim(enum limtype how, const struct rlimit *limit,
  11256. const struct limits *l)
  11257. {
  11258. rlim_t val;
  11259. val = limit->rlim_max;
  11260. if (how & SOFT)
  11261. val = limit->rlim_cur;
  11262. if (val == RLIM_INFINITY)
  11263. out1fmt("unlimited\n");
  11264. else {
  11265. val /= l->factor;
  11266. out1fmt("%lld\n", (long long) val);
  11267. }
  11268. }
  11269. int
  11270. ulimitcmd(int argc, char **argv)
  11271. {
  11272. int c;
  11273. rlim_t val = 0;
  11274. enum limtype how = SOFT | HARD;
  11275. const struct limits *l;
  11276. int set, all = 0;
  11277. int optc, what;
  11278. struct rlimit limit;
  11279. what = 'f';
  11280. while ((optc = nextopt("HSa"
  11281. #ifdef RLIMIT_CPU
  11282. "t"
  11283. #endif
  11284. #ifdef RLIMIT_FSIZE
  11285. "f"
  11286. #endif
  11287. #ifdef RLIMIT_DATA
  11288. "d"
  11289. #endif
  11290. #ifdef RLIMIT_STACK
  11291. "s"
  11292. #endif
  11293. #ifdef RLIMIT_CORE
  11294. "c"
  11295. #endif
  11296. #ifdef RLIMIT_RSS
  11297. "m"
  11298. #endif
  11299. #ifdef RLIMIT_MEMLOCK
  11300. "l"
  11301. #endif
  11302. #ifdef RLIMIT_NPROC
  11303. "p"
  11304. #endif
  11305. #ifdef RLIMIT_NOFILE
  11306. "n"
  11307. #endif
  11308. #ifdef RLIMIT_AS
  11309. "v"
  11310. #endif
  11311. #ifdef RLIMIT_LOCKS
  11312. "w"
  11313. #endif
  11314. )) != '\0')
  11315. switch (optc) {
  11316. case 'H':
  11317. how = HARD;
  11318. break;
  11319. case 'S':
  11320. how = SOFT;
  11321. break;
  11322. case 'a':
  11323. all = 1;
  11324. break;
  11325. default:
  11326. what = optc;
  11327. }
  11328. for (l = limits; l->option != what; l++)
  11329. ;
  11330. set = *argptr ? 1 : 0;
  11331. if (set) {
  11332. char *p = *argptr;
  11333. if (all || argptr[1])
  11334. error("too many arguments");
  11335. if (strncmp(p, "unlimited\n", 9) == 0)
  11336. val = RLIM_INFINITY;
  11337. else {
  11338. val = (rlim_t) 0;
  11339. while ((c = *p++) >= '0' && c <= '9')
  11340. {
  11341. val = (val * 10) + (long)(c - '0');
  11342. if (val < (rlim_t) 0)
  11343. break;
  11344. }
  11345. if (c)
  11346. error("bad number");
  11347. val *= l->factor;
  11348. }
  11349. }
  11350. if (all) {
  11351. for (l = limits; l->name; l++) {
  11352. getrlimit(l->cmd, &limit);
  11353. out1fmt("%-20s ", l->name);
  11354. printlim(how, &limit, l);
  11355. }
  11356. return 0;
  11357. }
  11358. getrlimit(l->cmd, &limit);
  11359. if (set) {
  11360. if (how & HARD)
  11361. limit.rlim_max = val;
  11362. if (how & SOFT)
  11363. limit.rlim_cur = val;
  11364. if (setrlimit(l->cmd, &limit) < 0)
  11365. error("error setting limit (%m)");
  11366. } else {
  11367. printlim(how, &limit, l);
  11368. }
  11369. return 0;
  11370. }
  11371. #ifdef CONFIG_ASH_MATH_SUPPORT
  11372. /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
  11373. Permission is hereby granted, free of charge, to any person obtaining
  11374. a copy of this software and associated documentation files (the
  11375. "Software"), to deal in the Software without restriction, including
  11376. without limitation the rights to use, copy, modify, merge, publish,
  11377. distribute, sublicense, and/or sell copies of the Software, and to
  11378. permit persons to whom the Software is furnished to do so, subject to
  11379. the following conditions:
  11380. The above copyright notice and this permission notice shall be
  11381. included in all copies or substantial portions of the Software.
  11382. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  11383. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  11384. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  11385. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  11386. CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  11387. TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  11388. SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  11389. */
  11390. /* This is my infix parser/evaluator. It is optimized for size, intended
  11391. * as a replacement for yacc-based parsers. However, it may well be faster
  11392. * than a comparable parser written in yacc. The supported operators are
  11393. * listed in #defines below. Parens, order of operations, and error handling
  11394. * are supported. This code is thread safe. The exact expression format should
  11395. * be that which POSIX specifies for shells. */
  11396. /* The code uses a simple two-stack algorithm. See
  11397. * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
  11398. * for a detailed explanation of the infix-to-postfix algorithm on which
  11399. * this is based (this code differs in that it applies operators immediately
  11400. * to the stack instead of adding them to a queue to end up with an
  11401. * expression). */
  11402. /* To use the routine, call it with an expression string and error return
  11403. * pointer */
  11404. /*
  11405. * Aug 24, 2001 Manuel Novoa III
  11406. *
  11407. * Reduced the generated code size by about 30% (i386) and fixed several bugs.
  11408. *
  11409. * 1) In arith_apply():
  11410. * a) Cached values of *numptr and &(numptr[-1]).
  11411. * b) Removed redundant test for zero denominator.
  11412. *
  11413. * 2) In arith():
  11414. * a) Eliminated redundant code for processing operator tokens by moving
  11415. * to a table-based implementation. Also folded handling of parens
  11416. * into the table.
  11417. * b) Combined all 3 loops which called arith_apply to reduce generated
  11418. * code size at the cost of speed.
  11419. *
  11420. * 3) The following expressions were treated as valid by the original code:
  11421. * 1() , 0! , 1 ( *3 ) .
  11422. * These bugs have been fixed by internally enclosing the expression in
  11423. * parens and then checking that all binary ops and right parens are
  11424. * preceded by a valid expression (NUM_TOKEN).
  11425. *
  11426. * Note: It may be desirable to replace Aaron's test for whitespace with
  11427. * ctype's isspace() if it is used by another busybox applet or if additional
  11428. * whitespace chars should be considered. Look below the "#include"s for a
  11429. * precompiler test.
  11430. */
  11431. /*
  11432. * Aug 26, 2001 Manuel Novoa III
  11433. *
  11434. * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
  11435. *
  11436. * Merge in Aaron's comments previously posted to the busybox list,
  11437. * modified slightly to take account of my changes to the code.
  11438. *
  11439. */
  11440. /*
  11441. * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
  11442. *
  11443. * - allow access to variable,
  11444. * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
  11445. * - realize assign syntax (VAR=expr, +=, *= etc)
  11446. * - realize exponentiation (** operator)
  11447. * - realize comma separated - expr, expr
  11448. * - realise ++expr --expr expr++ expr--
  11449. * - realise expr ? expr : expr (but, second expr calculate always)
  11450. * - allow hexadecimal and octal numbers
  11451. * - was restored loses XOR operator
  11452. * - remove one goto label, added three ;-)
  11453. * - protect $((num num)) as true zero expr (Manuel`s error)
  11454. * - always use special isspace(), see comment from bash ;-)
  11455. */
  11456. #define arith_isspace(arithval) \
  11457. (arithval == ' ' || arithval == '\n' || arithval == '\t')
  11458. typedef unsigned char operator;
  11459. /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
  11460. * precedence, and 3 high bits are an ID unique across operators of that
  11461. * precedence. The ID portion is so that multiple operators can have the
  11462. * same precedence, ensuring that the leftmost one is evaluated first.
  11463. * Consider * and /. */
  11464. #define tok_decl(prec,id) (((id)<<5)|(prec))
  11465. #define PREC(op) ((op) & 0x1F)
  11466. #define TOK_LPAREN tok_decl(0,0)
  11467. #define TOK_COMMA tok_decl(1,0)
  11468. #define TOK_ASSIGN tok_decl(2,0)
  11469. #define TOK_AND_ASSIGN tok_decl(2,1)
  11470. #define TOK_OR_ASSIGN tok_decl(2,2)
  11471. #define TOK_XOR_ASSIGN tok_decl(2,3)
  11472. #define TOK_PLUS_ASSIGN tok_decl(2,4)
  11473. #define TOK_MINUS_ASSIGN tok_decl(2,5)
  11474. #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
  11475. #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
  11476. #define TOK_MUL_ASSIGN tok_decl(3,0)
  11477. #define TOK_DIV_ASSIGN tok_decl(3,1)
  11478. #define TOK_REM_ASSIGN tok_decl(3,2)
  11479. /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
  11480. #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
  11481. /* conditional is right associativity too */
  11482. #define TOK_CONDITIONAL tok_decl(4,0)
  11483. #define TOK_CONDITIONAL_SEP tok_decl(4,1)
  11484. #define TOK_OR tok_decl(5,0)
  11485. #define TOK_AND tok_decl(6,0)
  11486. #define TOK_BOR tok_decl(7,0)
  11487. #define TOK_BXOR tok_decl(8,0)
  11488. #define TOK_BAND tok_decl(9,0)
  11489. #define TOK_EQ tok_decl(10,0)
  11490. #define TOK_NE tok_decl(10,1)
  11491. #define TOK_LT tok_decl(11,0)
  11492. #define TOK_GT tok_decl(11,1)
  11493. #define TOK_GE tok_decl(11,2)
  11494. #define TOK_LE tok_decl(11,3)
  11495. #define TOK_LSHIFT tok_decl(12,0)
  11496. #define TOK_RSHIFT tok_decl(12,1)
  11497. #define TOK_ADD tok_decl(13,0)
  11498. #define TOK_SUB tok_decl(13,1)
  11499. #define TOK_MUL tok_decl(14,0)
  11500. #define TOK_DIV tok_decl(14,1)
  11501. #define TOK_REM tok_decl(14,2)
  11502. /* exponent is right associativity */
  11503. #define TOK_EXPONENT tok_decl(15,1)
  11504. /* For now unary operators. */
  11505. #define UNARYPREC 16
  11506. #define TOK_BNOT tok_decl(UNARYPREC,0)
  11507. #define TOK_NOT tok_decl(UNARYPREC,1)
  11508. #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
  11509. #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
  11510. #define PREC_PRE (UNARYPREC+2)
  11511. #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
  11512. #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
  11513. #define PREC_POST (UNARYPREC+3)
  11514. #define TOK_POST_INC tok_decl(PREC_POST, 0)
  11515. #define TOK_POST_DEC tok_decl(PREC_POST, 1)
  11516. #define SPEC_PREC (UNARYPREC+4)
  11517. #define TOK_NUM tok_decl(SPEC_PREC, 0)
  11518. #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
  11519. #define NUMPTR (*numstackptr)
  11520. static inline int tok_have_assign(operator op)
  11521. {
  11522. operator prec = PREC(op);
  11523. convert_prec_is_assing(prec);
  11524. return (prec == PREC(TOK_ASSIGN) ||
  11525. prec == PREC_PRE || prec == PREC_POST);
  11526. }
  11527. static inline int is_right_associativity(operator prec)
  11528. {
  11529. return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
  11530. prec == PREC(TOK_CONDITIONAL));
  11531. }
  11532. typedef struct ARITCH_VAR_NUM {
  11533. arith_t val;
  11534. arith_t contidional_second_val;
  11535. char contidional_second_val_initialized;
  11536. char *var; /* if NULL then is regular number,
  11537. else is variable name */
  11538. } v_n_t;
  11539. typedef struct CHK_VAR_RECURSIVE_LOOPED {
  11540. const char *var;
  11541. struct CHK_VAR_RECURSIVE_LOOPED *next;
  11542. } chk_var_recursive_looped_t;
  11543. static chk_var_recursive_looped_t *prev_chk_var_recursive;
  11544. static int arith_lookup_val(v_n_t *t)
  11545. {
  11546. if(t->var) {
  11547. const char * p = lookupvar(t->var);
  11548. if(p) {
  11549. int errcode;
  11550. /* recursive try as expression */
  11551. chk_var_recursive_looped_t *cur;
  11552. chk_var_recursive_looped_t cur_save;
  11553. for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
  11554. if(strcmp(cur->var, t->var) == 0) {
  11555. /* expression recursion loop detected */
  11556. return -5;
  11557. }
  11558. }
  11559. /* save current lookuped var name */
  11560. cur = prev_chk_var_recursive;
  11561. cur_save.var = t->var;
  11562. cur_save.next = cur;
  11563. prev_chk_var_recursive = &cur_save;
  11564. t->val = arith (p, &errcode);
  11565. /* restore previous ptr after recursiving */
  11566. prev_chk_var_recursive = cur;
  11567. return errcode;
  11568. } else {
  11569. /* allow undefined var as 0 */
  11570. t->val = 0;
  11571. }
  11572. }
  11573. return 0;
  11574. }
  11575. /* "applying" a token means performing it on the top elements on the integer
  11576. * stack. For a unary operator it will only change the top element, but a
  11577. * binary operator will pop two arguments and push a result */
  11578. static inline int
  11579. arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
  11580. {
  11581. v_n_t *numptr_m1;
  11582. arith_t numptr_val, rez;
  11583. int ret_arith_lookup_val;
  11584. if (NUMPTR == numstack) goto err; /* There is no operator that can work
  11585. without arguments */
  11586. numptr_m1 = NUMPTR - 1;
  11587. /* check operand is var with noninteger value */
  11588. ret_arith_lookup_val = arith_lookup_val(numptr_m1);
  11589. if(ret_arith_lookup_val)
  11590. return ret_arith_lookup_val;
  11591. rez = numptr_m1->val;
  11592. if (op == TOK_UMINUS)
  11593. rez *= -1;
  11594. else if (op == TOK_NOT)
  11595. rez = !rez;
  11596. else if (op == TOK_BNOT)
  11597. rez = ~rez;
  11598. else if (op == TOK_POST_INC || op == TOK_PRE_INC)
  11599. rez++;
  11600. else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
  11601. rez--;
  11602. else if (op != TOK_UPLUS) {
  11603. /* Binary operators */
  11604. /* check and binary operators need two arguments */
  11605. if (numptr_m1 == numstack) goto err;
  11606. /* ... and they pop one */
  11607. --NUMPTR;
  11608. numptr_val = rez;
  11609. if (op == TOK_CONDITIONAL) {
  11610. if(! numptr_m1->contidional_second_val_initialized) {
  11611. /* protect $((expr1 ? expr2)) without ": expr" */
  11612. goto err;
  11613. }
  11614. rez = numptr_m1->contidional_second_val;
  11615. } else if(numptr_m1->contidional_second_val_initialized) {
  11616. /* protect $((expr1 : expr2)) without "expr ? " */
  11617. goto err;
  11618. }
  11619. numptr_m1 = NUMPTR - 1;
  11620. if(op != TOK_ASSIGN) {
  11621. /* check operand is var with noninteger value for not '=' */
  11622. ret_arith_lookup_val = arith_lookup_val(numptr_m1);
  11623. if(ret_arith_lookup_val)
  11624. return ret_arith_lookup_val;
  11625. }
  11626. if (op == TOK_CONDITIONAL) {
  11627. numptr_m1->contidional_second_val = rez;
  11628. }
  11629. rez = numptr_m1->val;
  11630. if (op == TOK_BOR || op == TOK_OR_ASSIGN)
  11631. rez |= numptr_val;
  11632. else if (op == TOK_OR)
  11633. rez = numptr_val || rez;
  11634. else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
  11635. rez &= numptr_val;
  11636. else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
  11637. rez ^= numptr_val;
  11638. else if (op == TOK_AND)
  11639. rez = rez && numptr_val;
  11640. else if (op == TOK_EQ)
  11641. rez = (rez == numptr_val);
  11642. else if (op == TOK_NE)
  11643. rez = (rez != numptr_val);
  11644. else if (op == TOK_GE)
  11645. rez = (rez >= numptr_val);
  11646. else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
  11647. rez >>= numptr_val;
  11648. else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
  11649. rez <<= numptr_val;
  11650. else if (op == TOK_GT)
  11651. rez = (rez > numptr_val);
  11652. else if (op == TOK_LT)
  11653. rez = (rez < numptr_val);
  11654. else if (op == TOK_LE)
  11655. rez = (rez <= numptr_val);
  11656. else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
  11657. rez *= numptr_val;
  11658. else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
  11659. rez += numptr_val;
  11660. else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
  11661. rez -= numptr_val;
  11662. else if (op == TOK_ASSIGN || op == TOK_COMMA)
  11663. rez = numptr_val;
  11664. else if (op == TOK_CONDITIONAL_SEP) {
  11665. if (numptr_m1 == numstack) {
  11666. /* protect $((expr : expr)) without "expr ? " */
  11667. goto err;
  11668. }
  11669. numptr_m1->contidional_second_val_initialized = op;
  11670. numptr_m1->contidional_second_val = numptr_val;
  11671. }
  11672. else if (op == TOK_CONDITIONAL) {
  11673. rez = rez ?
  11674. numptr_val : numptr_m1->contidional_second_val;
  11675. }
  11676. else if(op == TOK_EXPONENT) {
  11677. if(numptr_val < 0)
  11678. return -3; /* exponent less than 0 */
  11679. else {
  11680. arith_t c = 1;
  11681. if(numptr_val)
  11682. while(numptr_val--)
  11683. c *= rez;
  11684. rez = c;
  11685. }
  11686. }
  11687. else if(numptr_val==0) /* zero divisor check */
  11688. return -2;
  11689. else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
  11690. rez /= numptr_val;
  11691. else if (op == TOK_REM || op == TOK_REM_ASSIGN)
  11692. rez %= numptr_val;
  11693. }
  11694. if(tok_have_assign(op)) {
  11695. char buf[32];
  11696. if(numptr_m1->var == NULL) {
  11697. /* Hmm, 1=2 ? */
  11698. goto err;
  11699. }
  11700. /* save to shell variable */
  11701. snprintf(buf, sizeof(buf), "%lld", (long long) rez);
  11702. setvar(numptr_m1->var, buf, 0);
  11703. /* after saving, make previous value for v++ or v-- */
  11704. if(op == TOK_POST_INC)
  11705. rez--;
  11706. else if(op == TOK_POST_DEC)
  11707. rez++;
  11708. }
  11709. numptr_m1->val = rez;
  11710. /* protect geting var value, is number now */
  11711. numptr_m1->var = NULL;
  11712. return 0;
  11713. err: return(-1);
  11714. }
  11715. /* longest must first */
  11716. static const char op_tokens[] = {
  11717. '<','<','=',0, TOK_LSHIFT_ASSIGN,
  11718. '>','>','=',0, TOK_RSHIFT_ASSIGN,
  11719. '<','<', 0, TOK_LSHIFT,
  11720. '>','>', 0, TOK_RSHIFT,
  11721. '|','|', 0, TOK_OR,
  11722. '&','&', 0, TOK_AND,
  11723. '!','=', 0, TOK_NE,
  11724. '<','=', 0, TOK_LE,
  11725. '>','=', 0, TOK_GE,
  11726. '=','=', 0, TOK_EQ,
  11727. '|','=', 0, TOK_OR_ASSIGN,
  11728. '&','=', 0, TOK_AND_ASSIGN,
  11729. '*','=', 0, TOK_MUL_ASSIGN,
  11730. '/','=', 0, TOK_DIV_ASSIGN,
  11731. '%','=', 0, TOK_REM_ASSIGN,
  11732. '+','=', 0, TOK_PLUS_ASSIGN,
  11733. '-','=', 0, TOK_MINUS_ASSIGN,
  11734. '-','-', 0, TOK_POST_DEC,
  11735. '^','=', 0, TOK_XOR_ASSIGN,
  11736. '+','+', 0, TOK_POST_INC,
  11737. '*','*', 0, TOK_EXPONENT,
  11738. '!', 0, TOK_NOT,
  11739. '<', 0, TOK_LT,
  11740. '>', 0, TOK_GT,
  11741. '=', 0, TOK_ASSIGN,
  11742. '|', 0, TOK_BOR,
  11743. '&', 0, TOK_BAND,
  11744. '*', 0, TOK_MUL,
  11745. '/', 0, TOK_DIV,
  11746. '%', 0, TOK_REM,
  11747. '+', 0, TOK_ADD,
  11748. '-', 0, TOK_SUB,
  11749. '^', 0, TOK_BXOR,
  11750. /* uniq */
  11751. '~', 0, TOK_BNOT,
  11752. ',', 0, TOK_COMMA,
  11753. '?', 0, TOK_CONDITIONAL,
  11754. ':', 0, TOK_CONDITIONAL_SEP,
  11755. ')', 0, TOK_RPAREN,
  11756. '(', 0, TOK_LPAREN,
  11757. 0
  11758. };
  11759. /* ptr to ")" */
  11760. #define endexpression &op_tokens[sizeof(op_tokens)-7]
  11761. static arith_t arith (const char *expr, int *perrcode)
  11762. {
  11763. register char arithval; /* Current character under analysis */
  11764. operator lasttok, op;
  11765. operator prec;
  11766. const char *p = endexpression;
  11767. int errcode;
  11768. size_t datasizes = strlen(expr) + 2;
  11769. /* Stack of integers */
  11770. /* The proof that there can be no more than strlen(startbuf)/2+1 integers
  11771. * in any given correct or incorrect expression is left as an exercise to
  11772. * the reader. */
  11773. v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
  11774. *numstackptr = numstack;
  11775. /* Stack of operator tokens */
  11776. operator *stack = alloca((datasizes) * sizeof(operator)),
  11777. *stackptr = stack;
  11778. *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
  11779. *perrcode = errcode = 0;
  11780. while(1) {
  11781. if ((arithval = *expr) == 0) {
  11782. if (p == endexpression) {
  11783. /* Null expression. */
  11784. return 0;
  11785. }
  11786. /* This is only reached after all tokens have been extracted from the
  11787. * input stream. If there are still tokens on the operator stack, they
  11788. * are to be applied in order. At the end, there should be a final
  11789. * result on the integer stack */
  11790. if (expr != endexpression + 1) {
  11791. /* If we haven't done so already, */
  11792. /* append a closing right paren */
  11793. expr = endexpression;
  11794. /* and let the loop process it. */
  11795. continue;
  11796. }
  11797. /* At this point, we're done with the expression. */
  11798. if (numstackptr != numstack+1) {
  11799. /* ... but if there isn't, it's bad */
  11800. err:
  11801. return (*perrcode = -1);
  11802. }
  11803. if(numstack->var) {
  11804. /* expression is $((var)) only, lookup now */
  11805. errcode = arith_lookup_val(numstack);
  11806. }
  11807. ret:
  11808. *perrcode = errcode;
  11809. return numstack->val;
  11810. } else {
  11811. /* Continue processing the expression. */
  11812. if (arith_isspace(arithval)) {
  11813. /* Skip whitespace */
  11814. goto prologue;
  11815. }
  11816. if((p = endofname(expr)) != expr) {
  11817. size_t var_name_size = (p-expr) + 1; /* trailing zero */
  11818. numstackptr->var = alloca(var_name_size);
  11819. safe_strncpy(numstackptr->var, expr, var_name_size);
  11820. expr = p;
  11821. num:
  11822. numstackptr->contidional_second_val_initialized = 0;
  11823. numstackptr++;
  11824. lasttok = TOK_NUM;
  11825. continue;
  11826. } else if (is_digit(arithval)) {
  11827. numstackptr->var = NULL;
  11828. numstackptr->val = strtoll(expr, (char **) &expr, 0);
  11829. goto num;
  11830. }
  11831. for(p = op_tokens; ; p++) {
  11832. const char *o;
  11833. if(*p == 0) {
  11834. /* strange operator not found */
  11835. goto err;
  11836. }
  11837. for(o = expr; *p && *o == *p; p++)
  11838. o++;
  11839. if(! *p) {
  11840. /* found */
  11841. expr = o - 1;
  11842. break;
  11843. }
  11844. /* skip tail uncompared token */
  11845. while(*p)
  11846. p++;
  11847. /* skip zero delim */
  11848. p++;
  11849. }
  11850. op = p[1];
  11851. /* post grammar: a++ reduce to num */
  11852. if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
  11853. lasttok = TOK_NUM;
  11854. /* Plus and minus are binary (not unary) _only_ if the last
  11855. * token was as number, or a right paren (which pretends to be
  11856. * a number, since it evaluates to one). Think about it.
  11857. * It makes sense. */
  11858. if (lasttok != TOK_NUM) {
  11859. switch(op) {
  11860. case TOK_ADD:
  11861. op = TOK_UPLUS;
  11862. break;
  11863. case TOK_SUB:
  11864. op = TOK_UMINUS;
  11865. break;
  11866. case TOK_POST_INC:
  11867. op = TOK_PRE_INC;
  11868. break;
  11869. case TOK_POST_DEC:
  11870. op = TOK_PRE_DEC;
  11871. break;
  11872. }
  11873. }
  11874. /* We don't want a unary operator to cause recursive descent on the
  11875. * stack, because there can be many in a row and it could cause an
  11876. * operator to be evaluated before its argument is pushed onto the
  11877. * integer stack. */
  11878. /* But for binary operators, "apply" everything on the operator
  11879. * stack until we find an operator with a lesser priority than the
  11880. * one we have just extracted. */
  11881. /* Left paren is given the lowest priority so it will never be
  11882. * "applied" in this way.
  11883. * if associativity is right and priority eq, applied also skip
  11884. */
  11885. prec = PREC(op);
  11886. if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
  11887. /* not left paren or unary */
  11888. if (lasttok != TOK_NUM) {
  11889. /* binary op must be preceded by a num */
  11890. goto err;
  11891. }
  11892. while (stackptr != stack) {
  11893. if (op == TOK_RPAREN) {
  11894. /* The algorithm employed here is simple: while we don't
  11895. * hit an open paren nor the bottom of the stack, pop
  11896. * tokens and apply them */
  11897. if (stackptr[-1] == TOK_LPAREN) {
  11898. --stackptr;
  11899. /* Any operator directly after a */
  11900. lasttok = TOK_NUM;
  11901. /* close paren should consider itself binary */
  11902. goto prologue;
  11903. }
  11904. } else {
  11905. operator prev_prec = PREC(stackptr[-1]);
  11906. convert_prec_is_assing(prec);
  11907. convert_prec_is_assing(prev_prec);
  11908. if (prev_prec < prec)
  11909. break;
  11910. /* check right assoc */
  11911. if(prev_prec == prec && is_right_associativity(prec))
  11912. break;
  11913. }
  11914. errcode = arith_apply(*--stackptr, numstack, &numstackptr);
  11915. if(errcode) goto ret;
  11916. }
  11917. if (op == TOK_RPAREN) {
  11918. goto err;
  11919. }
  11920. }
  11921. /* Push this operator to the stack and remember it. */
  11922. *stackptr++ = lasttok = op;
  11923. prologue:
  11924. ++expr;
  11925. }
  11926. }
  11927. }
  11928. #endif /* CONFIG_ASH_MATH_SUPPORT */
  11929. #ifdef DEBUG
  11930. const char *bb_applet_name = "debug stuff usage";
  11931. int main(int argc, char **argv)
  11932. {
  11933. return ash_main(argc, argv);
  11934. }
  11935. #endif
  11936. /*-
  11937. * Copyright (c) 1989, 1991, 1993, 1994
  11938. * The Regents of the University of California. All rights reserved.
  11939. *
  11940. * This code is derived from software contributed to Berkeley by
  11941. * Kenneth Almquist.
  11942. *
  11943. * Redistribution and use in source and binary forms, with or without
  11944. * modification, are permitted provided that the following conditions
  11945. * are met:
  11946. * 1. Redistributions of source code must retain the above copyright
  11947. * notice, this list of conditions and the following disclaimer.
  11948. * 2. Redistributions in binary form must reproduce the above copyright
  11949. * notice, this list of conditions and the following disclaimer in the
  11950. * documentation and/or other materials provided with the distribution.
  11951. *
  11952. * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
  11953. * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
  11954. *
  11955. * 4. Neither the name of the University nor the names of its contributors
  11956. * may be used to endorse or promote products derived from this software
  11957. * without specific prior written permission.
  11958. *
  11959. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  11960. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  11961. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  11962. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  11963. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  11964. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  11965. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  11966. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  11967. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  11968. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  11969. * SUCH DAMAGE.
  11970. */