123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915 |
- #include "ckcsym.h"
- /* C K U U S 4 -- "User Interface" for C-Kermit, part 4 */
- /*
- Authors:
- Frank da Cruz <fdc@columbia.edu>,
- The Kermit Project, New York City
- Jeffrey E Altman <jaltman@secure-endpoints.com>
- Secure Endpoints Inc., New York City
- Copyright (C) 1985, 2020,
- Trustees of Columbia University in the City of New York.
- All rights reserved. See the C-Kermit COPYING.TXT file or the
- copyright text in the ckcmai.c module for disclaimer and permissions.
- Last update:
- Fri Sep 18 14:54:00 2020
- */
- /*
- File ckuus4.c -- Functions moved from other ckuus*.c modules to even
- out their sizes.
- */
- #include "ckcdeb.h"
- #include "ckcasc.h"
- #include "ckcker.h"
- #include "ckcnet.h" /* Network symbols */
- #include "ckuusr.h"
- #include "ckuver.h"
- #include "ckcxla.h" /* Character sets */
- #ifdef HAVE_LOCALE
- #include <locale.h>
- #endif /* HAVE_LOCALE */
- #ifdef CK_AUTHENTICATION
- #include "ckuath.h"
- #endif /* CK_AUTHENTICATION */
- #ifdef CK_SSL
- #include "ck_ssl.h"
- #endif /* CK_SSL */
- #ifdef VMS
- #include <errno.h> /* For \v(errno) */
- extern char * ckvmserrstr(unsigned long);
- #ifndef OLD_VMS
- #include <lib$routines.h> /* Not for VAX C 2.4 */
- #else
- #include <libdef.h>
- #endif /* OLD_VMS */
- _PROTOTYP(int vmsttyfd, (void) );
- #endif /* VMS */
- #ifdef OS2
- #ifndef NT
- #define INCL_NOPM
- #define INCL_VIO /* Needed for ckocon.h */
- #include <os2.h>
- #undef COMMENT
- #else
- #include <windows.h>
- #include <tapi.h>
- #include "ckntap.h"
- #define APIRET ULONG
- #endif /* NT */
- #include "ckocon.h"
- #include "ckodir.h" /* [jt] 2013/11/21 - for MAXPATHLEN */
- #include "ckoetc.h"
- int StartedFromDialer = 0;
- HWND hwndDialer = 0;
- LONG KermitDialerID = 0;
- #ifdef putchar
- #undef putchar
- #endif /* putchar */
- #define putchar(x) conoc(x)
- #ifdef CK_PID
- #include <process.h>
- #endif /* CK_PID */
- #endif /* OS2 */
- #ifdef KUI
- extern struct keytab * term_font;
- extern int ntermfont, tt_font, tt_font_size;
- #endif /* KUI */
- extern xx_strp xxstring;
- #ifdef DEC_TCPIP
- #include <descrip>
- #include <dvidef>
- #include <dcdef>
- #endif /* DEC_TCPIP */
- #ifndef NOICP
- extern char *tfnam[];
- extern int tlevel;
- #endif /* NOICP */
- #ifdef FNFLOAT
- #include <math.h> /* Floating-point functions */
- #endif /* FNFLOAT */
- int fp_rounding = 0; /* Nonzero if printf("%f") rounds */
- int fp_digits = 0; /* Digits of floating point precision */
- extern int quiet, network, xitsta, escape, nopush, xferstat,
- exitonclose, tn_exit, ttnproto, autodl, flow, byteorder, what, lastxfer;
- extern int filepeek, nscanfile, makestrlen;
- extern char * k_info_dir;
- #ifndef MAC
- #ifndef AMIGA
- extern int ttyfd;
- #endif /* MAC */
- #endif /* AMIGA */
- #ifdef TNCODE
- extern int tn_nlm, tn_b_nlm, tn_b_xfer, tn_sb_bug;
- extern int tn_rem_echo;
- extern int tn_b_meu, tn_b_ume, tn_auth_krb5_des_bug;
- #endif /* TNCODE */
- static char * lastkwval = NULL;
- char * xferfile = NULL;
- int xferlog = 0;
- extern int local, xargc, stayflg, rcflag, bgset, backgrd, cfilef,
- inserver, srvcdmsg, success;
- #ifdef VMS
- extern int batch;
- #endif /* VMS */
- extern char cmdfil[], *versio, *ckxsys, **xargv;
- extern char lasttakeline[];
- #ifdef DEBUG
- extern char debfil[]; /* Debug log file name */
- extern int debtim;
- #endif /* DEBUG */
- extern int noinit;
- static char ndatbuf[10];
- char *months[] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
- char *
- zzndate() { /* Returns today's date as yyyymmdd */
- char * p = NULL;
- int x;
- /* WARNING - This will fail if asctime() returns non-English month names */
- ztime(&p); /* Get "asctime" string */
- if (p == NULL || *p == NUL) return("");
- for (x = 20; x < 24; x++) /* yyyy */
- ndatbuf[x - 20] = p[x];
- ndatbuf[6] = (char) ((p[8] == ' ') ? '0' : p[8]);
- ndatbuf[7] = p[9]; /* dd */
- for (x = 0; x < 12; x++) /* mm */
- if (!strncmp(p+4,months[x],3)) break;
- if (x == 12) {
- ndatbuf[4] = ndatbuf[5] = '?';
- } else {
- x++;
- ndatbuf[4] = (char) ((x < 10) ? '0' : '1');
- ndatbuf[5] = (char) ((x % 10) + 48);
- }
- ndatbuf[8] = NUL;
- debug(F110,"zzndate return",ndatbuf,0);
- return((char *)ndatbuf);
- }
- #ifdef DCMDBUF
- extern struct cmdptr *cmdstk;
- extern char *line, *tmpbuf;
- #else
- extern struct cmdptr cmdstk[];
- extern char line[], tmpbuf[];
- #endif /* DCMDBUF */
- #ifdef OS2
- extern char exedir[];
- #else
- extern char * exedir;
- #endif /* OS2 */
- extern int nettype;
- #ifndef NOICP /* Most of this file... */
- #ifdef CKLOGDIAL
- extern char diafil[];
- #endif /* CKLOGDIAL */
- #ifndef AMIGA
- #ifndef MAC
- #include <signal.h>
- #endif /* MAC */
- #endif /* AMIGA */
- #ifdef SV68 /* July 2006 believe it or not */
- #ifndef SEEK_CUR
- #include <unistd.h>
- #endif /* SEEK_CUR */
- #endif /* SV68 */
- #ifdef SCO32 /* June 2011 believe it or not... */
- #ifdef XENIX
- #ifndef SEEK_CUR
- #include <unistd.h>
- #endif /* SEEK_CUR */
- #endif /* XENIX */
- #endif /* SCO32 */
- #ifdef STRATUS /* Stratus Computer, Inc. VOS */
- #ifdef putchar
- #undef putchar
- #endif /* putchar */
- #define putchar(x) conoc(x)
- #ifdef getchar
- #undef getchar
- #endif /* getchar */
- #define getchar(x) coninc(0)
- #endif /* STRATUS */
- #ifdef ANYX25
- extern int revcall, closgr, cudata;
- int x25ver;
- extern char udata[];
- #ifndef IBMX25
- extern int npadx3;
- extern CHAR padparms[];
- extern struct keytab padx3tab[];
- #endif /* !IBMX25 */
- #ifdef IBMX25
- /* global variables only available for IBM X.25 - possibly interesting for
- * other implementations
- */
- extern x25addr_t local_nua;
- extern x25addr_t remote_nua;
- #endif /* IBMX25 */
- #endif /* ANYX25 */
- #ifdef NETCONN
- #ifndef NODIAL
- extern int nnetdir;
- extern char *netdir[];
- #endif /* NODIAL */
- extern char ipaddr[];
- #ifdef CK_NETBIOS
- extern unsigned short netbiosAvail;
- extern unsigned long NetbeuiAPI;
- extern unsigned char NetBiosName[];
- extern unsigned char NetBiosAdapter;
- extern unsigned char NetBiosLSN;
- #endif /* CK_NETBIOS */
- #ifdef TCPSOCKET
- extern char myipaddr[];
- extern int tcp_rdns;
- #ifdef CK_DNS_SRV
- extern int tcp_dns_srv;
- #endif /* CK_DNS_SRV */
- extern char * tcp_address;
- #ifndef NOHTTP
- extern char * tcp_http_proxy;
- #endif /* NOHTTP */
- #ifdef NT
- #ifdef CK_SOCKS
- extern char * tcp_socks_svr;
- #ifdef CK_SOCKS_NS
- extern char * tcp_socks_ns;
- #endif /* CK_SOCKS_NS */
- #endif /* CK_SOCKS */
- #endif /* NT */
- #ifndef NOTCPOPTS
- #ifdef SOL_SOCKET
- #ifdef SO_LINGER
- extern int tcp_linger;
- extern int tcp_linger_tmo;
- #endif /* SO_LINGER */
- #ifdef SO_DONTROUTE
- extern int tcp_dontroute;
- #endif /* SO_DONTROUTE */
- #ifdef TCP_NODELAY
- extern int tcp_nodelay;
- #endif /* TCP_NODELAY */
- #ifdef SO_SNDBUF
- extern int tcp_sendbuf;
- #endif /* SO_SNDBUF */
- #ifdef SO_RCVBUF
- extern int tcp_recvbuf;
- #endif /* SO_RCVBUF */
- #ifdef SO_KEEPALIVE
- extern int tcp_keepalive;
- #endif /* SO_KEEPALIVE */
- #endif /* SOL_SOCKET */
- #endif /* NOTCPOPTS */
- #endif /* TCPSOCKET */
- #endif /* NETCONN */
- extern char * floname[];
- #ifndef NOSPL
- extern int vareval; /* Variable evaluation method */
- extern int fndiags; /* Function diagnostics on/off */
- extern int divbyzero;
- int itsapattern = 0;
- int isinbuflen = 0;
- int isjoin = 0;
- #ifdef CK_APC
- extern int apcactive; /* Nonzero = APC command was rec'd */
- extern int apcstatus; /* Are APC commands being processed? */
- #ifdef DCMDBUF
- extern char *apcbuf; /* APC command buffer */
- #else
- extern char apcbuf[];
- #endif /* DCMDBUF */
- #endif /* CK_APC */
- extern char evalbuf[]; /* EVALUATE result */
- extern char uidbuf[], pwbuf[], prmbuf[];
- _PROTOTYP( static char * fneval, (char *, char * [], int, char * ) );
- _PROTOTYP( static VOID myflsh, (void) );
- _PROTOTYP( static char * getip, (char *) );
- _PROTOTYP( int delta2sec, (char *, long *) );
- #ifdef NEWFTP
- _PROTOTYP( char * ftp_cpl_mode, (void) );
- _PROTOTYP( char * ftp_dpl_mode, (void) );
- _PROTOTYP( char * ftp_authtype, (void) );
- #endif /* NEWFTP */
- #ifndef NOHTTP
- _PROTOTYP( char * http_host, (void) );
- _PROTOTYP( int http_isconnected, (void) );
- _PROTOTYP( char * http_security, (void) );
- #endif /* NOHTTP */
- #ifndef NOSEXP
- _PROTOTYP( char * dosexp, (char *) );
- int fsexpflag = 0;
- #endif /* NOSEXP */
- static char hexdigits[16] = {
- '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
- };
- extern char * tempdir;
- #ifdef CK_REXX
- extern char rexxbuf[];
- #endif /* CK_REXX */
- extern int tfline[];
- char *wkdays[] = {
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
- };
- #endif /* NOSPL */
- #ifdef OS2
- extern char startupdir[], inidir[];
- #else
- #ifdef VMSORUNIX
- extern char startupdir[];
- #endif /* VMSORUNIX */
- #endif /* OS2 */
- #ifdef OS2
- _PROTOTYP (int os2getcp, (void) );
- #ifdef TCPSOCKET
- extern char tcpname[];
- #endif /* TCPSOCKET */
- extern int tcp_avail;
- #ifdef DECNET
- extern int dnet_avail;
- #endif /* DECNET */
- #ifdef SUPERLAT
- extern int slat_avail;
- #endif /* SUPERLAT */
- #ifndef NOTERM
- extern int tt_type, max_tt;
- extern struct tt_info_rec tt_info[];
- #endif /* NOTERM */
- extern int tt_rows[], tt_cols[];
- #else /* OS2 */
- extern int tt_rows, tt_cols;
- #endif /* OS2 */
- #ifdef CK_TAPI
- extern int tttapi;
- extern int tapipass;
- extern struct keytab * tapilinetab;
- extern struct keytab * _tapilinetab;
- extern int ntapiline;
- #endif /* CK_TAPI */
- extern struct keytab colxtab[];
- extern int ncolx;
- extern char ttname[], *zinptr, *kermrc;
- extern char inidir[];
- extern int activecmd, remonly, cmd_rows, cmd_cols, parity, seslog,
- sessft, sosi, hwparity, tsecs, xargs, zincnt, tlevel, insilence, cmdmsk,
- timint, timef, inbufsize, dialog, binary, carrier, cdtimo, cmask, duplex,
- fmask, inecho, nmac, turnch, turn, kbchar;
- #ifndef NOXFER
- extern CHAR eol, mypadc, mystch, padch, seol, stchr, * epktmsg, feol;
- extern char *cksysid;
- extern struct ck_p ptab[];
- extern int
- protocol, prefixing, xfrbel, xfrcan, xfrint, xfrchr, xfrnum, pktpaus,
- lscapr, lscapu, xfermode, dest, slostart, maxrps, maxsps, maxtry, mypadn,
- npad, pkttim, bigrbsiz, bigsbsiz, keep, atcapr, autopar, bctr, bctu,
- crunched, ckdelay, ebq, ebqflg, pktlog, retrans, rpackets, rptflg, rptq,
- rtimo, spackets, spsiz, spsizf, spsizr, timeouts, fncact, fncnv, urpsiz,
- wmax, wslotn, wslotr, fdispla, spmax, fnrpath, fnspath, crc16;
- #endif /* NOXFER */
- #ifdef OS2
- extern int zxpn;
- extern int viewonly;
- #endif /* OS2 */
- #ifndef NOXFER
- #ifdef GFTIMER
- extern CKFLOAT fptsecs, fpxfsecs;
- #endif /* GFTIMER */
- extern long xfsecs, tfcps;
- #ifdef CK_TMPDIR
- extern char *dldir;
- #endif /* CK_TMPDIR */
- #endif /* NOXFER */
- #ifdef RECURSIVE
- extern int recursive;
- #endif /* RECURSIVE */
- #ifdef VMS
- extern int frecl;
- #endif /* VMS */
- extern CK_OFF_T ffc, tfc, tlci, tlco;
- extern long filcnt, rptn, speed, ccu, ccp, vernum, xvernum;
- #ifndef NOSPL
- extern char fspec[], myhost[];
- #endif /* NOSPL */
- extern char *tfnam[]; /* Command file names */
- extern char pktfil[], /* Packet log file name */
- #ifdef TLOG
- trafil[], /* Transaction log file name */
- #endif /* TLOG */
- sesfil[]; /* Session log file name */
- #ifndef NOXMIT /* TRANSMIT command variables */
- extern char xmitbuf[];
- extern int xmitf, xmitl, xmitx, xmits, xmitw, xmitt;
- #endif /* NOXMIT */
- extern int cmdlvl;
- #ifndef NOSPL
- /* Script programming language items */
- extern char **a_ptr[]; /* Arrays */
- extern int a_dim[];
- static char * inpmatch = NULL;
- #ifdef CKFLOAT
- char * inpscale = NULL;
- #endif /* CKFLOAT */
- extern char * inpbuf, inchar[]; /* Buffers for INPUT and REINPUT */
- extern char *inpbp; /* And pointer to same */
- static char *r3 = (char *)0;
- extern int incount; /* INPUT character count */
- extern int m_found; /* MINPUT result */
- extern int maclvl; /* Macro invocation level */
- extern struct mtab *mactab; /* Macro table */
- extern char *mrval[];
- extern int macargc[], topargc;
- #ifdef COMMENT
- extern char *m_line[];
- extern char *topline;
- #endif /* COMMENT */
- extern char *m_arg[MACLEVEL][10]; /* You have to put in the dimensions */
- extern char *g_var[GVARS]; /* for external 2-dimensional arrays. */
- #ifdef DCMDBUF
- extern int *count, *inpcas;
- #else
- extern int count[], inpcas[];
- #endif /* DCMDBUF */
- #endif /* NOSPL */
- #ifdef UNIX
- extern int haslock; /* For UUCP locks */
- extern char flfnam[];
- #ifndef USETTYLOCK
- extern char lock2[];
- #endif /* USETTYLOCK */
- #endif /* UNIX */
- #ifdef OS2ORUNIX
- extern int maxnam, maxpath; /* Longest name, path length */
- #endif /* OS2ORUNIX */
- extern int mdmtyp, mdmsav;
- #ifndef NODIAL
- /* DIAL-related variables */
- extern char modemmsg[];
- extern MDMINF *modemp[]; /* Pointers to modem info structs */
- extern int nmdm, dialhng, dialtmo, dialksp, dialdpy, dialsrt, dialsta;
- extern int dialrtr, dialint, dialrstr, dialcon, dialcq, dialfld;
- extern int mdmspd, dialec, dialdc, dialmth, dialmauto, dialesc;
- extern char *dialnum, *dialini, *dialdir[], *dialcmd, *dialnpr,
- *dialdcon, *dialdcoff, *dialecon, *dialecoff, *dialhcmd, *diallac,
- *dialhwfc, *dialswfc, *dialnofc, *dialpulse, *dialtone, *dialname,
- *dialaaon, *dialaaoff, *dialmac;
- extern char *diallcc, *dialixp, *dialixs, *dialldp, *diallds,
- *dialpxi, *dialpxo, *dialsfx, *dialtfp;
- extern char *diallcp, *diallcs;
- extern int ntollfree, ndialpxx, nlocalac;
- extern char *dialtfc[], *diallcac[], *dialpxx[], *matchpxx;
- extern int ndialpucc, ndialtocc;
- extern char *dialtocc[], *dialpucc[];
- extern int ndialdir, dialcnf, dialcvt, dialidt, dialpace;
- extern long dialmax, dialcapas;
- extern struct keytab mdmtab[];
- #ifdef BIGBUFOK
- #define ARGBUFSIZ 8191
- #else
- #define ARGBUFSIZ 1023
- #endif /* BIGBUFOK */
- #ifdef BIGBUFOK
- extern char * dialmsg[];
- #endif /* BIGBUFOK */
- #endif /* NODIAL */
- #ifndef NOCSETS
- /* Translation stuff */
- extern int nfilc;
- extern struct keytab fcstab[];
- extern int fcharset, tcharset, tslevel, language, nlng, tcsr, tcsl;
- extern int dcset7, dcset8;
- extern struct keytab lngtab[];
- extern struct csinfo fcsinfo[], tcsinfo[];
- extern struct langinfo langs[];
- #ifdef CK_ANSIC
- extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* Character set */
- extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* translation functions */
- #else
- extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(); /* Character set */
- extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(); /* translation functions. */
- #endif /* CK_ANSIC */
- #ifdef UNICODE
- extern int ucsbom, ucsorder;
- #endif /* UNICODE */
- #endif /* NOCSETS */
- #ifndef NOSPL
- /* Built-in variable names, maximum length VNAML (20 characters) */
- struct keytab vartab[] = {
- { "_line", VN_TFLN, CM_INV}, /* 192 */
- { "apcactive", VN_APC, CM_INV}, /* 192 */
- #ifdef NT
- { "appdata", VN_APPDATA, 0}, /* 201 */
- #endif /* NT */
- { "argc", VN_ARGC, 0},
- { "args", VN_ARGS, 0},
- { "authname", VN_AUTHN, 0}, /* 196 */
- { "authstate", VN_AUTHS, 0}, /* 195 */
- { "authtype", VN_AUTHT, 0}, /* 195 */
- { "bits", VN_BITS, 0}, /* 212 */
- { "blockcheck",VN_BLK, 0}, /* 195 */
- #ifdef BROWSER
- { "browser", VN_BROWSR,0}, /* 193 */
- { "browsopts", VN_BROPT, 0}, /* 193 */
- { "browsurl", VN_URL, 0}, /* 193 */
- { "buildid", VN_BUILD, 0}, /* 199 */
- #endif /* BROWSER */
- { "byteorder", VN_BYTE, 0}, /* 195 */
- #ifndef NOCSETS
- { "charset", VN_CSET, 0}, /* 192 */
- #endif /* NOCSETS */
- { "cmdbufsize",VN_CMDBL, 0}, /* 195 */
- { "cmdfile", VN_CMDF, 0},
- { "cmdlevel", VN_CMDL, 0},
- { "cmdsource", VN_CMDS, 0},
- { "cols", VN_COLS, 0}, /* 190 */
- #ifdef NT
- { "common", VN_COMMON, 0}, /* 201 */
- #endif /* NT */
- { "connection",VN_CONN, 0}, /* 190 */
- { "count", VN_COUN, 0},
- #ifndef NOXFER
- { "cps", VN_CPS, 0}, /* 190 */
- #endif /* NOXFER */
- { "cpu", VN_CPU, 0},
- #ifndef NOXFER
- { "crc16", VN_CRC16, 0}, /* 192 */
- { "ctty", VN_TTYNAM,0}, /* 196 */
- #endif /* NOXFER */
- #ifndef NOLOGDIAL
- #ifndef NOLOCAL
- { "cx_time", VN_CXTIME,0}, /* 195 */
- { "cx_status", VN_CX_STA,0}, /* 199 */
- #endif /* NOLOCAL */
- #endif /* NOLOGDIAL */
- #ifndef NODIAL
- { "d$ac", VN_D_AC, 0}, /* 192 */
- { "d$cc", VN_D_CC, 0}, /* 192 */
- { "d$ip", VN_D_IP, 0}, /* 192 */
- { "d$lc", VN_D_LCP, 0}, /* 193 */
- { "d$lcp", VN_D_LCP, CM_INV}, /* 193 */
- { "d$lp", VN_D_LP, 0}, /* 192 */
- { "d$px", VN_D_PXX, 0}, /* 195 */
- { "d$pxx", VN_D_PXX, CM_INV}, /* 195 */
- #endif /* NODIAL */
- { "date", VN_DATE, 0},
- { "day", VN_DAY, 0},
- #ifdef NT
- { "desktop", VN_DESKTOP, 0}, /* 201 */
- #endif /* NT */
- #ifndef NODIAL
- { "dialcount", VN_DRTR, 0}, /* 195 */
- { "dialmessage",VN_DMSG, 0}, /* 212 */
- { "dialnumber",VN_DNUM, 0}, /* 192 */
- { "dialresult",VN_MDMSG, 0}, /* 192 */
- { "dialstatus",VN_DIAL, 0}, /* 190 */
- { "dialsuffix",VN_PDSFX, 0}, /* 193 */
- { "dialtype", VN_DTYPE, 0}, /* 193 */
- #endif /* NODIAL */
- { "directory", VN_DIRE, 0},
- #ifndef NODIAL
- { "dm_hf", VN_DM_HF, 0}, /* 199 */
- { "dm_lp", VN_DM_LP, 0}, /* 195 */
- { "dm_sp", VN_DM_SP, 0}, /* 195 */
- { "dm_pd", VN_DM_PD, 0}, /* 195 */
- { "dm_td", VN_DM_TD, 0}, /* 195 */
- { "dm_wa", VN_DM_WA, 0}, /* 195 */
- { "dm_wb", VN_DM_WB, 0}, /* 199 */
- { "dm_wd", VN_DM_WD, 0}, /* 195 */
- { "dm_rc", VN_DM_RC, 0}, /* 195 */
- #endif /* NODIAL */
- #ifndef NOXFER
- { "download", VN_DLDIR, 0}, /* 192 */
- #endif /* NOXFER */
- { "editor", VN_EDITOR,0},
- { "editfile", VN_EDFILE,0},
- { "editopts", VN_EDOPT, 0},
- { "errno", VN_ERRNO, 0}, /* 192 */
- { "errstring", VN_ERSTR, 0}, /* 192 */
- { "escape", VN_ESC, 0}, /* 193 */
- { "evaluate", VN_EVAL, 0}, /* 190 */
- #ifdef OS2ORUNIX
- { "exedir", VN_EXEDIR,0}, /* 192 */
- #endif /* OS2ORUNIX */
- { "exitstatus",VN_EXIT, 0},
- #ifdef CKCHANNELIO
- { "f_count", VN_FCOU, 0}, /* 195 */
- { "f_error", VN_FERR, 0}, /* 195 */
- { "f_max", VN_FMAX, 0}, /* 195 */
- { "fileerror", VN_FERR, CM_INV}, /* 195 */
- { "filemax", VN_FERR, CM_INV}, /* 195 */
- #endif /* CKCHANNELIO */
- { "filename", VN_FNAM, 0}, /* 193 */
- { "filenumber",VN_FNUM, 0}, /* 193 */
- { "filespec", VN_FILE, 0},
- { "fsize", VN_FFC, 0}, /* 190 */
- #ifdef GFTIMER
- { "ftime", VN_FTIME, 0}, /* 199 */
- #else
- { "ftime", VN_NTIM, CM_INV},
- #endif /* GFTIMER */
- #ifndef NOFTP
- #ifndef SYSFTP
- { "ftp_code", VN_FTP_C, 0}, /* 199 */
- { "ftp_cpl", VN_FTP_B, 0}, /* 199 */
- { "ftp_connected", VN_FTP_X, 0}, /* 199 */
- { "ftp_dpl", VN_FTP_D, 0}, /* 199 */
- { "ftp_getputremote", VN_FTP_G, 0}, /* 199 */
- { "ftp_host", VN_FTP_H, 0}, /* 199 */
- { "ftp_loggedin", VN_FTP_L, 0}, /* 199 */
- { "ftp_message", VN_FTP_M, 0}, /* 199 */
- { "ftp_msg", VN_FTP_M, CM_INV}, /* 199 */
- { "ftp_security", VN_FTP_Z, 0}, /* 199 */
- { "ftp_server", VN_FTP_S, 0}, /* 199 */
- #endif /* SYSFTP */
- #endif /* NOFTP */
- { "ftype", VN_MODE, 0}, /* 190 */
- #ifdef KUI
- { "gui_fontname", VN_GUI_FNM, 0}, /* 205 */
- { "gui_fontsize", VN_GUI_FSZ, 0}, /* 205 */
- { "gui_runmode", VN_GUI_RUN, 0}, /* 205 */
- { "gui_xpos", VN_GUI_XP, 0}, /* 205 */
- { "gui_xres", VN_GUI_XR, 0}, /* 205 */
- { "gui_ypos", VN_GUI_YP, 0}, /* 205 */
- { "gui_yres", VN_GUI_YR, 0}, /* 205 */
- #endif /* KUI */
- { "herald", VN_HERALD, 0},
- { "home", VN_HOME, 0},
- { "host", VN_HOST, 0},
- { "hour", VN_HOUR, 0}, /* 200 */
- #ifndef NOHTTP
- { "http_code", VN_HTTP_C, 0}, /* 199 */
- { "http_connected", VN_HTTP_N, 0}, /* 199 */
- { "http_host", VN_HTTP_H, 0}, /* 199 */
- { "http_message", VN_HTTP_M, 0}, /* 199 */
- { "http_security", VN_HTTP_S, 0}, /* 199 */
- #endif /* NOHTTP */
- { "hwparity", VN_HWPAR, 0}, /* 195 */
- { "input", VN_IBUF, 0},
- { "inchar", VN_ICHR, 0},
- { "incount", VN_ICNT, 0},
- { "inidir", VN_INI, 0}, /* 192 */
- { "inmatch", VN_MATCH, 0}, /* 196 */
- { "inmessage", VN_INPMSG,0}, /* 212 */
- { "inscale", VN_ISCALE,0}, /* 210 */
- { "instatus", VN_ISTAT, 0}, /* 192 */
- { "intime", VN_INTIME,0}, /* 193 */
- { "inwait", VN_INTMO, 0}, /* 195 */
- { "ip", VN_IPADDR, CM_ABR|CM_INV},
- { "ipaddress", VN_IPADDR,0}, /* 192 */
- { "iprompt", VN_PROMPT,0}, /* 199 */
- { "kbchar", VN_KBCHAR,0}, /* 196 */
- #ifndef NOLOCAL
- #ifdef OS2
- { "keyboard", VN_KEYB, 0},
- #endif /* OS2 */
- #endif /* NOLOCAL */
- #ifdef CK_KERBEROS
- { "krb4errmsg", VN_K4EMSG,0},
- { "krb4errno", VN_K4ENO, 0},
- { "krb4principal", VN_K4PRN, 0},
- { "krb4realm", VN_K4RLM, 0},
- { "krb4service", VN_K4SRV, 0},
- { "krb5cc", VN_K5CC, 0},
- { "krb5errmsg", VN_K5EMSG,0},
- { "krb5errno", VN_K5ENO, 0},
- { "krb5principal", VN_K5PRN, 0},
- { "krb5realm", VN_K5RLM, 0},
- { "krb5service", VN_K5SRV, 0},
- #endif /* CK_KERBEROS */
- { "lastcommand", VN_PREVCMD, 0}, /* 299 */
- #ifndef NOLASTFILE
- { "lastfilespec", VN_LASTFIL, 0}, /* 212 */
- #endif /* NOLASTFILE */
- { "lastkeywordvalue", VN_LASTKWV, 0}, /* 212 */
- { "lastkwvalue", VN_LASTKWV, CM_ABR|CM_INV}, /* 212 */
- { "line", VN_LINE, 0},
- { "local", VN_LCL, 0},
- #ifdef UNIX
- { "lockdir", VN_LCKDIR,0}, /* 195 */
- { "lockpid", VN_LCKPID,0}, /* 195 */
- #endif /* UNIX */
- { "log_connection", VN_LOG_CON, 0}, /* 206 */
- { "log_debug", VN_LOG_DEB, 0}, /* 206 */
- { "log_packet", VN_LOG_PKT, 0}, /* 206 */
- { "log_session", VN_LOG_SES, 0}, /* 206 */
- { "log_transaction", VN_LOG_TRA, 0},/* 206 */
- { "maclevel", VN_MACLVL,0}, /* 195 */
- { "macro", VN_MAC, 0},
- #ifdef FNFLOAT
- { "math_e", VN_MA_E, 0}, /* 195 */
- { "math_pi", VN_MA_PI, 0}, /* 195 */
- { "math_precision", VN_MA_PR, 0}, /* 195 */
- #endif /* FNFLOAT */
- { "minput", VN_MINP, 0}, /* 192 */
- { "model", VN_MODL, 0}, /* 193 */
- { "modem", VN_MDM, 0},
- { "month", VN_MONTH, 0}, /* 304 */
- #ifndef NOLOCAL
- #ifdef OS2
- { "mousecurx", VN_MOU_X, 0}, /* K95 1.1.14 */
- { "mousecury", VN_MOU_Y, 0}, /* K95 1.1.14 */
- #endif /* OS2 */
- #endif /* NOLOCAL */
- #ifndef NODIAL
- { "m_aa_off", VN_M_AAX, 0}, /* all 192... */
- { "m_aa_on", VN_M_AAO, 0},
- { "m_dc_off", VN_M_DCX, 0},
- { "m_dc_on", VN_M_DCO, 0},
- { "m_dial", VN_M_DCM, 0},
- { "m_ec_off", VN_M_ECX, 0},
- { "m_ec_on", VN_M_ECO, 0},
- { "m_fc_hw", VN_M_HWF, 0},
- { "m_fc_no", VN_M_NFC, 0},
- { "m_fc_sw", VN_M_SWF, 0},
- { "m_hup", VN_M_HUP, 0},
- { "m_init", VN_M_INI, 0},
- { "m_name", VN_M_NAM, 0}, /* 195 */
- { "m_pulse", VN_M_PDM, 0},
- { "m_sig_cd", VN_MS_CD, 0}, /* 195 */
- { "m_sig_cts", VN_MS_CTS,0}, /* 195 */
- { "m_sig_dsr", VN_MS_DSR,0}, /* 195 */
- { "m_sig_dtr", VN_MS_DTR,0}, /* 195 */
- { "m_sig_ri", VN_MS_RI, 0}, /* 195 */
- { "m_sig_rts", VN_MS_RTS,0}, /* 195 */
- { "m_tone", VN_M_TDM, 0},
- #endif /* NODIAL */
- { "name", VN_NAME, 0},
- { "ndate", VN_NDAT, 0},
- { "nday", VN_NDAY, 0},
- { "newline", VN_NEWL, 0},
- { "nmonth", VN_NMONTH,0}, /* 304 */
- { "ntime", VN_NTIM, 0},
- { "osname", VN_OSNAM, 0}, /* 193 */
- { "osrelease", VN_OSREL, 0}, /* 193 */
- { "osversion", VN_OSVER, 0}, /* 193 */
- #ifndef NOXFER
- { "packetlen", VN_RPSIZ, 0}, /* 192 */
- #endif /* NOXFER */
- { "parity", VN_PRTY, 0}, /* 190 */
- { "password", VN_PWD, CM_INV}, /* 192 */
- #ifdef NT
- { "personal", VN_PERSONAL, 0}, /* 201 */
- #endif /* NT */
- #ifdef PEXITSTAT
- { "pexitstat", VN_PEXIT, 0}, /* 193 */
- #endif /* PEXITSTAT */
- #ifdef CK_PID
- { "pid", VN_PID, 0}, /* 193 */
- #endif /* CK_PID */
- { "platform", VN_SYSV, 0},
- { "printer", VN_PRINT, 0}, /* 193 */
- { "program", VN_PROG, 0},
- { "prompt", VN_PRM, CM_INV}, /* 192 */
- #ifndef NOXFER
- { "protocol", VN_PROTO, 0}, /* 192 */
- { "p_8bit", VN_P_8BIT,0}, /* 193 */
- { "p_ctl", VN_P_CTL, 0}, /* 193 */
- { "p_rpt", VN_P_RPT, 0}, /* 193 */
- { "query", VN_QUE, 0}, /* 190 */
- #endif /* NOXFER */
- { "remoteip", VN_HOSTIP,0}, /* 212 */
- { "return", VN_RET, 0},
- #ifdef CK_REXX
- { "rexx", VN_REXX, 0}, /* 190 */
- #endif /* CK_REXX */
- #ifdef TN_COMPORT
- { "rfc2217_signature", VN_TNC_SIG, 0}, /* 201 */
- { "rfc2717_signature", VN_TNC_SIG, CM_INV}, /* 202 */
- #endif /* TN_COMPORT */
- { "rows", VN_ROWS, 0}, /* 190 */
- #ifndef NOSEXP
- { "sdepth", VN_LSEXP,0}, /* 199 */
- #endif /* NOSEXP */
- { "secure", VN_SECURE, 0}, /* 199 */
- #ifndef NOLOCAL
- #ifdef OS2
- { "select", VN_SELCT, 0}, /* 192 */
- #endif /* OS2 */
- #endif /* NOLOCAL */
- { "sendlist", VN_SNDL, 0},
- { "serial", VN_SERIAL,0}, /* 195 */
- { "setlinemsg",VN_SLMSG, 0}, /* 195 */
- #ifndef NOSEXP
- { "sexpression",VN_SEXP, 0}, /* 199 */
- #endif /* NOSEXP */
- { "speed", VN_SPEE, 0},
- #ifdef OS2
- { "space", VN_SPA, 0},
- { "startup", VN_STAR, 0}, /* 190 */
- #else
- #ifdef UNIX
- { "startup", VN_STAR, 0}, /* 193 */
- #else
- #ifdef VMS
- { "startup", VN_STAR, 0}, /* 193 */
- #endif /* VMS */
- #endif /* UNIX */
- #endif /* OS2 */
- { "status", VN_SUCC, 0},
- #ifndef NOSEXP
- { "svalue", VN_VSEXP, 0}, /* 199 */
- #endif /* NOSEXP */
- #ifndef NOXFER
- { "sysid", VN_SYSI, 0},
- #endif /* NOXFER */
- { "system", VN_SYST, 0},
- { "terminal", VN_TTYP, 0},
- #ifdef OS2
- #ifndef NOKVERBS
- { "termkey", VN_TRMK, CM_INV}, /* 192 */
- #endif /* NOKVERBS */
- #endif /* OS2 */
- { "test", VN_TEST, 0}, /* 193 */
- { "textdir", VN_TXTDIR,0}, /* 195 */
- #ifndef NOXFER
- { "tfsize", VN_TFC, 0},
- { "tftime", VN_TFTIM, 0}, /* 195 */
- #endif /* NOXFER */
- { "time", VN_TIME, 0},
- { "timestamp", VN_NOW, 0}, /* 200 */
- { "tmpdir", VN_TEMP, 0}, /* 192 */
- #ifdef CK_TRIGGER
- { "trigger", VN_TRIG, 0}, /* 193 */
- #endif /* CK_TRIGGER */
- #ifdef CK_TTYFD
- { "ttyfd", VN_TTYF, 0},
- #endif /* CK_TTYFD */
- { "ty_ln", VN_TY_LN, 0}, /* 195 */
- { "ty_lc", VN_TY_LC, 0}, /* 195 */
- { "ty_lm", VN_TY_LM, 0}, /* 195 */
- #ifdef BROWSER
- { "url", VN_URL, CM_INV}, /* 193 */
- #endif /* BROWSER */
- { "userid", VN_UID, 0}, /* 192 */
- { "vareval", VN_VAREVAL, 0}, /* 212 */
- { "version", VN_VERS, 0},
- #ifndef NOXFER
- { "window", VN_WINDO, 0}, /* 192 */
- #endif /* NOXFER */
- #ifdef IBMX25
- { "x25local_nua", VN_X25LA, 0}, /* 193 */
- { "x25remote_nua", VN_X25RA, 0}, /* 193 */
- #endif /* IBMX25 */
- #ifdef CK_SSL
- { "x509_issuer", VN_X509_I, 0},
- { "x509_subject", VN_X509_S, 0},
- #endif /* CK_SSL */
- #ifndef NOXFER
- { "xferstatus",VN_XFSTAT,0}, /* 193 */
- { "xfermsg", VN_XFMSG, 0}, /* 193 */
- { "xfer_badpackets", VN_XF_BC, 0}, /* 195 */
- { "xfer_timeouts", VN_XF_TM, 0}, /* 195 */
- { "xfer_retransmits",VN_XF_RX, 0}, /* 195 */
- #endif /* NOXFER */
- { "xprogram", VN_XPROG, 0}, /* 193 */
- { "xversion", VN_XVNUM, 0}, /* 192 */
- { "year", VN_YEAR, 0} /* 304 */
- };
- int nvars = (sizeof(vartab) / sizeof(struct keytab));
- #endif /* NOSPL */
- #ifndef NOSPL
- struct keytab fnctab[] = { /* Function names */
- #ifdef OS2
- { ".oox", FN_OOX, CM_INV}, /* ... */
- #endif /* OS2 */
- #ifdef CKCHANNELIO
- { "_eof", FN_FEOF, 0},
- { "_errmsg", FN_FERMSG, 0},
- { "_getblock", FN_FGBLK, 0},
- { "_getchar", FN_FGCHAR, 0},
- { "_getline", FN_FGLINE, 0},
- { "_handle", FN_FILNO, 0},
- { "_line", FN_NLINE, 0},
- { "_pos", FN_FPOS, 0},
- { "_putblock", FN_FPBLK, 0},
- { "_putchar", FN_FPCHAR, 0},
- { "_putline", FN_FPLINE, 0},
- { "_status", FN_FSTAT, 0},
- #endif /* CKCHANNELIO */
- { "aaconvert", FN_AADUMP, 0}, /* Associative Array conversion */
- { "absolute", FN_ABS, 0}, /* Absolute value */
- #ifdef TCPSOCKET
- { "addr2name", FN_HSTADD,CM_INV}, /* IP Address to Hostname */
- { "addrtoname", FN_HSTADD,CM_INV}, /* IP Address to Hostname */
- #endif /* TCPSOCKET */
- { "arraylook", FN_ALOOK,0}, /* Array lookup */
- { "b64decode", FN_FMB64,0}, /* Base-64 conversion */
- { "b64encode", FN_TOB64,0}, /* ... */
- { "basename", FN_BSN, 0}, /* Basename */
- { "break", FN_BRK, 0}, /* Break (as in Snobol) */
- { "ca", FN_CAP, CM_INV|CM_ABR}, /* Abbreviation for capitablize */
- { "cap", FN_CAP, CM_INV|CM_ABR}, /* Abbreviation for capitablize */
- { "capitalize", FN_CAP, 0}, /* First Letter -> uppercase */
- { "caps", FN_CAP, CM_INV}, /* ditto */
- { "character", FN_CHR, 0}, /* Character from code */
- { "checksum", FN_CHK, 0}, /* Checksum */
- { "cmdstack", FN_CMDSTK,0}, /* Command stack */
- { "cmpdates", FN_CMPDATE,0}, /* Compare dates */
- { "code", FN_COD, 0}, /* Code from character */
- #ifndef NOPUSH
- { "command", FN_CMD, 0}, /* Output from a command */
- #endif /* NOPUSH */
- { "contents", FN_CON, 0}, /* Definition (contents) of variable */
- { "count", FN_COUNT, 0}, /* Occurrences of string in string */
- { "crc16", FN_CRC, 0}, /* CRC-16 */
- #ifdef OS2
- { "crypt", FN_CRY, CM_INV},
- #endif /* OS2 */
- { "cvtcset", FN_XLATE, 0}, /* Convert character set */
- { "cvtdate", FN_DTIM, 0}, /* Convert free date/time to std */
- #ifdef ZFCDAT
- { "date", FN_FD, 0}, /* File modification/creation date */
- #endif /* ZFCDAT */
- { "day", FN_DAY, 0}, /* Day of week */
- { "dayname", FN_DAYNAME,0}, /* Name of day of week */
- { "dayofyear", FN_JDATE, 0}, /* Date to Day of Year */
- { "decodehex", FN_UNPCT, 0}, /* Decode string with hex escapes */
- { "definition", FN_DEF, 0}, /* Return definition of given macro */
- { "delta2secs", FN_DELSEC, 0}, /* Delta time to seconds */
- { "deltatosecs", FN_DELSEC, CM_INV}, /* Delta time to seconds */
- #ifndef NODIAL
- { "dialconvert",FN_PNCVT,0}, /* Convert portable phone number */
- #endif /* NODIAL */
- { "diffdates", FN_DIFDATE,0}, /* Difference of two date-times */
- { "dimension", FN_DIM, 0}, /* Dimension of array */
- { "dir", FN_DIR, CM_INV|CM_ABR}, /* Abbreviation for direct.. */
- { "dire", FN_DIR, CM_INV|CM_ABR}, /* Abbreviation for direct.. */
- { "direc", FN_DIR, CM_INV|CM_ABR}, /* Abbreviation for direct.. */
- { "direct", FN_DIR, CM_INV|CM_ABR}, /* Abbreviation for direct.. */
- { "directo", FN_DIR, CM_INV|CM_ABR}, /* Abbreviation for direct.. */
- { "director", FN_DIR, CM_INV|CM_ABR}, /* Abbreviation for direct.. */
- { "directories",FN_DIR, 0}, /* List of directories */
- { "directory", FN_DIR, CM_INV}, /* List of directories */
- { "dirname", FN_DNAM, 0}, /* Directory part of filename */
- { "dos2unixpath",FN_PC_DU, CM_INV}, /* DOS to UNIX path */
- { "dostounixpath",FN_PC_DU, 0}, /* DOS to UNIX path */
- { "doy", FN_JDATE,CM_INV}, /* Date to Day of Year */
- { "doy2date", FN_DATEJ,0}, /* Day of Year to date */
- { "doytodate", FN_DATEJ,CM_INV}, /* Day of Year to date */
- { "emailaddress",FN_EMAIL, 0}, /* Email address */
- #ifdef FN_ERRMSG
- { "errstring", FN_ERRMSG,0}, /* Error code to message */
- #endif /* FN_ERRMSG */
- { "evaluate", FN_EVA, 0}, /* Evaluate given arith expression */
- { "execute", FN_EXE, 0}, /* Execute given macro */
- { "filecompare",FN_FILECMP, 0}, /* File compare */
- { "fileinfo", FN_FILEINF, 0}, /* File information */
- { "files", FN_FC, 0}, /* File count */
- #ifdef FNFLOAT
- { "fpabsolute", FN_FPABS, 0}, /* Floating-point absolute value */
- { "fpadd", FN_FPADD, 0}, /* FP add */
- { "fpcosine", FN_FPCOS, 0}, /* FP cosine */
- { "fpdivide", FN_FPDIV, 0}, /* FP divide */
- { "fpexp", FN_FPEXP, 0}, /* FP e to the x */
- { "fpint", FN_FPINT, 0}, /* FP to integer */
- { "fplog10", FN_FPLOG, 0}, /* FP base-10 logarithm */
- { "fplogn", FN_FPLN, 0}, /* FP natural logarithm */
- { "fpmaximum", FN_FPMAX, 0}, /* FP maxinum */
- { "fpminimum", FN_FPMIN, 0}, /* FP mininum */
- { "fpmodulus", FN_FPMOD, 0}, /* FP modulus */
- { "fpmultiply", FN_FPMUL, 0}, /* FP multiply */
- { "fpraise", FN_FPPOW, 0}, /* FP raise to a power */
- { "fpround", FN_FPROU, 0}, /* FP round */
- { "fpsine", FN_FPSIN, 0}, /* FP sine */
- { "fpsqrt", FN_FPSQR, 0}, /* FP square root */
- { "fpsubtract", FN_FPSUB, 0}, /* FP subtract */
- { "fptangent", FN_FPTAN, 0}, /* FP tangent */
- #endif /* FNFLOAT */
- { "function", FN_FUNC, 0 }, /* Test for existence of a function */
- { "getpidinfo", FN_PID, CM_INV }, /* Get PID info (synonym for pidnfo) */
- { "hex2ip", FN_HEX2IP,0}, /* Hex to IP address */
- { "hextoip", FN_HEX2IP,CM_INV}, /* Hex to IP address */
- { "hex2n", FN_HEX2N, CM_INV}, /* Hex to decimal number */
- { "hexify", FN_HEX, 0}, /* Hexify (string) */
- { "index", FN_IND, 0}, /* Index (string search) */
- { "ip2hex", FN_IP2HEX,0}, /* IP address to hex */
- { "iptohex", FN_IP2HEX,CM_INV}, /* IP address to hex */
- { "ipaddress", FN_IPA, 0}, /* Find and return IP address */
- { "jdate", FN_JDATE, CM_INV}, /* Date to Day of Year */
- { "join", FN_JOIN, 0}, /* Join array elements */
- { "keywordvalue", FN_KWVAL, 0}, /* Keyword=Value */
- #ifdef CK_KERBEROS
- { "krbflags", FN_KRB_FG, 0}, /* Kerberos functions */
- { "krbisvalid", FN_KRB_IV, 0},
- { "krbnextticket", FN_KRB_NX, 0},
- { "krbtickets", FN_KRB_TK, 0},
- { "krbtimeleft", FN_KRB_TT, 0},
- #endif /* CK_KERBEROS */
- { "kwvalue", FN_KWVAL, CM_INV}, /* Keyword=Value */
- { "left", FN_LEF, 0}, /* Leftmost n characters of string */
- { "length", FN_LEN, 0}, /* Return length of argument */
- { "literal", FN_LIT, 0}, /* Return argument literally */
- #ifdef NT
- { "longpathname",FN_LNAME,0}, /* GetLongPathName() */
- #else
- { "longpathname",FN_FFN,CM_INV},
- #endif /* NT */
- { "lop", FN_STL, 0}, /* Lop */
- { "lopx", FN_LOPX, 0}, /* Lopx */
- { "lower", FN_LOW, 0}, /* Return lowercased argument */
- { "lpad", FN_LPA, 0}, /* Return left-padded argument */
- { "ltrim", FN_LTR, 0}, /* Left-Trim */
- { "maximum", FN_MAX, 0}, /* Return maximum of two arguments */
- { "minimum", FN_MIN, 0}, /* Return minimum of two arguments */
- { "mjd", FN_MJD, 0}, /* Date to Modified Julian Date */
- { "mjd2date", FN_MJD2, CM_INV}, /* MJD to Date */
- { "mjdtodate", FN_MJD2, 0}, /* MJD to Date */
- { "modulus", FN_MOD, 0}, /* Return modulus of two arguments */
- { "monthname", FN_MONNAME,0}, /* Name of month of year */
- #ifdef COMMENT
- { "msleep", FN_MSLEEP,0}, /* Sleep for n milliseconds */
- #endif /* COMMENT */
- { "n2hex", FN_2HEX, CM_INV}, /* Number to hex */
- { "n2octal", FN_2OCT, CM_INV}, /* Number to octal */
- { "n2time", FN_N2TIM,0}, /* Number to hh:mm:ss */
- #ifdef TCPSOCKET
- { "name2addr", FN_HSTNAM,CM_INV}, /* Hostname to IP Address */
- #endif /* TCPSOCKET */
- { "nday", FN_NDAY, 0}, /* Numeric day of week */
- { "nextfile", FN_FIL, 0}, /* Next file in list */
- { "ntime", FN_NTIM, 0}, /* Time to seconds since midnight */
- { "ntohex", FN_2HEX, CM_INV}, /* Number to hex */
- { "ntooctal", FN_2OCT, CM_INV}, /* Number to octal */
- { "ntotime", FN_N2TIM,CM_INV}, /* Number to hh:mm:ss */
- { "oct2n", FN_OCT2N,CM_INV}, /* Octal to decimal number */
- { "octton", FN_OCT2N,CM_INV}, /* Octal to decimal number */
- { "pathname", FN_FFN, 0}, /* Full file name */
- { "pattern", FN_PATTERN, 0}, /* Pattern (for INPUT) */
- #ifdef CK_PERMS
- { "permissions",FN_PERM, 0}, /* Permissions of file */
- #else
- { "permissions",FN_PERM, CM_INV}, /* Permissions of file */
- #endif /* CK_PERMS */
- #ifdef SEEK_CUR
- { "pictureinfo",FN_PICTURE, 0 }, /* Picture orientation/dimensions */
- #endif /* SEEK_CUR */
- { "pidinfo", FN_PID, 0 }, /* Get PID info */
- { "radix", FN_RADIX, 0 }, /* Radix conversion */
- #ifndef NORANDOM
- { "random", FN_RAND, 0}, /* Random number */
- #endif /* NORANDOM */
- #ifndef NOPUSH
- { "rawcommand", FN_RAW, 0}, /* Output from a command (raw) */
- #endif /* NOPUSH */
- #ifdef RECURSIVE
- { "rdirectories", FN_RDIR, 0}, /* Recursive directory list */
- #endif /* RECURSIVE */
- { "recurse", FN_RECURSE, 0}, /* Recursive variable evaluation */
- #ifdef RECURSIVE
- { "rfiles", FN_RFIL, 0}, /* Recursive file list */
- #endif /* RECURSIVE */
- { "rep", FN_REP, CM_INV|CM_ABR},
- { "repeat", FN_REP, 0}, /* Repeat argument given # of times */
- { "replace", FN_RPL, 0}, /* Replace characters in string */
- { "reverse", FN_REV, 0}, /* Reverse the argument string */
- { "right", FN_RIG, 0}, /* Rightmost n characters of string */
- { "rindex", FN_RIX, 0}, /* Right index */
- { "rpad", FN_RPA, 0}, /* Right-pad the argument */
- { "rsearch", FN_RSEARCH, 0}, /* R-L Search for pattern in string */
- #ifdef OS2
- { "scrncurx", FN_SCRN_CX, 0}, /* Screen Cursor X Pos */
- { "scrncury", FN_SCRN_CY, 0}, /* Screen Cursor Y Pos */
- { "scrnstr", FN_SCRN_STR, 0}, /* Screen String */
- #endif /* OS2 */
- { "search", FN_SEARCH, 0}, /* L-R Search for pattern in string */
- #ifndef NOSEXP
- { "sexpression",FN_SEXP, 0}, /* S-Expression */
- #endif /* NOSEXP */
- #ifdef NT
- { "shortpathname",FN_SNAME,0}, /* GetShortPathName() */
- #else
- { "shortpathname",FN_FFN,CM_INV},
- #endif /* NT */
- { "size", FN_FS, 0}, /* File size */
- #ifdef COMMENT
- { "sleep", FN_SLEEP,0}, /* Sleep for n seconds */
- #endif /* COMMENT */
- { "span", FN_SPN, 0}, /* Span - like Snobol */
- { "split", FN_SPLIT,0}, /* Split string into words */
- { "squeeze", FN_SQUEEZE,0}, /* Squeeze whitespace in string */
- { "strcmp", FN_STRCMP,0}, /* String comparison */
- { "stringtype", FN_STRINGT,0}, /* String type (7-bit, 8-bit, UTF-8) */
- { "stripb", FN_STB, 0}, /* Strip enclosing braces/brackets */
- { "stripn", FN_STN, 0}, /* Strip n chars */
- { "stripx", FN_STX, 0}, /* Strip suffix */
- { "su", FN_SUB, CM_INV|CM_ABR},
- { "sub", FN_SUB, CM_INV|CM_ABR},
- { "subs", FN_SUB, CM_INV|CM_ABR},
- { "subst", FN_SUB, CM_INV|CM_ABR},
- { "substitute", FN_SUBST,0}, /* Substitute chars */
- { "substring", FN_SUB, 0}, /* Extract substring from argument */
- { "tablelook", FN_TLOOK,0}, /* Table lookup */
- { "time", FN_TIME, 0}, /* Free-format time to hh:mm:ss */
- { "tod2secs", FN_NTIM, CM_INV}, /* Time-of-day-to-secs-since-midnite */
- { "todtosecs", FN_NTIM, CM_INV}, /* Time-of-day-to-secs-since-midnite */
- { "trim", FN_TRM, 0}, /* Trim */
- { "unhexify", FN_UNH, 0}, /* Unhexify */
- { "unix2dospath",FN_PC_UD, CM_INV}, /* UNIX to DOS path */
- { "unixtodospath",FN_PC_UD, 0}, /* UNIX to DOS path */
- { "untabify", FN_UNTAB,0}, /* Untabify */
- { "upper", FN_UPP, 0}, /* Return uppercased argument */
- { "utcdate", FN_TOGMT,0}, /* Date-time to UTC (GMT) */
- { "verify", FN_VER, 0}, /* Verify */
- { "word", FN_WORD, 0}, /* Extract a word */
- { "", 0, 0}
- };
- int nfuncs = (sizeof(fnctab) / sizeof(struct keytab)) - 1;
- #endif /* NOSPL */
- #ifndef NOSPL /* Buffer for expansion of */
- #ifdef BIGBUFOK /* built-in variables. */
- #define VVBUFL 1024
- #else
- #define VVBUFL 256
- #endif /* BIGBUFOK */
- char vvbuf[VVBUFL+1];
- #endif /* NOSPL */
- struct keytab disptb[] = { /* Log file disposition */
- { "append", 1, 0},
- { "new", 0, 0}
- };
- #ifdef CKFLOAT
- /* I N I T F L O A T -- Deduce floating-point precision by inspection */
- #ifdef COMMENT
- /* For looking at internal floating-point representations */
- static char fp_xbuf[128];
- static char *
- tohex(s, n) CHAR * s; int n; {
- int x;
- char * p = fp_xbuf;
- while (n-- > 0) {
- x = (*s >> 4) & 0x0f;
- *p++ = hexdigits[x];
- x = *s++ & 0x0f;
- *p++ = hexdigits[x];
- }
- *p = NUL;
- return((char *)fp_xbuf);
- }
- #endif /* COMMENT */
- char math_pi[] = "3.1415926535897932384626433832795";
- char math_e[] = "2.7182818284590452353602874713527";
- VOID
- initfloat() {
- char * buf = NULL;
- int i, x, y;
- /*
- We malloc a big temporary buffer for sprintf() to minimize likelihood of
- (and damage from) sprintf buffer overflows. In any case, the only way this
- could happen would be if sprintf() itself had bugs, since the format
- descriptor says to cut it off at 250 decimal places.
- */
- if ((buf = (char *)malloc(4096))) {
- sprintf(buf,"%0.250f",(10.0 / 3.0));
- for (i = 2; i < 250 && buf[i] == '3'; i++) ;
- x = i - 1;
- debug(F111,"initfloat 10.0/3.0",buf,x);
- sprintf(buf,"%0.250f",(4.0 / 9.0));
- for (i = 2; i < 250 && buf[i] == '4'; i++) ;
- y = i - 1;
- debug(F111,"initfloat 4.0/9.0",buf,y);
- fp_digits = (x < y) ? x : y;
- if (fp_digits < sizeof(math_pi) - 1) {
- math_pi[fp_digits+1] = NUL;
- math_e[fp_digits+1] = NUL;
- }
- sprintf(buf,"%0.6f",(7.0 / 9.0));
- if (buf[7] == '8') fp_rounding = 1;
- debug(F111,"initfloat 7.0/9.0",buf,fp_rounding);
- debug(F101,"initfloat precision","",fp_digits);
- free(buf);
- }
- }
- #endif /* CKFLOAT */
- /*
- P R E S C A N -- A quick look through the command-line options for
- items that must be handled before the initialization file is executed.
- */
- #ifdef NT
- extern int StartedFromDialer;
- #endif /* NT */
- #ifdef OS2
- extern int k95stdio;
- unsigned long startflags = 0L;
- #endif /* OS2 */
- static char *
- findinpath(arg) char * arg; {
- #ifdef OS2
- char * scriptenv, * keymapenv;
- int len;
- #endif /* OS2 */
- #ifdef DCMDBUF
- extern char * cmdbuf;
- #else
- extern char cmdbuf[];
- #endif /* DCMDBUF */
- char takepath[4096];
- char * s;
- int x, z;
- /* Set up search path... */
- #ifdef OS2
- char * appdata0 = NULL, *appdata1 = NULL;
- #ifdef NT
- scriptenv = getenv("K95SCRIPTS");
- keymapenv = getenv("K95KEYMAPS");
- makestr(&appdata0,(char *)GetAppData(0));
- makestr(&appdata1,(char *)GetAppData(1));
- #else /* NT */
- scriptenv = getenv("K2SCRIPTS");
- keymapenv = getenv("K2KEYMAPS");
- #endif /* NT */
- if (!scriptenv)
- scriptenv = getenv("CK_SCRIPTS");
- if (!scriptenv)
- scriptenv = "";
- if (!keymapenv)
- keymapenv = getenv("CK_KEYMAPS");
- if (!keymapenv)
- keymapenv = "";
- debug(F110,"startupdir",startupdir,0);
- debug(F110,"common appdata directory",appdata1,0);
- debug(F110,"appdata directory",appdata0,0);
- debug(F110,"inidir",inidir,0);
- debug(F110,"home",zhome(),0);
- debug(F110,"exedir",exedir,0);
- len = strlen(scriptenv) + strlen(keymapenv) + 3*strlen(startupdir)
- + 3*strlen(inidir) + 3*strlen(zhome()) + 3*strlen(exedir)
- + (appdata0 ? 3*strlen(appdata0) : 0)
- + (appdata1 ? 3*strlen(appdata1) : 0)
- + 6*strlen("SCRIPTS/") + 6*strlen("KEYMAPS/") + 16;
- if (len >= 4096) { /* SAFE (length is checked) */
- takepath[0] = '\0';
- debug(F111,"findinpath error - path length too long","len",len);
- } else
- sprintf(takepath,
- /* semicolon-separated path list */
- "%s%s%s%s%s;%s%s;%s%s;%s%s%s%s%s%s%s%s%s%s%s%s%s;%s%s;%s%s;%s;%s%s;%s%s",
- scriptenv,
- (scriptenv[0] && scriptenv[strlen(scriptenv)-1]==';')?"":";",
- keymapenv,
- (keymapenv[0] && keymapenv[strlen(keymapenv)-1]==';')?"":";",
- startupdir,
- startupdir, "SCRIPTS/",
- startupdir, "KEYMAPS/",
- appdata1 ? appdata1 : "",
- appdata1 ? "Kermit 95;" : "",
- appdata1 ? appdata1 : "",
- appdata1 ? "Kermit 95/SCRIPTS/;" : "",
- appdata1 ? appdata1 : "",
- appdata1 ? "Kermit 95/KEYMAPS/;" : "",
- appdata0 ? appdata0 : "",
- appdata0 ? "Kermit 95;" : "",
- appdata0 ? appdata0 : "",
- appdata0 ? "Kermit 95/SCRIPTS/;" : "",
- appdata0 ? appdata0 : "",
- appdata0 ? "Kermit 95/KEYMAPS/;" : "",
- inidir,
- inidir, "SCRIPTS/",
- inidir, "KEYMAPS/",
- zhome(),
- zhome(), "SCRIPTS/",
- zhome(), "KEYMAPS/",
- exedir,
- exedir, "SCRIPTS/",
- exedir, "KEYMAPS/"
- );
- debug(F110,"findinpath takepath",takepath,0);
- #ifdef NT
- makestr(&appdata0,NULL);
- makestr(&appdata1,NULL);
- #endif /* NT */
- #else /* not OS2 */
- #ifndef NOSPL
- z = 1024; /* Look in home directory */
- s = takepath;
- zzstring("\\v(home)",&s,&z);
- #else
- takepath[0] = '\0';
- #endif /* NOSPL */
- #endif /* OS2 */
- /*
- All the logic for searching the take path is in the command parser.
- So even though we aren't parsing commands, we initialize and call the
- parser from here, with the purported filename stuffed into the command
- buffer, followed by some carriage returns to make the parser return.
- If the file is not found, or otherwise not accessible, the parser prints
- an appropriate message, and then we just exit.
- */
- cmdini(); /* Allocate command buffers etc */
- cmini(0); /* Initialize them */
- /* Stuff filename into command buf with braces in case of spaces */
- ckmakmsg(cmdbuf,CMDBL,"{",arg,"}",NULL);
- debug(F110,"findinpath cmdbuf",cmdbuf,0);
- ckstrncat(cmdbuf,"\r\r",CMDBL); /* And some carriage returns */
- if (cmifip("","",&s,&x,0,takepath,xxstring) < 0)
- return(NULL);
- cmres();
- return(s);
- }
- static int tr_int; /* Flag if TRANSMIT interrupted */
- #ifndef MAC
- SIGTYP
- #ifdef CK_ANSIC
- trtrap(int foo) /* TRANSMIT interrupt trap */
- #else
- trtrap(foo) int foo; /* TRANSMIT interrupt trap */
- #endif /* CK_ANSIC */
- /* trtrap */ {
- #ifdef __EMX__
- signal(SIGINT, SIG_ACK);
- #endif
- tr_int = 1; /* (Need arg for ANSI C) */
- SIGRETURN;
- }
- #endif /* MAC */
- #endif /* NOICP */
- #ifdef UNIX
- VOID
- getexedir() {
- extern char * xarg0;
- long xx;
- /*
- Unix provides no standard service for this. We look in argv[0], and if
- we're lucky there's a full pathname. If not we do a PATH search.
- */
- if (ckstrchr(xarg0,'/')) { /* Global copy of argv[0] */
- int i, k;
- char * p = NULL;
- if ((k = ckstrncpy(tmpbuf,xarg0,TMPBUFSIZ-2)) > 0) {
- p = tmpbuf;
- /* Convert to fully qualified pathname */
- if (tmpbuf[0]) if (tmpbuf[0] != '/') {
- line[0] = NUL;
- zfnqfp(tmpbuf,LINBUFSIZ-2,(char *)line);
- if (line[0])
- p = line;
- }
- xx = zchki(p);
- if (xx > -1) { /* Is the result an existing file? */
- k = strlen(p);
- for (i = k-1; i > 0; i--) { /* Yes, strip name part */
- if (p[i] == '/') {
- if (i < k-1)
- p[i+1] = NUL;
- break;
- }
- }
- }
- makestr(&exedir,p); /* Save the result */
- }
- }
- if (!exedir && xarg0) { /* Not found? */
- char * p;
- p = getenv("PATH"); /* Search the PATH */
- if (p) { /* If there is one... */
- char * q, * PATH = NULL;
- int k;
- makestr(&PATH,p); /* Pokeable copy of PATH string */
- if (PATH) { /* If malloc succeeded... */
- p = PATH;
- while (p && *p) { /* Loop through segments */
- q = ckstrchr(p,':'); /* End of this segment */
- if (q == p) { /* Null PATH segment */
- p++; /* Skip over colon */
- continue;
- }
- if (q) /* If not at end of PATH string */
- *q++ = NUL; /* zero out the colon */
- if ((k = ckstrncpy(tmpbuf,p,TMPBUFSIZ)) > 0) {
- if (tmpbuf[k-1] != '/') { /* Copy this PATH segment */
- tmpbuf[k++] = '/'; /* Append '/' if needed */
- tmpbuf[k] = NUL;
- }
- /* Append the argv[0] value */
- if (ckstrncpy(&tmpbuf[k],xarg0,TMPBUFSIZ) > 0) {
- if (zchki(tmpbuf) > -1) { /* File exists? */
- tmpbuf[k] = NUL; /* Yes, we're done */
- zfnqfp(tmpbuf,LINBUFSIZ,(char *)line);
- makestr(&exedir,line);
- break;
- }
- } else break;
- } else break;
- p = q; /* Not found, go to next segment */
- } /* while */
- free(PATH); /* Free PATH copy */
- }
- }
- if (!exedir) { /* Still nothing? */
- if (zchki(xarg0) > -1) { /* Maybe it's in the current dir */
- zfnqfp(zgtdir(),LINBUFSIZ,(char *)line);
- makestr(&exedir,line);
- }
- }
- }
- if (!exedir) { /* Still nothing? */
- makestr(&exedir,"/"); /* Fake it with with root. */
- }
- }
- #endif /* UNIX */
- int arg_x = 0;
- static int x_prescan = 0;
- /*
- The argument y once meant something but I can't imagine what so now
- it's ignored. (Prior to 22 Aug 98, prescan() was called twice by main(),
- and the arg differentiated the two calls. But this caused all sorts of
- problems & confusion, so I commented out the second call. This issue might
- need to be revisited.)
- */
- VOID
- prescan(dummy) int dummy; { /* Arg is ignored. */
- extern int howcalled;
- int yargc; char **yargv;
- char x;
- char *yp, *yy;
- #ifdef DEBUG
- int debcount = 0;
- #endif /* DEBUG */
- int z;
- if (x_prescan) /* Only run once */
- return;
- x_prescan = 1;
- yargc = xargc; /* Make copy of arg vector */
- yargv = xargv;
- #ifndef NOICP
- #ifdef DCMDBUF
- if (!kermrc)
- if (!(kermrc = (char *) malloc(KERMRCL+1)))
- fatal("prescan: no memory for kermrc");
- #endif /* DCMDBUF */
- ckstrncpy(kermrc,KERMRC,KERMRCL); /* Default init file name */
- #endif /* NOICP */
- #ifdef OS2
- yp = getenv("K95STARTFLAGS");
- if (yp) {
- startflags = atoi(yp);
- }
- #endif /* OS2 */
- #ifdef IKSD
- if (howcalled == I_AM_IKSD) /* Internet Kermit Service daemon */
- inserver = 1; /* (See inserver section of ckcmai) */
- #endif /* IKSD */
- /* Command line options for Kermit */
- #ifndef NOCMDL
- if (yargc > 1
- && *yargv[1] != '-'
- && (yargv[1][0] != '=')
- #ifdef KERBANG
- && (yargv[1][0] != '+')
- #endif /* KERBANG */
- #ifdef IKSD
- && (howcalled != I_AM_IKSD)
- #endif /* IKSD */
- ) { /* Filename as 1st argument */
- #ifndef NOICP
- char *s;
- #endif /* NOICP */
- #ifndef NOURL
- extern int haveurl;
- extern struct urldata g_url;
- if (urlparse(yargv[1],&g_url)) {
- if (!ckstrcmp(g_url.svc,"ftp",-1,0) ||
- !ckstrcmp(g_url.svc,"ftps",-1,0)) {
- haveurl = 1;
- howcalled = I_AM_FTP;
- } else if (!ckstrcmp(g_url.svc,"telnet",-1,0) ||
- !ckstrcmp(g_url.svc,"telnets",-1,0)) {
- haveurl = 1;
- howcalled = I_AM_TELNET;
- } else if (!ckstrcmp(g_url.svc,"ssh",-1,0)) {
- haveurl = 1;
- howcalled = I_AM_SSH;
- } else if (!ckstrcmp(g_url.svc,"iksd",-1,0) ||
- !ckstrcmp(g_url.svc,"kermit",-1,0)) {
- haveurl = 1;
- howcalled = I_AM_KERMIT;
- } else if (!ckstrcmp(g_url.svc,"http",-1,0) ||
- !ckstrcmp(g_url.svc,"https",-1,0)) {
- haveurl = 1;
- howcalled = I_AM_HTTP;
- }
- if (haveurl) {
- while (--yargc > 0) { /* Go through command-line args */
- yargv++; /* looking for -Y and -d */
- yp = *yargv+1;
- if (**yargv == '-') {
- x = *(*yargv+1);
- while (x) {
- switch (x) {
- #ifndef NOICP
- case '+':
- case '-':
- if (doxarg(yargv,1) < 0) {
- fatal("Extended argument error");
- }
- yp = "";
- break;
- #endif /* NOICP */
- case 'Y':
- noinit++;
- break;
- case 'q':
- quiet = 1;
- break;
- case 'h':
- noinit = 1;
- #ifdef OS2
- startflags |= 2; /* No network DLLs */
- startflags |= 4; /* No TAPI DLLs */
- startflags |= 8; /* No Security DLLs */
- startflags |= 16; /* No Zmodem DLLs */
- startflags |= 32; /* Stdin */
- startflags |= 64; /* Stdout */
- #endif /* OS2 */
- break;
- case 'd': /* = SET DEBUG ON */
- #ifdef DEBUG
- if (debcount++ > 0)
- debtim = 1;
- if (!deblog)
- deblog = debopn("debug.log",0);
- #endif /* DEBUG */
- break;
- #ifdef OS2
- case 'W':
- if (*(yp+1))
- fatal("invalid argument bundling after -W");
- yargv++, yargc--;
- if (yargc < 1)
- fatal("Window handle missing");
- hwndDialer = (HWND) atol(*yargv);
- StartedFromDialer = 1;
- yargv++, yargc--;
- KermitDialerID = atol(*yargv) ;
- break;
- case '#': /* K95 initialization options */
- if (*(yp+1)) {
- fatal("invalid argument bundling");
- }
- yargv++, yargc--;
- if (yargc < 1)
- fatal("-# argument missing");
- startflags |= atol(*yargv);
- break;
- #endif /* OS2 */
- }
- if (!yp)
- break;
- x = *++yp;
- }
- }
- }
- return;
- }
- }
- /* after this point non-Kermit personalities must return */
- switch (howcalled) {
- case I_AM_KERMIT:
- case I_AM_IKSD:
- case I_AM_SSHSUB:
- break;
- default:
- return;
- }
- #endif /* NOURL */
- #ifndef NOICP
- /* If it is not a URL that we recognize, try to treat it as a file */
- if (!isabsolute(yargv[1])) /* If not absolute */
- s = findinpath(yargv[1]); /* Look in PATH */
- else
- s = yargv[1];
- if (!s)
- doexit(BAD_EXIT,xitsta);
- zfnqfp(s,CKMAXPATH,cmdfil); /* In case of CD in file */
- yargc -= 1; /* Skip past the filename */
- yargv += 1; /* Otherwise we'll get an error */
- #endif /* NOICP */
- }
- #ifndef NOCMDL
- #ifdef NEWFTP
- if (howcalled == I_AM_FTP) { /* Kermit's FTP client personality */
- while (--yargc > 0) { /* Go through command-line args */
- yargv++; /* looking for -Y and -d */
- yp = *yargv+1;
- if (**yargv == '-') {
- x = *(*yargv+1);
- while (x) {
- switch (x) {
- #ifndef NOICP
- case '+':
- case '-':
- if (doxarg(yargv,1) < 0) {
- fatal("Extended argument error");
- }
- yp = "";
- break;
- #endif /* NOICP */
- case 'Y':
- noinit++;
- break;
- case 'q':
- quiet = 1;
- break;
- case 'h':
- noinit = 1;
- #ifdef OS2
- startflags |= 2; /* No network DLLs */
- startflags |= 4; /* No TAPI DLLs */
- startflags |= 8; /* No Security DLLs */
- startflags |= 16; /* No Zmodem DLLs */
- startflags |= 32; /* Stdin */
- startflags |= 64; /* Stdout */
- #endif /* OS2 */
- break;
- case 'd': /* = SET DEBUG ON */
- #ifdef DEBUG
- if (debcount++ > 0)
- debtim = 1;
- if (!deblog)
- deblog = debopn("debug.log",0);
- #endif /* DEBUG */
- break;
- #ifdef OS2
- case 'W':
- if (*(yp+1))
- fatal("invalid argument bundling after -W");
- yargv++, yargc--;
- if (yargc < 1)
- fatal("Window handle missing");
- hwndDialer = (HWND) atol(*yargv);
- StartedFromDialer = 1;
- yargv++, yargc--;
- KermitDialerID = atol(*yargv) ;
- break;
- case '#': /* K95 initialization options */
- if (*(yp+1)) {
- fatal("invalid argument bundling");
- }
- yargv++, yargc--;
- if (yargc < 1)
- fatal("-# argument missing");
- startflags |= atol(*yargv);
- break;
- #endif /* OS2 */
- }
- if (!yp)
- break;
- x = *++yp;
- }
- }
- }
- return;
- }
- #endif /* NEWFTP */
- #endif /* NOCMDL */
- while (--yargc > 0) { /* Go through command-line args */
- yargv++;
- yp = *yargv+1; /* Pointer for bundled args */
- if (**yargv == '=') /* Same rules as cmdlin()... */
- return;
- debug(F110,"prescan *yargv",*yargv,0);
- #ifndef NOICP
- #ifdef KERBANG
- yy = *yargv;
- if (!strcmp(yy,"+") || (*yy == '+' && *(yy+1) < (char)33)) {
- char * s;
- yargv++;
- noinit = 1;
- if (!*yargv)
- return;
- cfilef = 1;
- s = findinpath(*yargv);
- if (s) {
- zfnqfp(s,CKMAXPATH,cmdfil);
- return;
- } else
- doexit(BAD_EXIT,xitsta);
- }
- #endif /* KERBANG */
- #endif /* NOICP */
- if (!strcmp(*yargv,"--")) /* getopt() conformance */
- return;
- #ifdef VMS
- else if (**yargv == '/')
- continue;
- #endif /* VMS */
- else if (**yargv == '-') { /* Got an option (begins with dash) */
- x = *(*yargv+1); /* Get option letter */
- while (x) { /* Allow for bundled options */
- debug(F000,"prescan arg","",x);
- switch (x) {
- #ifndef NOICP
- case '+':
- case '-':
- if (doxarg(yargv,1) < 0) {
- fatal("Extended argument error");
- }
- #ifndef COMMENT /* Jeff 28 Apr 2003 */
- yp = NULL; /* (not "") */
- #else
- yargv++, yargc--;
- yp = *yargv;
- #endif /* COMMENT */
- break;
- #endif /* NOICP */
- case '7': /* Undocumented... */
- sstelnet = 1; /* (because it doesn't work) */
- break;
- #ifdef IKSD
- case 'A': {
- char * p;
- inserver = 1; /* Flag that we are doing this */
- srvcdmsg = 2; /* Preset this */
- /* See inserver section of ckcmai.c for more settings */
- #ifdef OS2
- if (*(yp+1)) {
- fatal("invalid argument bundling after -A");
- }
- #ifdef NT
- /* Support for Pragma Systems Telnet/Terminal Servers */
- p = getenv("PRAGMASYS_INETD_SOCK");
- if (p && atoi(p) != 0) {
- ttname[0] = '$';
- ckstrncpy(&ttname[1],p,TTNAMLEN-1);
- break;
- }
- #endif /* NT */
- yargv++, yargc--;
- if (yargc < 1 || **yargv == '-') {
- fatal("-A argument missing");
- } else {
- ttname[0] = '$';
- ckstrncpy(&ttname[1],*yargv,TTNAMLEN-1);
- }
- #endif /* OS2 */
- break;
- }
- #endif /* IKSD */
- #ifdef OS2
- case 'W':
- if (*(yp+1))
- fatal("invalid argument bundling after -W");
- yargv++, yargc--;
- if (yargc < 1)
- fatal("Window handle missing");
- #ifdef COMMENT
- if (dummy) {
- yargv++, yargc--;
- break;
- } else {
- #endif /* COMMENT */
- hwndDialer = (HWND) atol(*yargv);
- StartedFromDialer = 1;
- yargv++, yargc--;
- KermitDialerID = atol(*yargv) ;
- #ifdef COMMENT
- }
- #endif /* COMMENT */
- break;
- case '#': /* K95 initialization options */
- if (*(yp+1)) {
- fatal("invalid argument bundling");
- }
- yargv++, yargc--;
- if (yargc < 1)
- fatal("-# argument missing");
- startflags |= atol(*yargv);
- break;
- #endif /* OS2 */
- #ifndef NOSPL
- case 'M': /* My User Name */
- if (*(yp+1)) {
- fatal("invalid argument bundling");
- }
- yargv++, yargc--;
- if ((yargc < 1) || (**yargv == '-')) {
- fatal("missing username");
- }
- if ((int)strlen(*yargv) > UIDBUFLEN) {
- fatal("username too long");
- }
- #ifdef COMMENT
- /*
- This can't work. uidbuf is overwritten in sysinit() which has yet to be
- called. This cannot be set in prescan().
- */
- #ifdef IKSD
- if (!inserver)
- #endif /* IKSD */
- ckstrncpy(uidbuf,*yargv,UIDBUFLEN);
- #endif /* COMMENT */
- break;
- #endif /* NOSPL */
- case 'R': /* Remote-only advisory */
- #ifdef CK_IFRO
- remonly = 1;
- #endif /* CK_IFRO */
- break;
- case 'S': /* STAY */
- stayflg = 1;
- break;
- case 'h':
- noinit = 1;
- #ifdef OS2
- startflags |= 2; /* No network DLLs */
- startflags |= 4; /* No TAPI DLLs */
- startflags |= 8; /* No Security DLLs */
- startflags |= 16; /* No Zmodem DLLs */
- startflags |= 32; /* Stdin */
- startflags |= 64; /* Stdout */
- #endif /* OS2 */
- break;
- #ifndef NOICP
- case 'Y': /* No init file */
- noinit = 1;
- break;
- #endif /* NOICP */
- case 'q':
- quiet = 1;
- break;
- case 'd': /* = SET DEBUG ON */
- #ifdef DEBUG
- if (debcount++ > 0)
- debtim = 1;
- if (!deblog)
- deblog = debopn("debug.log",0);
- #endif /* DEBUG */
- break;
- case 'x': /* Server */
- arg_x = 1; /* Note in advance */
- break;
- #ifndef NOICP
- case 'y': /* Alternative init file */
- noinit = 0;
- yargv++, yargc--;
- if (yargc < 1) fatal("missing name in -y");
- /* Replace init file name */
- ckstrncpy(kermrc,*yargv,KERMRCL);
- rcflag = 1; /* Flag that this has been done */
- debug(F111,"prescan kermrc",kermrc,rcflag);
- break;
- #endif /* NOICP */
- case 'z': /* = SET BACKGROUND OFF */
- bgset = 0;
- backgrd = 0;
- #ifdef VMS
- batch = 0;
- #endif /* VMS */
- break;
- case 'B': /* Force background (batch) */
- bgset = 1;
- backgrd = 1;
- #ifdef VMS
- batch = 1;
- #endif /* VMS */
- break;
- #ifdef CK_NETBIOS
- case 'N':
- {
- int n ;
- yargv++, yargc--;
- #ifdef COMMENT
- if (y)
- break;
- #endif /* COMMENT */
- if (strlen(*yargv) != 1 || (*yargv)[0] == 'X') {
- NetBiosAdapter = -1;
- } else {
- n = atoi(*yargv);
- if (n >= 0 && n <= 9)
- NetBiosAdapter = n;
- else
- NetBiosAdapter = -1;
- }
- }
- break;
- #endif /* CK_NETBIOS */
- default:
- break;
- }
- if (!yp)
- break;
- x = *++yp; /* See if options are bundled */
- }
- }
- }
- #endif /* NOCMDL */
- }
- /* G E T T C S -- Get Transfer (Intermediate) Character Set */
- /*
- Given two file character sets, this routine picks out the appropriate
- "transfer" character set to use for translating between them.
- The transfer character set number is returned.
- At present this routine is somewhat overloaded. It's fine for file
- transfer because it does not assume the Kermit partner understands UTF8.
- However, for terminal emulation it *should* use UTF8 as the intermediate
- character set whenever possible so as not to lose characters it might
- have been able to display; for example on a terminal connection from
- the Linux console (UTF8) to a BBS that uses CP437 box-drawing characters.
- This is handled in the CONNECT command code in ckucns.c, which avoids
- calling this routine if the character-set on either end is UTF8.
- Translation between different Kanji character sets is not yet supported.
- */
- int
- gettcs(cs1,cs2) int cs1, cs2; {
- #ifdef NOCSETS /* No character-set support */
- return(0); /* so no translation */
- #else
- int tcs = TC_TRANSP;
- #ifdef KANJI
- /* Kanji not supported yet */
- if (fcsinfo[cs1].alphabet == AL_JAPAN ||
- fcsinfo[cs2].alphabet == AL_JAPAN )
- tcs = TC_TRANSP;
- else
- #endif /* KANJI */
- #ifdef CYRILLIC
- /*
- I can't remember why we don't test both sets here, but I think there
- must have been a reason...
- */
- if (fcsinfo[cs2].alphabet == AL_CYRIL)
- tcs = TC_CYRILL;
- else
- #endif /* CYRILLIC */
- #ifdef HEBREW
- if (fcsinfo[cs1].alphabet == AL_HEBREW ||
- fcsinfo[cs2].alphabet == AL_HEBREW )
- tcs = TC_HEBREW;
- else
- #endif /* HEBREW */
- #ifdef GREEK
- if (fcsinfo[cs1].alphabet == AL_GREEK ||
- fcsinfo[cs2].alphabet == AL_GREEK )
- tcs = TC_GREEK;
- else
- #endif /* GREEK */
- /* Roman sets ... */
- #ifdef LATIN2 /* East European */
- if (cs1 == FC_2LATIN || cs2 == FC_2LATIN || /* Latin-2 */
- cs1 == FC_CP852 || cs2 == FC_CP852 || /* CP852 */
- cs1 == FC_CP1250 || cs2 == FC_CP1250 || /* Windows Latin-2 */
- cs1 == FC_MAZOVIA || cs2 == FC_MAZOVIA) /* Polish Mazovia */
- tcs = TC_2LATIN;
- else
- #endif /* LATIN2 */
- /* West European Euro-aware */
- if (cs1 == FC_CP858 || cs1 == FC_9LATIN ||
- cs2 == FC_CP858 || cs2 == FC_9LATIN)
- tcs = TC_9LATIN;
- else /* Traditional West European */
- tcs = TC_1LATIN;
- return(tcs);
- #endif /* NOCSETS */
- }
- #ifndef NOLOCAL
- /* D O C O N E C T -- Do the connect command */
- /*
- q = 0 means issue normal informational message about how to get back, etc.
- q != 0 means to skip the message.
- */
- int
- doconect(q,async) int q, async; {
- int x; /* Return code */
- #ifdef CK_AUTODL
- extern CHAR ksbuf[];
- #endif /* CK_AUTODL */
- #ifndef NOKVERBS /* Keyboard macro material */
- extern int keymac, keymacx;
- #endif /* NOKVERBS */
- extern int justone, adl_err;
- int qsave; /* For remembering "quiet" value */
- #ifdef OS2
- extern int term_io;
- int term_io_save;
- #ifdef KUI
- extern int kui_async;
- #endif /* KUI */
- #endif /* OS2 */
- int is_tn = 0;
- #ifdef IKSD
- if (inserver) {
- if (!quiet)
- printf("\r\n?Sorry, IKSD cannot CONNECT.\r\n");
- return(success = 0);
- }
- #endif /* IKSD */
- is_tn =
- #ifdef TNCODE
- (local && network && IS_TELNET()) || (!local && sstelnet)
- #else
- 0
- #endif /* TNCODE */
- ;
- /*
- Saving, changing, and restoring the global "quiet" variable around calls
- to conect() to control whether the verbose CONNECT message is printed is
- obviously less elegant than passing a parameter to conect(), but we do it
- this way to avoid the need to change all of the ck?con.c modules. NOTE:
- it is important to restore the value immediately upon return in case there
- is an autodownload or APC.
- */
- qsave = quiet; /* Save it */
- if (!quiet && q > -1)
- quiet = q; /* Use argument temporarily */
- conres(); /* Put console back to normal */
- debug(F101,"doconect justone 1","",justone);
- #ifdef CK_AUTODL
- ksbuf[0] = NUL; /* Autodownload packet buffer */
- #endif /* CK_AUTODL */
- #ifdef OS2
- display_demo = 1; /* Remember to display demo */
- #endif /* OS2 */
- #ifdef IKS_OPTION
- if (is_tn && TELOPT_U(TELOPT_KERMIT) && ttchk() >= 0
- #ifdef OS2
- && !viewonly
- #endif /* OS2 */
- ) {
- /* If the remote side is in a state of IKS START-SERVER */
- /* we request that the state be changed. We will detect */
- /* a failure to adhere to the request when we call ttinc() */
- if (!iks_wait(KERMIT_REQ_STOP,0) && !tcp_incoming) {
- if (!quiet) {
- printf("\r\nEnter Client/Server Mode... Use:\r\n\r\n");
- printf(
- " REMOTE LOGIN <user> <password> to log in to the server if necessary.\r\n");
- printf(" SEND and GET for file transfer.\r\n");
- printf(" REMOTE commands for file management.\r\n");
- printf(" FINISH to terminate Client/Server mode.\r\n");
- printf(" BYE to terminate and close connection.\r\n");
- printf(" REMOTE HELP for additional information.\r\n\r\n");
- }
- quiet = qsave;
- return(0); /* Failure */
- }
- }
- /* Let our peer know our state. */
- #ifdef CK_AUTODL
- if (is_tn && TELOPT_ME(TELOPT_KERMIT)
- #ifdef OS2
- && !viewonly
- #endif /* OS2 */
- ) {
- if (autodl && !TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
- tn_siks(KERMIT_START); /* Send Kermit-Server Start */
- } else if (!autodl && TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
- tn_siks(KERMIT_STOP);
- }
- }
- #else /* CK_AUTODL */
- if (is_tn && TELOPT_ME(TELOPT_KERMIT) &&
- TELOPT_SB(TELOPT_KERMIT).kermit.me_start)
- tn_siks(KERMIT_STOP);
- #endif /* CK_AUTODL */
- #endif /* IKS_OPTION */
- debug(F101,"doconect flow","",flow);
- #ifdef OS2
- debug(F101,"doconect async","",async);
- #ifdef KUI
- if (kui_async)
- async = 1;;
- #endif /* KUI */
- x = conect(async); /* Connect the first time */
- #else /* OS2 */
- x = conect();
- #endif /* OS2 */
- debok = 1;
- #ifdef IKS_OPTION
- if (TELOPT_U(TELOPT_KERMIT) &&
- TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
- !tcp_incoming && !quiet && ttchk() >= 0
- ) {
- printf("\r\nEnter Client/Server Mode... Use:\r\n\r\n");
- printf(
- " REMOTE LOGIN <user> <password> to log in to the server if necessary.\r\n");
- printf(" SEND and GET for file transfer.\r\n");
- printf(" REMOTE commands for file management.\r\n");
- printf(" FINISH to terminate Client/Server mode.\r\n");
- printf(" BYE to terminate and close connection.\r\n");
- printf(" REMOTE HELP for additional information.\r\n\r\n");
- }
- #endif /* IKS_OPTION */
- quiet = qsave; /* Restore "quiet" value */
- debug(F101,"doconect justone 2","",justone);
- #ifdef NETCONN
- if (network && tn_exit && ttchk() < 0)
- doexit(GOOD_EXIT,xitsta); /* Exit with good status */
- #endif /* NETCONN */
- #ifdef OS2ORUNIX
- /* Exit on disconnect if the port is not open or carrier detect */
- if (exitonclose && (ttchk() < 0))
- doexit(GOOD_EXIT,xitsta);
- #endif /* OS2ORUNIX */
- #ifdef CKCONINTB4CB
- /* The order makes a difference in HP-UX 8.00. */
- /* The other order makes it think it's in the background when it */
- /* returns from CONNECT (Apr 1999). */
- setint();
- concb((char)escape); /* Restore console for commands */
- #else
- /* This is how it has always been so better leave it */
- /* this way for all non-HP-UX-8.00 builds. */
- concb((char)escape); /* Restore console for commands */
- setint();
- #endif /* CKCONINTB4CB */
- #ifdef OS2
- if (!async) {
- term_io_save = term_io; /* Disable I/O by emulator */
- term_io = 0;
- #endif /* OS2 */
- #ifdef CK_APC
- /*
- If an APC command was received during CONNECT mode, we define it now
- as a macro, execute the macro, and then return to CONNECT mode.
- We do this in a WHILE loop in case additional APCs come during subsequent
- CONNECT sessions.
- */
- debug(F101,"doconect apcactive","",apcactive);
- debug(F101,"doconect success","",success);
- while (x > 0 && (apcactive == APC_LOCAL ||
- (apcactive == APC_REMOTE && apcstatus != APC_OFF))) {
- debug(F101,"doconect justone 3","",justone);
- if (mlook(mactab,"_apc_commands",nmac) == -1) {
- debug(F110,"doconect about to execute APC",apcbuf,0);
- domac("_apc_commands",apcbuf,cmdstk[cmdlvl].ccflgs|CF_APC);
- delmac("_apc_commands",1);
- #ifdef DEBUG
- } else {
- debug(F100,"doconect APC in progress","",0);
- #endif /* DEBUG */
- }
- debug(F101,"doconect apcactive after domac","",apcactive);
- if (!apcactive) { /* In case CLEAR APC was in APC */
- debug(F101,"doconect quit APC loop: apcactive","",apcactive);
- break;
- }
- /* Also don't reconnect if autodownload failed - very confusing! */
- /* Let them view the local screen to see what happened. - fdc */
- /* This should be conditional. If someone is relying on the */
- /* connect mode autodownload for the kermit server to use with */
- /* a remotely executed script we should be able to return to */
- /* connect mode on the failure. What we really need to do is */
- /* report the status of the transfer and then return to CONNECT. */
- /* In unix this would simply be a printf(), but in K95 it could */
- /* use a popup dialog to report the status. - Jeff */
- #ifndef NOXFER
- debug(F101,"doconect xferstat","",xferstat);
- if (apcactive == APC_LOCAL && !xferstat && adl_err != 0) {
- debug(F101,"doconect quit APC loop: xferstat","",xferstat);
- apcactive = APC_INACTIVE;
- break;
- }
- #endif /* NOXFER */
- #ifdef OS2
- msleep(250);
- #endif /* OS2 */
- debug(F101,"doconect justone 4","",justone);
- qsave = quiet; /* Do this again... */
- if (!quiet && q > -1)
- quiet = q;
- #ifdef CK_AUTODL
- ksbuf[0] = NUL;
- #endif /* CK_AUTODL */
- #ifdef IKS_OPTION
- #ifdef CK_AUTODL
- if (is_tn &&
- TELOPT_ME(TELOPT_KERMIT) &&
- !TELOPT_SB(TELOPT_KERMIT).kermit.me_start &&
- autodl
- #ifdef CK_APC
- && !apcactive
- #endif /* CK_APC */
- #ifdef OS2
- && !viewonly
- #endif /* OS2 */
- ) {
- tn_siks(KERMIT_START); /* Send Kermit-Server Start */
- }
- #endif /* CK_AUTODL */
- #endif /* IKS_OPTION */
- #ifndef OS2
- x = conect(); /* Re-CONNECT. */
- #else /* OS2 */
- x = conect(0);
- term_io = term_io_save;
- #endif /* OS2 */
- debok = 1;
- quiet = qsave;
- debug(F101,"doconect justone 5","",justone);
- #ifdef NETCONN
- if (network && ttchk() < 0) {
- if (tn_exit || exitonclose)
- doexit(GOOD_EXIT,xitsta);
- else
- break;
- }
- #endif /* NETCONN */
- #ifdef OS2ORUNIX
- /* If connection dropped */
- if (ttchk() < 0) {
- concb((char)escape); /* Restore console. */
- if (exitonclose)
- doexit(GOOD_EXIT,xitsta);
- else
- break;
- }
- #endif /* OS2ORUNIX */
- } /* Loop back for more. */
- #endif /* CK_APC */
- #ifndef NOKVERBS
- if ((keymac > 0) && (keymacx > -1)) { /* Executing a keyboard macro? */
- /* Set up the macro and return */
- /* Do not clear the keymac flag */
- #ifdef OS2
- term_io = term_io_save;
- #endif /* OS2 */
- return(dodo(keymacx,NULL,CF_KMAC|cmdstk[cmdlvl].ccflgs));
- }
- #endif /* NOKVERBS */
- #ifdef OS2
- term_io = term_io_save;
- } /* if (!async) */
- #endif /* OS2 */
- #ifdef CKCONINTB4CB
- /* The order makes a difference in HP-UX 8.00. */
- /* The other order makes it think it's in the background when it */
- /* returns from CONNECT (Apr 1999). */
- setint();
- concb((char)escape); /* Restore console for commands */
- #else
- /* This is how it has always been so better leave it */
- /* this way for all non-HP-UX-8.00 builds. */
- concb((char)escape); /* Restore console for commands */
- setint();
- #endif /* CKCONINTB4CB */
- #ifdef OS2
- if (!async)
- #endif /* OS2 */
- what = W_COMMAND; /* Back in command mode. */
- return(x); /* Done. */
- }
- #endif /* NOLOCAL */
- #ifndef NOICP
- #ifdef COMMENT
- /*
- It seemed that this was needed for OS/2, in which \v(cmdfile) and other
- file-oriented variables or functions can return filenames containing
- backslashes, which are subsequently interpreted as quotes rather than
- directory separators (e.g. see commented section for VN_CMDF below).
- But the problem can't be cured at this level. Example:
- type \v(cmdfile)
- Without doubling, the filename is parsed correctly, but then when passed
- to UNIX 'cat' through the shell, the backslash is removed, and then cat
- can't open the file. With doubling, the filename is not parsed correctly
- and the TYPE command fails immediately with a "file not found" error.
- */
- /*
- Utility routine to double all backslashes in a string.
- s1 is pointer to source string, s2 is pointer to destination string,
- n is length of destination string, both NUL-terminated.
- Returns 0 if OK, -1 if not OK (destination string too short).
- */
- int
- dblbs(s1,s2,n) char *s1, *s2; int n; {
- int i = 0;
- while (*s1) {
- if (*s1 == '\\') {
- if (++i > n) return(-1);
- *s2++ = '\\';
- }
- if (++i > n) return(-1);
- *s2++ = *s1++;
- }
- *s2 = NUL;
- return(0);
- }
- #endif /* COMMENT */
- char *
- gmdmtyp() { /* Get modem type */
- #ifndef NODIAL
- int i, x;
- debug(F111,"gmdmtyp","mdmtyp",mdmtyp);
- debug(F111,"gmdmtyp","mdmsav",mdmsav);
- x = mdmtyp;
- if (x < 0) /* In case of network dialing */
- x = mdmsav;
- if (x < 1)
- return("none");
- else
- for (i = 0; i < nmdm; i++)
- if ((mdmtab[i].kwval == x) && (mdmtab[i].flgs == 0))
- return(mdmtab[i].kwd);
- #endif /* NODIAL */
- return("none");
- }
- #ifndef NOXMIT
- #ifndef NOLOCAL
- /* T R A N S M I T -- Raw upload */
- /* Obey current line, duplex, parity, flow, text/binary settings. */
- /* Returns 0 upon apparent success, 1 on obvious failure. */
- /***
- Things to add:
- . Make both text and binary mode obey set file bytesize.
- . Maybe allow user to specify terminators other than CR?
- . Maybe allow user to specify prompts other than single characters?
- . Make STATISTICS also work for TRANSMIT.
- . If TRANSMIT is done without echo, make some kind of (optional) display.
- . Make the same optimization for binary-mode transmit that was done for
- text-mode (in the no-echo / no-prompt / no-pause case).
- ***/
- /* T R A N S M I T -- Raw upload */
- /* s is the filename, t is the turnaround (prompt) character */
- /*
- Maximum number of characters to buffer.
- Must be less than LINBUFSIZ
- */
- #ifdef OS2
- #define XMBUFS 4096 /* For compatibility with XYZmodem */
- #else /* OS2 */
- #define XMBUFS 1024
- #endif /* OS2 */
- #ifdef TNCODE
- #ifndef IAC
- #define IAC 255
- #endif /* IAC */
- #endif /* TNCODE */
- #define OUTXBUFSIZ 15
- static CHAR inxbuf[OUTXBUFSIZ+1]; /* Host-to-screen expansion buffer */
- static int inxcount = 0; /* and count */
- static CHAR outxbuf[OUTXBUFSIZ+1]; /* Keyboard-to-host expansion buf */
- static int outxcount = 0; /* and count */
- /* T R A N S M I T -- Unguarded non-protocol file transmission */
- /*
- Call with:
- char * s: Name of file to transmit.
- char t: Turnaround char for text-mode transmission (normally LF).
- int xlate: nonzero = charset translation for text-mode xfer, 0 = skip.
- int binary: nonzero = transmit in binary mode, 0 = in text mode.
- */
- #define XBBUFSIZ 508 /* For binary blasting */
- static CHAR xbbuf[XBBUFSIZ+4];
- int
- #ifdef CK_ANSIC
- transmit(char * s, char t, int xlate, int binary, int xxecho)
- #else
- transmit(s,t,xlate,binary,xxecho) char *s; char t; int xlate, binary, xxecho;
- #endif /* CK_ANSIC */
- /* transmit */ {
- #ifdef MAC
- extern char sstate;
- int count = 100;
- #else
- int count = 0;
- #ifdef OS2
- #ifdef NT
- SIGTYP (* oldsig)(int); /* For saving old interrupt trap. */
- #else /* NT */
- SIGTYP (* volatile oldsig)(int);
- #endif /* NT */
- #else /* OS2 */
- SIGTYP (* oldsig)();
- #endif /* OS2 */
- #endif /* MAC */
- int eof = 0; /* End of File flag */
- int eol = 0; /* End of Line flag */
- int rc = 1; /* Return code. 0=fail, 1=succeed. */
- int myflow; /* Local copy of global flow... */
- int is_tn = 0; /* Do Telnet negotiations */
- int xbufsiz = XMBUFS; /* Size of TRANSMIT buffer */
- int x, y, c, i; /* Int workers... */
- int control = 0; /* Echo loop control */
- long nbytes = 0; /* File byte count */
- long zz; /* Long worker */
- char *p; /* Char * worker */
- #ifdef PIPESEND
- extern int pipesend;
- #endif /* PIPESEND */
- #ifndef NOCSETS
- int tcs = TC_TRANSP; /* Intermediate (xfer) char set */
- int langsv = L_USASCII; /* Save current language */
- int unicode = 0;
- int tcssize = 0;
- #ifdef CK_ANSIC /* ANSI C prototypes... */
- CHAR (*sxo)(CHAR);
- CHAR (*rxo)(CHAR);
- CHAR (*sxi)(CHAR);
- CHAR (*rxi)(CHAR);
- #else /* Not ANSI C... */
- CHAR (*sxo)();
- CHAR (*rxo)();
- CHAR (*sxi)();
- CHAR (*rxi)();
- #endif /* CK_ANSIC */
- #ifdef UNICODE
- union ck_short uc;
- int bomorder = 0;
- #ifdef CK_ANSIC
- extern int (*xl_ufc[MAXFCSETS+1])(USHORT); /* Unicode to FCS */
- extern USHORT (*xl_fcu[MAXFCSETS+1])(CHAR); /* FCS to Unicode */
- extern int (*xuf)(USHORT);
- extern USHORT (*xfu)(CHAR);
- #else
- extern int (*xl_ufc[MAXFCSETS+1])();
- extern USHORT (*xl_fcu[MAXFCSETS+1])();
- extern int (*xuf)();
- extern USHORT (*xfu)();
- #endif /* CK_ANSIC */
- #endif /* UNICODE */
- #endif /* NOCSETS */
- debug(F101,"xmit t","",t);
- debug(F101,"xmit xlate","",xlate);
- debug(F101,"xmit binary","",binary);
- #ifdef PIPESEND
- if (pipesend) {
- if (nopush) return(-2);
- if (zxcmd(ZIFILE,s) < 1) {
- printf("\r\n?Can't start command: %s\n",s);
- return(0);
- }
- } else
- #endif /* PIPESEND */
- if (zopeni(ZIFILE,s) == 0) { /* Open the file to be transmitted */
- printf("\r\n?Can't open file %s\n",s);
- return(0);
- }
- x = -1; /* Open the communication channel */
- if (ttopen(ttname,&x,mdmtyp,cdtimo) < 0) { /* (no harm if already open) */
- printf("\r\nCan't open device %s\n",ttname);
- return(0);
- }
- zz = x ? speed : -1L;
- if (binary) { /* Binary file transmission */
- myflow = (flow == FLO_XONX) ? FLO_NONE : flow;
- if (ttvt(zz,myflow) < 0) { /* So no Xon/Xoff! */
- printf("\r\nCan't condition line\n");
- return(0);
- }
- } else {
- if (ttpkt(zz,flow,parity) < 0) { /* Put the line in "packet mode" */
- printf("Can't condition line\n"); /* so Xon/Xoff will work, etc. */
- return(0);
- }
- }
- is_tn =
- #ifdef TNCODE
- (local && network && IS_TELNET()) || (!local && sstelnet)
- #else
- 0
- #endif /* TNCODE */
- ;
- #ifndef NOCSETS
- /* Set up character set translations */
- tcs = 0; /* "Transfer" or "Other" charset */
- sxo = rxo = NULL; /* Initialize byte-to-byte functions */
- sxi = rxi = NULL;
- unicode = 0; /* Assume Unicode won't be involved */
- if (!binary && xlate) { /* Set up charset translations */
- /*
- In the SENDING direction, we are converting from the local file's
- character-set (fcharset) to the remote terminal charset (tcsr). In the
- RECEIVING direction (echoing) we are converting from the remote end of the
- terminal charset (tcsr) to its local end (tcsl), which is not necessarily
- the same as the file character-set. Especially when the file character
- set is UCS-2, which is not a valid terminal character set. The various
- combinations are represented in this table:
- FCS = File Character Set
- RCS = Remote Terminal Character Set
- CCS = Console (Local Terminal) Character Set
- 8 4 2 1
- FCS FCS RCS CCS
- UCS UTF UTF UTF
- 0 0 0 0 = 0 = No translation
- 0 0 0 1 = 1 = FCS -> RCS, Echo RCS -> UTF
- 0 0 1 0 = 2 = FCS -> UTF, Echo UTF -> CCS
- 0 0 1 1 = 3 = FCS -> UTF, Echo no translation
- 0 1 0 0 = 4 = UTF -> RCS, Echo RCS -> CCS
- 0 1 0 1 = 5 = UTF -> RCS, Echo RCS -> UTF
- 0 1 1 0 = 6 = UTF -> UTF, Echo UTF -> CCS
- 0 1 1 1 = 7 = No translation
- 1 0 0 0 = 8 = UCS -> RCS, Echo RCS -> CCS
- 1 0 0 1 = 9 = UCS -> RCS, Echo RCS -> UTF
- 1 0 1 0 = 10 = UCS -> UTF, Echo UTF -> CCS
- 1 0 1 1 = 11 = UCS -> UTF, Echo no translation
- */
- #ifdef UNICODE
- xfu = NULL; /* Unicode translation functions */
- xuf = NULL;
- bomorder = ucsorder; /* UCS-2 byte order */
- if (fcharset == FC_UCS2) /* File charset is UCS-2 */
- unicode |= 8;
- else if (fcharset == FC_UTF8) /* File charset is UTF-8 */
- unicode |= 4;
- if (tcsr == FC_UTF8) /* Remote term charset is UTF-8 */
- unicode |= 2;
- if (tcsl == FC_UTF8) /* Local term charset is UTF-8 */
- unicode |= 1;
- #endif /* UNICODE */
- /*
- When Unicode not involved -- TCS is the intermediate (xfer) set, and:
- sxo = File-to-Intermediate charset function
- rxo = Intermediate-to-Remote-Terminal charset function
- sxi = Remote-Terminal-to-Intermediate
- rxi = Intermediate-to-Local-Terminal
- */
- tcs = gettcs(tcsr,fcharset); /* Get intermediate set. */
- sxo = xls[tcs][fcharset]; /* translation function */
- rxo = xlr[tcs][tcsr]; /* pointers for output functions */
- sxi = xls[tcs][tcsr]; /* and for input functions. */
- rxi = xlr[tcs][tcsl];
- /*
- At this point we have unicode nonzero if Unicode is involved in the
- conversion, and to 0 if it is not.
- The following is to prevent use of zmstuff() and zdstuff() by translation
- functions (stuffing works with file i/o, not with communication i/o).
- */
- langsv = language; /* Save current SET LANGUAGE */
- language = L_USASCII; /* No language-specific translations */
- }
- #endif /* NOCSETS */
- i = 0; /* Beginning of buffer. */
- #ifndef MAC
- #ifndef AMIGA
- oldsig = signal(SIGINT, trtrap); /* Save current interrupt trap. */
- #endif /* AMIGA */
- #endif /* MAC */
- tr_int = 0; /* Have not been interrupted (yet). */
- rc = 1; /* Return code presumed good. */
- #ifdef VMS
- conres();
- #endif /* VMS */
- #ifndef NOCSETS
- debug(F101,"XMIT unicode","",unicode);
- #ifdef UNICODE
- debug(F101,"XMIT bomorder","",bomorder);
- #endif /* UNICODE */
- #endif /* NOCSETS */
- c = 0; /* Initial condition */
- while (c > -1 && !eof) { /* Loop for all characters in file */
- eol = 0;
- #ifdef MAC
- /*
- * It is expensive to run the miniparser so don't do it for
- * every character.
- */
- if (--count < 0) {
- count = 100;
- miniparser(1);
- if (sstate == 'a') {
- sstate = '\0';
- goto xmitfail;
- }
- }
- #else /* Not MAC */
- if (tr_int) { /* Interrupted? */
- printf("^C...\n"); /* Print message */
- goto xmitfail;
- }
- #endif /* MAC */
- c = zminchar(); /* Get a file character */
- #ifdef COMMENT
- /* too much */
- #ifdef DEBUG
- if (deblog) {
- if (c < 0)
- debug(F101,"XMIT zminchar","",c);
- else
- debug(F000,"XMIT zminchar","",c);
- }
- #endif /* DEBUG */
- #endif /* COMMENT */
- if (c < -1) { /* Other error */
- printf("\r\n?TRANSMIT file read error: %s\n",ck_errstr());
- goto xmitfail;
- } else if (c > -1) {
- nbytes++;
- c &= fmask; /* Apply SET FILE BYTESIZE mask */
- } else if (c == -1) {
- eof = 1;
- debug(F101,"XMIT eof","",eof);
- }
- if (binary) { /* Binary... */
- if (c == -1) { /* If EOF */
- rc = 1; /* Success */
- eof = 1;
- goto xmitexit; /* Done */
- }
- if (!xmitw && !xxecho) { /* Special "blast" mode */
- if (count == XBBUFSIZ) { /* File input buffer full... */
- while (count > 0) {
- errno = 0;
- y = ttol(xbbuf,count);
- if (y < 0) { /* try to send it. */
- printf("\r\n?TRANSMIT output error: %s\n",
- ck_errstr());
- debug(F111,"XMIT binary ttol error",
- ck_errstr(),errno);
- rc = 0;
- break;
- }
- if (y < 0) break;
- count -= y;
- }
- count = 0;
- }
- xbbuf[count++] = c;
- #ifdef TNCODE
- if (c == IAC && is_tn) /* Telnet IAC */
- xbbuf[count++] = IAC; /* must be doubled */
- #endif /* TNCODE */
- continue;
- }
- if (ttoc(dopar((char) c)) < 0) { /* else just send the char */
- printf("\r\n?Can't transmit character\n");
- goto xmitfail;
- }
- #ifdef TNCODE
- if (c == IAC && is_tn) /* Quote Telnet IAC */
- ttoc((char)IAC);
- #endif /* TNCODE */
- if (xmitw) /* Pause if requested */
- msleep(xmitw);
- if (xxecho) { /* SET TRANSMIT ECHO ON? */
- if (duplex) { /* Yes, for half duplex */
- #ifndef NOLOCAL
- #ifdef OS2
- /* Echo to emulator */
- scriptwrtbuf((USHORT)(c & cmdmsk));
- #endif /* OS2 */
- #endif /* NOLOCAL */
- if (conoc((char)(c & cmdmsk)) < 0) /* echo locally. */
- goto xmitfail;
- } else { /* For full duplex, */
- int i, n; /* display whatever is there. */
- n = ttchk(); /* See how many chars are waiting */
- if (n < 0) { /* Connection dropped? */
- printf("\r\n?Connection lost\n");
- goto xmitfail;
- }
- for (i = 0; i < n; i++) { /* Read and echo that many. */
- x = ttinc(xmitt); /* Timed read just in case. */
- if (x > -1) { /* If no timeout */
- if (parity) x &= 0x7f; /* display the char, */
- #ifndef NOLOCAL
- #ifdef OS2
- /* Echo to emulator */
- scriptwrtbuf((USHORT)x);
- #endif /* OS2 */
- #endif /* NOLOCAL */
- if (conoc((char)(x & cmdmsk)) < 0) {
- printf("\r\n?Output error\n");
- goto xmitfail;
- }
- } else if (x == -2) {
- printf("\r\nConnection closed.\n");
- ttclos(1);
- goto xmitfail;
- } else if (x == -3) {
- printf(
- "\r\nSession Limit exceeded - closing connection.\n"
- );
- ttclos(1);
- goto xmitfail;
- } else {
- printf("\r\n?Communications error\n");
- goto xmitfail;
- }
- }
- }
- } else ttflui(); /* Not echoing, just flush input. */
- } else { /* Text mode, line at a time. */
- #ifdef UNICODE
- if (fcharset == FC_UCS2 && xlate) { /* Special for UCS-2 */
- char xbuf[8];
- x = 1 - (nbytes & 1); /* Odd or even byte */
- if (x == 0) /* Note: 1 = the 1st, 0 = 2nd, etc */
- uc.x_short = 0;
- if (bomorder) /* Little Endian */
- x = 1 - x; /* Save byte in appropriate half */
- debug(F101,"XMIT UCS2 x","",x);
- uc.x_char[x] = (CHAR) (c & 0xff);
- if (nbytes & 1) /* First byte, go back for next */
- continue;
- if (nbytes == 2) { /* UCS-2 Byte Order Mark */
- if (uc.x_short == (USHORT) 0xfeff) {
- debug(F100,"XMIT UCS2 BOM FEFF","",bomorder);
- continue;
- } else if (uc.x_short == (USHORT) 0xfffe) {
- bomorder = 1 - bomorder;
- debug(F100,"XMIT UCS2 BOM FFFE (swap)","",bomorder);
- continue;
- }
- }
- sprintf(xbuf,"%04X",uc.x_short); /* SAFE */
- debug(F111,"XMIT UCS2",xbuf,uc.x_short);
- if (nbytes & 1) /* Special eol test for UCS-2 */
- if (uc.x_short == '\n')
- eol = 1;
- #ifdef COMMENT
- if (uc.x_short == 0x2028 || uc.x_short == 0x2029)
- eol = 1;
- #endif /* COMMENT */
- } else
- #endif /* UNICODE */
- if (c == '\n') { /* Normal eol test otherwise */
- eol = 1;
- }
- if (eol) { /* End of line? */
- int stuff = -1;
- debug(F101,"XMIT eol length","",i);
- if (i == 0) { /* Blank line? */
- if (xmitf) /* Yes, insert fill if asked. */
- line[i++] = dopar((char) xmitf);
- }
- if (i == 0 || ((char) line[i-1]) != ((char) dopar(CR)))
- line[i++] = dopar(CR); /* Terminate it with CR */
- if (xmitl) {
- stuff = LF;
- #ifdef TNCODE
- } else if (is_tn && (tn_nlm != TNL_CR)) {
- /* TELNET NEWLINE ON/OFF/RAW */
- stuff = (tn_nlm == TNL_CRLF) ? LF : NUL;
- #endif /* TNCODE */
- }
- if (stuff > -1)
- line[i++] = dopar((char)stuff);
- line[i] = NUL;
- debug(F111,"XMIT eol line",line,i);
- } else if (c != -1) { /* Not a newline, regular character */
- int k, x;
- outxbuf[0] = c; /* In case of no translation */
- outxcount = 1; /* Assume result is one byte */
- #ifndef NOCSETS
- switch (unicode) {
- case 0: /* No Unicode involved */
- case 1:
- if (xlate) { /* If not /TRANSPARENT */
- /* Local-to-intermediate */
- if (sxo) c = (*sxo)((char)c);
- /* Intermediate-to-remote */
- if (rxo) c = (*rxo)((char)c);
- outxbuf[0] = c;
- }
- break;
- #ifdef UNICODE
- case 2: /* Local byte to UTF-8 */
- case 3:
- xfu = xl_fcu[fcharset];
- tcssize = fcsinfo[fcharset].size;
- outxcount =
- b_to_u((CHAR)c,outxbuf,OUTXBUFSIZ,tcssize);
- break;
- case 4: /* Local UTF-8 to remote byte */
- case 5:
- xuf = xl_ufc[tcsr];
- x = u_to_b((CHAR)c); /* Convert to byte */
- if (x == -1) { /* If more input bytes needed */
- continue; /* go back and get them */
- } else if (x == -2) { /* LS or PS (shouldn't happen) */
- outxbuf[0] = CR;
- } else if (x == -9) { /* UTF-8 error */
- outxbuf[0] = '?'; /* Insert error char */
- outxbuf[1] = u_to_b2(); /* Insert next char */
- outxcount = 2;
- } else {
- outxbuf[0] = /* Otherwise store result */
- (unsigned)(x & 0xff);
- }
- break;
- case 6: /* UTF-8 to UTF-8 */
- case 7:
- break;
- case 8: /* UCS-2 to byte */
- case 9:
- xuf = xl_ufc[tcsr];
- outxbuf[0] = (*xuf)(uc.x_short);
- break;
- case 10:
- case 11: { /* UCS-2 to UTF-8 */
- int j;
- CHAR * buf = NULL;
- x = ucs2_to_utf8(uc.x_short,&buf);
- if (x < 0) {
- outxbuf[0] = 0xff; /* (= U+FFFD) */
- outxbuf[1] = 0xbd;
- x = 2;
- }
- for (j = 0; j < x; j++)
- outxbuf[j] = buf[j];
- outxcount = x;
- break;
- }
- #endif /* UNICODE */
- }
- #endif /* NOCSETS */
- outxbuf[outxcount] = NUL;
- debug(F111,"XMIT outxbuf",outxbuf,outxcount);
- /*
- Now the input character (1 or more bytes) is translated into the output
- expansion buffer (1 or more bytes); outxcount = number of bytes to add to
- the TRANSMIT line buffer, which we do here, taking care of parity, SI/SO
- processing, and quoting Telnet IACs.
- */
- for (k = 0; k < outxcount; k++) {
- c = outxbuf[k];
- if (xmits && parity && (c & 0200)) { /* If shifting */
- line[i++] = dopar(SO); /* needs to be done, */
- line[i++] = dopar((char)c); /* do it here, */
- line[i++] = dopar(SI); /* crudely. */
- } else {
- line[i++] = dopar((char)c);
- #ifdef TNCODE
- if (c == (CHAR)IAC && is_tn)
- line[i++] = (CHAR)IAC;
- #endif /* TNCODE */
- }
- }
- }
- /*
- Send characters if buffer full, or at end of line, or at end of file.
- (End of line only if echoing, waiting for a prompt, or pausing.)
- */
- debug(F000,"XMIT c",ckitoa(i),c);
- if (i >= xbufsiz || eof || (eol && (xxecho || xmitw || t))) {
- p = line;
- line[i] = '\0';
- debug(F111,"transmit buf",p,i);
- if (ttol((CHAR *)p,i) < 0) { /* try to send it. */
- printf("?TRANSMIT output error: %s\n",ck_errstr());
- rc = 0;
- break;
- }
- i = 0; /* Reset buffer pointer. */
- /*
- Now we handle the echo. If the user wants to see it, or if we have to
- wait for the turnaround character, t. If the echo is being displayed,
- and terminal character-set translation is required, we do it here.
- */
- if (duplex && xxecho) { /* If local echo, echo it */
- if (parity || cmdmsk == 0x7f) { /* Strip hi bits */
- char *ss = line; /* if necessary */
- while (*ss) {
- *ss &= 0x7f;
- ss++;
- }
- }
- #ifndef NOLOCAL
- #ifdef OS2
- { /* Echo to emulator */
- char *ss = p;
- while (*ss) {
- scriptwrtbuf((USHORT)*ss);
- ss++;
- }
- }
- #endif /* OS2 */
- #endif /* NOLOCAL */
- if (conoll(p) < 0)
- goto xmitfail;
- }
- if (xmitw) /* Sleep TRANSMIT PAUSE interval */
- msleep(xmitw);
- control = 0; /* Readback loop control */
- if (t != 0 && eol) /* TRANSMIT PROMPT given and at EOL */
- control |= 1;
- if (xxecho && !duplex) /* Echo desired and is remote */
- control |= 2;
- if (control) { /* Do this if reading back the echo */
- int n;
- x = 0;
- while (1) {
- if (control & 1) { /* Termination criterion */
- if (x == t) /* for turnaround */
- break;
- } else if (control & 2) { /* And for echoing */
- if ((n = ttchk()) < 1)
- break;
- }
- if ((x = ttinc(xmitt)) < 0) { /* Read with timeout */
- switch (x) {
- case -2:
- printf("Connection closed.\n");
- ttclos(1);
- goto xmitfail;
- case -3:
- printf(
- "Session Limit exceeded - closing connection.\n"
- );
- ttclos(1); /* full thru... */
- goto xmitfail;
- default:
- printf("?Timeout\n");
- goto xmitfail;
- }
- }
- if (x > -1 && (control & 2)) { /* Echo any echoes */
- if (parity)
- x &= 0x7f;
- c = x;
- #ifndef NOLOCAL
- #ifdef OS2
- scriptwrtbuf((USHORT)x);
- #endif /* OS2 */
- #endif /* NOLOCAL */
- inxbuf[0] = c;
- inxcount = 1;
- #ifndef NOCSETS
- switch (unicode & 3) { /* Remote bits */
- case 0:
- if (xlate) {
- if (sxi) c = (*sxi)((CHAR)c);
- if (rxi) c = (*rxi)((CHAR)c);
- inxbuf[0] = c;
- }
- break;
- #ifdef UNICODE
- case 1: /* Remote Byte to local UTF-8 */
- xfu = xl_fcu[tcsr];
- tcssize = fcsinfo[tcsr].size;
- inxcount =
- b_to_u((CHAR)c,
- inxbuf,
- OUTXBUFSIZ,
- tcssize
- );
- break;
- case 2: /* Remote UTF-8 to local Byte */
- xuf = xl_ufc[tcsl];
- x = u_to_b((CHAR)c);
- if (x < 0)
- continue;
- inxbuf[0] = (unsigned)(x & 0xff);
- break;
- case 3: /* UTF-8 to UTF-8 */
- break;
- #endif /* UNICODE */
- }
- #endif /* NOCSETS */
- inxbuf[inxcount] = NUL;
- if (conxo(inxcount,(char *)inxbuf) < 0)
- goto xmitfail;
- }
- }
- } else /* Not echoing */
- ttflui(); /* Just flush input buffer */
- } /* End of buffer-dumping block */
- } /* End of text mode */
- if (eof) {
- rc = 1;
- goto xmitexit;
- }
- } /* End of character-reading loop */
- xmitfail: /* Failure exit point */
- rc = 0;
- xmitexit: /* General exit point */
- if (rc > 0) {
- if (binary && !xmitw && !xxecho) { /* "blasting"? */
- while (count > 0) { /* Partial buffer still to go? */
- errno = 0;
- y = ttol(xbbuf,count);
- if (y < 0) {
- printf("?TRANSMIT output error: %s\n",
- ck_errstr());
- debug(F111,"XMIT binary eof ttol error",
- ck_errstr(),errno);
- rc = 0;
- break;
- }
- count -= y;
- }
- } else if (!binary && *xmitbuf) { /* Anything to send at EOF? */
- p = xmitbuf; /* Yes, point to string. */
- while (*p) /* Send it. */
- ttoc(dopar(*p++)); /* Don't worry about echo here. */
- }
- }
- #ifndef AMIGA
- #ifndef MAC
- signal(SIGINT,oldsig); /* Put old signal action back. */
- #endif /* MAC */
- #endif /* AMIGA */
- #ifdef VMS
- concb(escape); /* Put terminal back, */
- #endif /* VMS */
- zclose(ZIFILE); /* Close file, */
- #ifndef NOCSETS
- language = langsv; /* restore language, */
- #endif /* NOCSETS */
- ttres(); /* and terminal modes, */
- return(rc); /* and return successfully. */
- }
- #endif /* NOLOCAL */
- #endif /* NOXMIT */
- #ifndef NOCSETS
- _PROTOTYP( CHAR (*sxx), (CHAR) ); /* Local translation function */
- _PROTOTYP( CHAR (*rxx), (CHAR) ); /* Local translation function */
- _PROTOTYP( CHAR zl1as, (CHAR) ); /* Latin-1 to ascii */
- _PROTOTYP( CHAR xl1as, (CHAR) ); /* ditto */
- /* X L A T E -- Translate a local file from one character set to another */
- /*
- Translates input file (fin) from character set csin to character set csout
- and puts the result in the output file (fout). The two character sets are
- file character sets from fcstab.
- */
- int
- xlate(fin, fout, csin, csout) char *fin, *fout; int csin, csout; {
- #ifndef MAC
- #ifdef OS2
- extern int k95stdout;
- extern int wherex[], wherey[];
- extern unsigned char colorcmd;
- #ifdef NT
- SIGTYP (* oldsig)(int); /* For saving old interrupt trap. */
- #else /* NT */
- SIGTYP (* volatile oldsig)(int); /* For saving old interrupt trap. */
- #endif /* NT */
- #else /* OS2 */
- SIGTYP (* oldsig)();
- #endif /* OS2 */
- #endif /* MAC */
- #ifdef CK_ANSIC
- int (*fn)(char); /* Output function pointer */
- #else
- int (*fn)();
- #endif /* CK_ANSIC */
- extern int xlatype;
- int filecode; /* Code for output file */
- int scrnflg = 0;
- int z = 1; /* Return code. */
- int x, c, c2; /* Workers */
- #ifndef UNICODE
- int tcs;
- #endif /* UNICODE */
- ffc = 0L;
- if (zopeni(ZIFILE,fin) == 0) { /* Open the file to be translated */
- #ifdef COMMENT
- /* An error message was already printed by zopeni() */
- printf("?Can't open input file %s\n",fin);
- #endif /* COMMENT */
- return(0);
- }
- #ifdef MAC
- /*
- If user specified no output file, it goes to the screen. For the Mac,
- this must be done a special way (result goes to a new window); the Mac
- doesn't have a "controlling terminal" device name.
- */
- filecode = !strcmp(fout,CTTNAM) ? ZCTERM : ZOFILE;
- #else
- #ifdef VMS
- filecode = !strcmp(fout,CTTNAM) ? ZCTERM : ZMFILE;
- #else
- #ifdef OS2
- filecode = (!stricmp(fout,"con") || !stricmp(fout,"con:")) ?
- ZCTERM : ZMFILE;
- if ((filecode == ZCTERM) && !k95stdout && !inserver)
- csout = FC_UCS2;
- #else /* OS2 */
- filecode = ZOFILE;
- #endif /* OS2 */
- #endif /* VMS */
- #endif /* MAC */
- if (zopeno(filecode,fout,NULL,NULL) == 0) { /* And the output file */
- printf("?Can't open output file %s\n",fout);
- return(0);
- }
- #ifndef AMIGA
- #ifndef MAC
- oldsig = signal(SIGINT, trtrap); /* Save current interrupt trap. */
- #endif /* MAC */
- #endif /* AMIGA */
- scrnflg = (filecode == ZCTERM); /* Set output function */
- if (scrnflg)
- fn = NULL;
- else if (filecode == ZMFILE)
- fn = putmfil;
- else
- fn = putfil;
- tr_int = 0; /* Have not been interrupted (yet). */
- z = 1; /* Return code presumed good. */
- if (!scrnflg && !quiet)
- printf(" %s (%s) => %s (%s)\n", /* Say what we're doing. */
- fin, fcsinfo[csin].keyword,
- fout,fcsinfo[csout].keyword
- );
- #ifndef UNICODE
- /*
- Non-Unicode picks the "most appropriate" transfer character set as the
- intermediate set, which results in loss of any characters that the source
- and target sets have in common, but are lacking from the intermediate set.
- */
- #ifdef KANJI
- /* Special handling for Japanese... */
- if (fcsinfo[csin].alphabet == AL_JAPAN ||
- fcsinfo[csout].alphabet == AL_JAPAN) {
- USHORT eu;
- int c, x, y;
- xpnbyte(-1,0,0,NULL); /* Reset output machine */
- xlatype = XLA_JAPAN;
- while ((c = xgnbyte(FC_JEUC,csin,NULL)) > -1) { /* Get an EUC byte */
- if (tr_int) { /* Interrupted? */
- printf("^C...\n"); /* Print message */
- z = 0;
- break;
- }
- /* Send EUC byte to output machine */
- if ((x = xpnbyte(c,TC_JEUC,csout,fn)) < 0) {
- z = -1;
- break;
- }
- }
- goto xxlate;
- }
- #endif /* KANJI */
- /* Regular bytewise conversion... */
- tcs = gettcs(csin,csout); /* Get intermediate set. */
- if (csin == csout) { /* Input and output sets the same? */
- sxx = rxx = NULL; /* If so, no translation. */
- } else { /* Otherwise, set up */
- if (tcs < 0 || tcs > MAXTCSETS ||
- csin < 0 || csin > MAXFCSETS ||
- csout < 0 || csout > MAXFCSETS) {
- debug(F100,"XLATE csets out of range","",0);
- sxx = rxx = NULL;
- } else {
- sxx = xls[tcs][csin]; /* translation function */
- rxx = xlr[tcs][csout]; /* pointers. */
- if (rxx == zl1as) rxx = xl1as;
- }
- }
- while ((c = zminchar()) != -1) { /* Loop for all characters in file */
- if (tr_int) { /* Interrupted? */
- printf("^C...\n"); /* Print message */
- z = 0;
- break;
- }
- if (sxx) c = (*sxx)((CHAR)c); /* From fcs1 to tcs */
- if (rxx) c = (*rxx)((CHAR)c); /* from tcs to fcs2 */
- if (zchout(filecode,(char)c) < 0) { /* Output xlated character */
- z = -1;
- break;
- }
- }
- goto xxlate; /* Done. */
- #else /* UNICODE */
- /*
- Use Unicode as the intermediate character set. It's simple and gives
- little or no loss, but the overhead is a bit higher.
- */
- initxlate(csin,csout); /* Set up translation functions */
- if (xlatype == XLA_NONE) {
- while ((c = zminchar()) != -1) { /* Loop for all characters in file */
- if (tr_int) { /* Interrupted? */
- printf("^C...\n"); /* Print message */
- z = 0;
- break;
- }
- if (zchout(filecode,(char)c) < 0) { /* Output xlated character */
- z = -1;
- break;
- }
- }
- goto xxlate; /* Done. */
- }
- #ifndef NOLOCAL
- #ifdef OS2
- if (csout == FC_UCS2 && /* we're translating to UCS-2 */
- filecode == ZCTERM && /* for the real screen... */
- !k95stdout && !inserver
- ) {
- union {
- USHORT ucs2;
- UCHAR bytes[2];
- } output;
- while (1) { /* In this case we go two-by-two. */
- if ((c = xgnbyte(FC_UCS2,csin,NULL)) < 0)
- break;
- output.bytes[0] = c;
- if ((c = xgnbyte(FC_UCS2,csin,NULL)) < 0)
- break;
- output.bytes[1] = c;
- if (tr_int) { /* Interrupted? */
- printf("^C...\n"); /* Print message */
- z = 0;
- break;
- }
- VscrnWrtUCS2StrAtt(VCMD,
- &output.ucs2,
- 1,
- wherey[VCMD],
- wherex[VCMD],
- &colorcmd
- );
- }
- } else
- #endif /* OS2 */
- #endif /* NOLOCAL */
- /* General case: Get next byte translated from fcs to UCS-2 */
- #ifdef COMMENT
- while ((c = xgnbyte(FC_UCS2,csin,NULL)) > -1 &&
- (c2 = xgnbyte(FC_UCS2,csin,NULL)) > -1) {
- extern int fileorder;
- if (tr_int) { /* Interrupted? */
- printf("^C...\n"); /* Print message */
- z = 0;
- break;
- }
- debug(F001,"XLATE c","",c);
- debug(F001,"XLATE c2","",c2);
- /* And then send UCS-2 byte to translate-and-output machine */
- if ((x = xpnbyte(fileorder?c2:c,TC_UCS2,csout,fn)) < 0) {
- z = -1;
- break;
- }
- if ((x = xpnbyte(fileorder?c:c2,TC_UCS2,csout,fn)) < 0) {
- z = -1;
- break;
- }
- }
- #else
- while ((c = xgnbyte(FC_UCS2,csin,NULL)) > -1) {
- if (tr_int) { /* Interrupted? */
- printf("^C...\n"); /* Print message */
- z = 0;
- break;
- }
- if ((x = xpnbyte(c,TC_UCS2,csout,fn)) < 0) {
- z = -1;
- break;
- }
- }
- #endif /* COMMENT */
- #endif /* UNICODE */
- xxlate: /* Common exit point */
- #ifndef AMIGA
- #ifndef MAC
- signal(SIGINT,oldsig); /* Put old signal action back. */
- #endif /* MAC */
- #endif /* AMIGA */
- tr_int = 0;
- if (z < 0) {
- if (z == -1)
- printf("?File output error: %s\n",ck_errstr());
- z = 0;
- }
- zclose(ZIFILE); /* Close files */
- zclose(filecode); /* ... */
- return(success = z); /* and return status. */
- }
- int
- doxlate() {
- #ifdef OS2ONLY
- extern int tt_font;
- #endif /* OS2ONLY */
- #ifdef UNIX
- extern char ** mtchs; /* zxpand() file list */
- #endif /* UNIX */
- int x, y, incs, outcs, multiple = 0, wild = 0, fc = 0, len = 0;
- int ofisdir = 0;
- char * s, * tocs = "";
- if ((x = cmifi("File(s) to translate","",&s,&wild,xxstring)) < 0) {
- if (x == -3) {
- printf("?Name of an existing file\n");
- return(-9);
- } else
- return(x);
- }
- ckstrncpy(line,s,LINBUFSIZ); /* Save copy of string just parsed. */
- if ((incs = cmkey(fcstab,nfilc,"from character-set","",xxstring)) < 0)
- return(incs);
- #ifdef OS2
- if (isunicode())
- tocs = "ucs2";
- else
- #endif /* OS2 */
- tocs = getdcset();
- if ((outcs = cmkey(fcstab,nfilc,"to character-set",tocs,xxstring)) < 0)
- return(outcs);
- if ((x = cmofi("output file",CTTNAM,&s,xxstring)) < 0) return(x);
- if (x > 1)
- ofisdir = 1;
- len = ckstrncpy(tmpbuf,s,TMPBUFSIZ);
- if ((y = cmcfm()) < 0) return(y); /* Confirm the command */
- if (len < 1)
- return(-2);
- if (ofisdir)
- multiple = 2;
- else if (wild) {
- if (isdir(tmpbuf))
- multiple = 2;
- else if (!strcmp(tmpbuf,CTTNAM))
- multiple = 1;
- #ifdef OS2
- else if (!stricmp(tmpbuf,"con") || !stricmp(tmpbuf,"con:"))
- multiple = 1;
- #else
- #ifdef UNIXOROSK
- else if (!strncmp(tmpbuf,"/dev/",4))
- multiple = 1;
- #endif /* UNIXOROSK */
- #endif /* OS2 */
- if (!multiple) {
- printf("?A single file please\n");
- return(-9);
- }
- }
- if (!multiple) { /* Just one file */
- return(success = xlate(line,tmpbuf,incs,outcs));
- } else { /* Translate multiple files */
- char dirbuf[CKMAXPATH+4];
- int k;
- #ifndef ZXREWIND
- int flags = ZX_FILONLY;
- #endif /* ZXREWIND */
- if (multiple == 2) { /* Target is a directory */
- k = ckstrncpy(dirbuf,tmpbuf,CKMAXPATH+1) - 1;
- if (k < 0)
- return(-2);
- #ifdef OS2ORUNIX
- if (dirbuf[k] != '/') {
- dirbuf[k+1] = '/';
- dirbuf[k+2] = NUL;
- }
- #else
- #ifdef OSK
- if (dirbuf[k] != '/') {
- dirbuf[k+1] = '/';
- dirbuf[k+2] = NUL;
- }
- #else
- #ifdef VMS
- if (ckmatch("*.DIR;1",s,0,0))
- k = cvtdir(tmpbuf,dirbuf,TMPBUFSIZ);
- if (dirbuf[k] != ']' &&
- dirbuf[k] != '>' &&
- dirbuf[k] != ':')
- return(-2);
- #else
- #ifdef datageneral
- if (dirbuf[k] != ':') {
- dirbuf[k+1] = ':';
- dirbuf[k+2] = NUL;
- }
- #else
- #ifdef STRATUS
- if (dirbuf[k] != '>') {
- dirbuf[k+1] = '>';
- dirbuf[k+2] = NUL;
- }
- #endif /* STRATUS */
- #endif /* datageneral */
- #endif /* VMS */
- #endif /* OSK */
- #endif /* OS2ORUNIX */
- }
- #ifdef ZXREWIND
- fc = zxrewind(); /* Rewind the file list */
- #else
- if (matchdot) flags |= ZX_MATCHDOT;
- fc = nzxpand(line,flags);
- #endif /* ZXREWIND */
- if (fc < 1) {
- printf("?Wildcard expansion error\n");
- return(-9);
- }
- #ifdef UNIX
- sh_sort(mtchs,NULL,fc,0,0,filecase); /* Sort the file list */
- #endif /* UNIX */
- while (1) { /* Loop through the files */
- znext(line);
- if (!line[0])
- break;
- if (multiple == 2)
- ckmakmsg(tmpbuf,TMPBUFSIZ,dirbuf,line,NULL,NULL);
- if (xlate(line,tmpbuf,incs,outcs) < 1)
- return(success = 0);
- }
- }
- return(success = 1);
- }
- #endif /* NOCSETS */
- /*
- Returns path of user's actual home directory (or, if specified, SET CD HOME
- directory), properly terminated to allow filenames or sub-paths to be
- appended.
- */
- static char hompthbuf[CKMAXPATH+1] = { NUL, NUL }; /* Home directory path */
- char *
- homepath() {
- int x;
- extern char hompthbuf[];
- extern char * myhome;
- char * h;
-
- /* myhome = SET CD HOME; zhome() uses API to get home directory */
- h = myhome ? myhome : zhome();
- hompthbuf[0] = NUL;
- /* Ensure it is terminated with appropriate directory or device separator. */
- #ifdef UNIXOROSK
- x = ckstrncpy(hompthbuf,h,CKMAXPATH+1);
- if (x <= 0) {
- hompthbuf[0] = '/';
- hompthbuf[1] = NUL;
- } else if (x < CKMAXPATH - 2 && hompthbuf[x-1] != '/') {
- hompthbuf[x] = '/';
- hompthbuf[x+1] = NUL;
- }
- return(hompthbuf);
- #else
- #ifdef STRATUS
- if (strlen(h) < CKMAXPATH)
- sprintf(hompthbuf,"%s>",h); /* SAFE */
- return(hompthbuf);
- #else
- return(h);
- #endif /* STRATUS */
- #endif /* UNIXOROSK */
- }
- /* D O L O G -- Do the log command */
- int
- dolog(x) int x; {
- int y, disp; char *s = NULL, * p = NULL, * q = NULL;
- extern int isguest;
- #ifdef ZFNQFP
- struct zfnfp * fnp;
- #endif /* ZFNQFP */
- if (isguest) {
- printf("?Anonymous log creation not allowed\n");
- return(-9);
- }
- switch (x) { /* Which log... */
- #ifdef DEBUG
- case LOGD:
- q = "debug.log";
- y = cmofi("Name of debugging log file",q,&s,xxstring);
- break;
- #endif /* DEBUG */
- case LOGP:
- q = "packet.log";
- y = cmofi("Name of packet log file",q,&s,xxstring);
- break;
- #ifndef NOLOCAL
- case LOGS:
- q = "session.log";
- y = cmofi("Name of session log file",q,&s,xxstring);
- break;
- #endif /* NOLOCAL */
- #ifdef TLOG
- case LOGT:
- q = "transact.log";
- y = cmofi("Name of transaction log file",q,&s,xxstring);
- break;
- #endif /* TLOG */
- #ifdef CKLOGDIAL
- case LOGM: {
- int m, n;
- char mypath[CKMAXPATH+1];
- q = CXLOGFILE;
- m = ckstrncpy(mypath,homepath(),CKMAXPATH);
- n = strlen(CXLOGFILE);
- if (m + n < CKMAXPATH)
- ckstrncat(mypath,CXLOGFILE,CKMAXPATH);
- else
- ckstrncpy(mypath,CXLOGFILE,CKMAXPATH);
- y = cmofi("Name of connection log file",mypath,&s,xxstring);
- break;
- }
- #endif /* CKLOGDIAL */
- default:
- printf("\n?Unknown log designator - %d\n",x);
- return(-2);
- }
- if (y < 0) return(y);
- if (y == 2) { /* If they gave a directory name */
- int k;
- char * ds = "/";
- k = strlen(s);
- if (k > 0 && s[k-1] == '/') ds = "";
- ckmakmsg(tmpbuf,TMPBUFSIZ,s,ds,q,NULL);
- s = tmpbuf;
- }
- #ifdef ZFNQFP
- #ifdef OS2ORUNIX
- if (*s != '|') /* Allow for pipes */
- #else
- #ifdef OSK
- if (*s != '|')
- #endif /* OSK */
- #endif /* OS2ORUNIX */
- if ((fnp = zfnqfp(s,TMPBUFSIZ - 1,tmpbuf))) {
- if (fnp->fpath)
- if ((int) strlen(fnp->fpath) > 0)
- s = fnp->fpath;
- } /* else if error keep original string */
- #endif /* ZFNQFP */
- ckstrncpy(line,s,LINBUFSIZ);
- s = line;
- #ifdef MAC
- y = 0;
- #else
- p = "new";
- #ifdef TLOG
- if ((x == LOGT && tlogfmt == 2) || x == LOGM)
- p = "append";
- #endif /* TLOG */
- if ((y = cmkey(disptb,2,"Disposition",p,xxstring)) < 0)
- return(y);
- #endif /* MAC */
- disp = y;
- if ((y = cmcfm()) < 0) return(y);
- switch (x) {
- #ifdef DEBUG
- case LOGD:
- return(deblog = debopn(s,disp));
- #endif /* DEBUG */
- #ifndef NOXFER
- case LOGP:
- return(pktlog = pktopn(s,disp));
- #endif /* NOXFER */
- #ifndef NOLOCAL
- case LOGS:
- setseslog(sesopn(s,disp));
- return(seslog);
- #endif /* NOLOCAL */
- #ifdef TLOG
- case LOGT:
- return(tralog = traopn(s,disp));
- #endif /* TLOG */
- #ifdef CKLOGDIAL
- case LOGM:
- return(dialog = diaopn(s,disp,0));
- #endif /* CKLOGDIAL */
- default:
- return(-2);
- }
- }
- #ifndef NOXFER
- int
- pktopn(s,disp) char *s; int disp; {
- static struct filinfo xx;
- if (!s)
- s = "";
- if (!*s)
- return(0);
- debug(F111,"pktopn",s,disp);
- zclose(ZPFILE);
- #ifdef OS2ORUNIX
- if (s[0] == '|') { /* Pipe */
- char * p = s + 1;
- debug(F110,"pktopn p",p,0);
- while (*p) {
- if (*p != ' ')
- break;
- else
- p++;
- }
- debug(F110,"pktopn pipe",p,0);
- pktlog = zxcmd(ZPFILE,p);
- debug(F101,"pktopn seslog","",seslog);
- } else { /* File */
- #endif /* OS2ORUNIX */
- if (disp) {
- xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
- xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
- xx.lblopts = 0;
- pktlog = zopeno(ZPFILE,s,NULL,&xx);
- } else pktlog = zopeno(ZPFILE,s,NULL,NULL);
- if (!pktlog && !quiet)
- printf("?%s - %s\n",s,ck_errstr());
- #ifdef OS2ORUNIX
- }
- #endif /* OS2ORUNIX */
- if (pktlog > 0)
- ckstrncpy(pktfil,s,CKMAXPATH+1);
- else
- *pktfil = '\0';
- return(pktlog);
- }
- #endif /* NOXFER */
- int
- traopn(s,disp) char *s; int disp; {
- #ifdef TLOG
- static struct filinfo xx;
- if (!s)
- s = "";
- if (!*s)
- return(0);
- debug(F111,"traopn",s,disp);
- debug(F101,"traopn tlogfmt","",tlogfmt);
- zclose(ZTFILE);
- #ifdef OS2ORUNIX
- if (tlogfmt == 2) { /* FTP format is special... */
- VOID doiklog();
- if (!disp) /* Append? */
- if (zchki(s) > -1) /* No - does file exist? */
- (VOID) zdelet(s); /* Yes - delete it. */
- xferlog = 1;
- ckstrncpy(trafil,s,CKMAXPATH);
- makestr(&xferfile,s);
- doiklog();
- return(1);
- }
- if (s[0] == '|') { /* Pipe */
- char * p = s + 1;
- debug(F110,"traopn p",p,0);
- while (*p) {
- if (*p != ' ')
- break;
- else
- p++;
- }
- debug(F110,"traopn pipe",p,0);
- tralog = zxcmd(ZTFILE,p);
- debug(F101,"traopn tralog","",tralog);
- }
- #endif /* OS2ORUNIX */
- if (s[0] != '|') { /* File */
- if (disp) {
- xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
- xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
- xx.lblopts = 0;
- tralog = zopeno(ZTFILE,s,NULL,&xx);
- } else tralog = zopeno(ZTFILE,s,NULL,NULL);
- }
- if (!tralog && !quiet)
- printf("?%s - %s\n",s,ck_errstr());
- if (tralog > 0 && tlogfmt > 0) {
- ckstrncpy(trafil,s,CKMAXPATH);
- tlog(F110,"Transaction Log:",versio,0L);
- #ifndef MAC
- tlog(F100,ckxsys,"",0L);
- #endif /* MAC */
- ztime(&s);
- tlog(F100,s,"",0L);
- } else
- *trafil = '\0';
- return(tralog);
- #else
- return(0);
- #endif /* TLOG */
- }
- #ifndef NOLOCAL
- int
- sesopn(s,disp) char * s; int disp; {
- static struct filinfo xx;
- extern int tsstate;
- tsstate = 0; /* Session log timestamp state */
- if (!s)
- s = "";
- if (!*s)
- return(0);
- debug(F111,"sesopn",s,disp);
- zclose(ZSFILE);
- #ifdef OS2ORUNIX
- if (s[0] == '|') { /* Pipe */
- char * p = s + 1;
- debug(F110,"sesopn p",p,0);
- while (*p) {
- if (*p != ' ')
- break;
- else
- p++;
- }
- debug(F110,"sesopn pipe",p,0);
- setseslog(zxcmd(ZSFILE,p));
- debug(F101,"sesopn seslog","",seslog);
- } else { /* File */
- #endif /* OS2ORUNIX */
- if (disp) {
- xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
- xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
- xx.lblopts = 0;
- setseslog(zopeno(ZSFILE,s,NULL,&xx));
- } else
- setseslog(zopeno(ZSFILE,s,NULL,NULL));
- if (!seslog && !quiet)
- printf("?%s - %s\n",s,ck_errstr());
- #ifdef OS2ORUNIX
- }
- #endif /* OS2ORUNIX */
- if (seslog > 0)
- ckstrncpy(sesfil,s,CKMAXPATH+1);
- else
- *sesfil = '\0';
- return(seslog);
- }
- #endif /* NOLOCAL */
- #endif /* NOICP */
- int
- debopn(s,disp) char *s; int disp; {
- #ifdef DEBUG
- #ifdef CK_UTSNAME
- extern char unm_mch[], unm_nam[], unm_rel[], unm_ver[], unm_mod[];
- #endif /* CK_UTSNAME */
- #ifdef OS2
- extern char ckxsystem[];
- #endif /* OS2 */
- char *tp;
- static struct filinfo xx;
- if (!s)
- s = "";
- if (!*s)
- return(0);
- zclose(ZDFILE);
- #ifdef OS2ORUNIX
- if (s[0] == '|') { /* Pipe */
- char * p = s + 1;
- debug(F110,"debopn p",p,0);
- while (*p) {
- if (*p != ' ')
- break;
- else
- p++;
- }
- debug(F110,"debopn pipe",p,0);
- deblog = zxcmd(ZDFILE,p);
- debug(F101,"debopn deblog","",deblog);
- } else { /* File */
- #endif /* OS2ORUNIX */
- if (disp) {
- xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
- xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
- xx.lblopts = 0;
- deblog = zopeno(ZDFILE,s,NULL,&xx);
- } else
- deblog = zopeno(ZDFILE,s,NULL,NULL);
- if (!deblog && !quiet)
- printf("?%s - %s\n",s,ck_errstr());
- #ifdef OS2ORUNIX
- }
- #endif /* OS2ORUNIX */
- if (deblog > 0) {
- ckstrncpy(debfil,s,CKMAXPATH+1);
- debug(F110,"Debug Log ",versio,0);
- #ifndef MAC
- #ifdef OS2
- debug(F110,ckxsys,ckxsystem,0);
- #else /* OS2 */
- debug(F100,ckxsys,"",0);
- #endif /* OS2 */
- #endif /* MAC */
- #ifdef CK_UTSNAME
- if (unm_mch[0]) {
- debug(F110,"uname machine",unm_mch,0);
- if (unm_mod[0])
- debug(F110,"uname model ",unm_mod,0);
- debug(F110,"uname sysname",unm_nam,0);
- debug(F110,"uname release",unm_rel,0);
- debug(F110,"uname version",unm_ver,0);
- }
- #ifdef KTARGET
- {
- char * s; /* Makefile target */
- s = KTARGET;
- if (!s) s = "";
- if (!*s) s = "(unknown)";
- debug(F110,"build target",s,0);
- }
- #endif /* KTARGET */
- deblog = 0;
- ztime(&tp);
- deblog = 1;
- debug(F100,tp,"",0);
- #endif /* UTSNAME */
- debug(F101,"byteorder","",byteorder);
- #ifndef NOICP
- #ifndef NOLOCAL
- if (local) {
- debug(F110,"Active connection: ",ttname,0);
- if (!network) {
- debug(F101,"Speed","",speed);
- if (hwparity)
- debug(F110,"Parity[hardware]",parnam((char)hwparity),0);
- else
- debug(F110,"Parity",parnam((char)parity),0);
- deblog = 0;
- debug(F110,"Modem",gmdmtyp(),0);
- deblog = 1;
- }
- } else {
- debug(F110,"Active connection: ","none",0);
- }
- #endif /* NOLOCAL */
- #endif /* NOICP */
- } else *debfil = '\0';
- return(deblog);
- #else
- return(0);
- #endif /* MAC */
- }
- /* C K D A T E -- Returns current date/time in standard format */
- static char nowbuf[18];
- char *
- ckdate() {
- extern struct keytab cmonths[];
- int x;
- char * t; /* Substitute today's date */
- char dbuf[32];
- ztime(&t);
- /* 012345678901234567890123 */
- /* Sat Jul 4 12:16:43 1998 */
- ckstrncpy(dbuf,t,32);
- t = dbuf;
- debug(F110,"ckdate dbuf",dbuf,0);
- nowbuf[0] = t[20];
- nowbuf[1] = t[21];
- nowbuf[2] = t[22];
- nowbuf[3] = t[23];
- nowbuf[4] = NUL;
- debug(F110,"ckdate nowbuf",nowbuf,0);
- t[7] = NUL;
- if ((x = lookup(cmonths,t+4,12,NULL)) < 0) {
- debug(F110,"ckdate bad month",t,0);
- return("<BAD_MONTH>");
- }
- sprintf(nowbuf+4,"%02d",x); /* SAFE */
- nowbuf[6] = (t[8] == SP) ? '0' : t[8];
- nowbuf[7] = t[9];
- nowbuf[8] = ' ';
- nowbuf[9] = NUL;
- debug(F110,"ckdate nowbuf",nowbuf,0);
- for (x = 11; x < 19; x++) nowbuf[x-2] = t[x];
- nowbuf[17] = NUL;
- debug(F110,"ckdate nowbuf",nowbuf,0);
- return((char *)nowbuf);
- }
- #ifndef NOICP
- #ifdef CKLOGDIAL
- /*
- fc = 0 for initial open, meaning open, then close immediately.
- fc > 0 for subsequent opens, meaning open for use, leave open.
- */
- int
- diaopn(s,disp,fc) char *s; int disp, fc; {
- static struct filinfo xx;
- if (!s)
- s = "";
- if (!*s)
- return(0);
- debug(F110,"diaopn log",s,0);
- debug(F101,"diaopn fc",s,fc);
- debug(F101,"diaopn disp 1",s,disp);
- if (fc) disp = 1; /* Force append if open for use */
- debug(F101,"diaopn disp 2",s,disp);
- zclose(ZDIFIL); /* In case a log was already open */
- #ifdef OS2ORUNIX
- if (s[0] == '|') { /* Pipe */
- char * p = s + 1;
- debug(F110,"diaopn p",p,0);
- while (*p) {
- if (*p != ' ')
- break;
- else
- p++;
- }
- debug(F110,"diaopn pipe",p,0);
- dialog = zxcmd(ZDIFIL,p);
- debug(F101,"diaopn dialog","",dialog);
- } else { /* File */
- #endif /* OS2ORUNIX */
- if (disp) {
- xx.bs = 0; xx.cs = 0; xx.rl = 0; xx.org = 0; xx.cc = 0;
- xx.typ = 0; xx.dsp = XYFZ_A; xx.os_specific = "";
- xx.lblopts = 0;
- dialog = zopeno(ZDIFIL,s,NULL,&xx);
- } else dialog = zopeno(ZDIFIL,s,NULL,NULL);
- if (!dialog)
- printf("?%s - %s\n",s,ck_errstr());
- #ifdef OS2ORUNIX
- }
- #endif /* OS2ORUNIX */
- if (dialog > 0)
- ckstrncpy(diafil,s,CKMAXPATH+1);
- else
- *diafil = '\0';
- if (fc == 0) /* Initial open */
- zclose(ZDIFIL); /* close it */
- return(dialog);
- }
- #endif /* CKLOGDIAL */
- #ifndef NOSHOW
- /* SHOW command routines */
- char *
- shoxm() {
- char * s;
- switch (binary) {
- case XYFT_T: s = "text"; break;
- #ifdef VMS
- case XYFT_B: s = "binary fixed"; break;
- case XYFT_I: s = "image"; break;
- case XYFT_L: s = "labeled"; break;
- case XYFT_U: s = "binary undef"; break;
- #else
- #ifdef MAC
- case XYFT_B: s = "binary"; break;
- case XYFT_M: s = "macbinary"; break;
- #else
- case XYFT_B: s = "binary"; break;
- #ifdef CK_LABELED
- case XYFT_L: s = "labeled"; break;
- #endif /* CK_LABELED */
- #endif /* MAC */
- #endif /* VMS */
- default: s = "unknown"; break;
- }
- return(s);
- }
- #ifndef NOXFER
- VOID /* SHOW TRANSFER */
- shoxfer() {
- extern int docrc, usepipes, xfrxla, whereflg;
- extern char * xfrmsg;
- printf("\n");
- printf(" Transfer Bell: %s\n",showoff(xfrbel));
- printf(" Transfer Interruption: %s\n",showoff(xfrint));
- printf(" Transfer Cancellation: %s\n",showoff(xfrcan));
- #ifndef NOCSETS
- printf(" Transfer Translation: %s\n",showoff(xfrxla));
- printf(" Transfer Character-set: ");
- if (tcharset == TC_TRANSP)
- printf("Transparent\n");
- else
- printf("%s\n",tcsinfo[tcharset].keyword);
- #endif /* NOCSETS */
- printf(" Transfer CRC-calculation: %s\n",showoff(docrc));
- printf(" Transfer Display: ");
- switch (fdispla) {
- case XYFD_N: printf("%s\n","none"); break;
- case XYFD_R: printf("%s\n","serial"); break;
- case XYFD_C: printf("%s\n","fullscreen"); break;
- case XYFD_S: printf("%s\n","crt"); break;
- case XYFD_B: printf("%s\n","brief"); break;
- case XYFD_G: printf("%s\n","gui"); break;
- }
- printf(" Transfer Message: %s\n", xfrmsg ? xfrmsg : "(none)");
- printf(" Transfer Locking-shift: ");
- if (lscapu == 2) {
- printf("forced");
- } else {
- printf("%s", (lscapr ? "enabled" : "disabled"));
- if (lscapr) printf(",%s%s", (lscapu ? " " : " not "), "used");
- }
- printf("\n Transfer Mode: %s\n",
- xfermode == XMODE_A ?
- "automatic" :
- "manual"
- );
- printf(" Transfer Pipes: %s\n", showoff(usepipes));
- printf(" Transfer Protocol: %s\n",ptab[protocol].p_name);
- printf(" Transfer Report: %s\n",showoff(whereflg));
- printf(" Transfer Slow-start: %s\n",showoff(slostart));
- printf("\n");
- }
- #endif /* NOXFER */
- VOID
- shoflow() {
- int i, x;
- extern int cxflow[], cxtype, ncxname, nfloname, autoflow;
- extern char * cxname[];
- printf("\nConnection type: %s\n",cxname[cxtype]);
- if (autoflow) {
- printf("Current flow-control: %s\n", floname[cxflow[cxtype]]);
- printf("Switches automatically: yes\n");
- } else {
- printf("Current flow-control: %s\n", floname[flow]);
- printf("Switches automatically: no\n");
- }
- printf("\nDefaults by connection type:\n");
- debug(F111,"shoflow cxtype",cxname[cxtype],cxtype);
- debug(F101,"shoflow flow","",flow);
- for (i = 0; i < ncxname; i++) {
- #ifdef NOLOCAL
- if (i > 0) break;
- #endif /* NOLOCAL */
- #ifndef NETCONN
- if (i > 2) break;
- #endif /* NETCONN */
- #ifndef DECNET
- if (i == CXT_DECNET) continue;
- #endif /* DECNET */
- #ifndef DECNET
- #ifndef SUPERLAT
- if (i == CXT_LAT) continue;
- #endif /* SUPERLAT */
- #endif /* DECNET */
- #ifndef CK_NETBIOS
- if (i == CXT_NETBIOS) continue;
- #endif /* CK_NETBIOS */
- #ifndef NPIPE
- if (i == CXT_NPIPE) continue;
- #endif /* NPIPE */
- #ifndef NETCMD
- if (i == CXT_PIPE) continue;
- #endif /* NETCMD */
- #ifndef ANYX25
- if (i == CXT_X25) continue;
- #endif /* ANYX25 */
- x = cxflow[i];
- debug(F101,"shoflow x","",x);
- if (x < nfloname)
- printf(" %-14s: %s\n",cxname[i],floname[x]);
- else
- printf(" %-14s: (%d)\n",cxname[i],x);
- }
- printf("\n");
- }
- #ifndef NOLOCAL
- #ifdef ANYX25
- int
- shox25(n) int n; {
- if (nettype == NET_SX25) {
- printf("SunLink X.25 V%d.%d",x25ver / 10,x25ver % 10);
- if (ttnproto == NP_X3) printf(", PAD X.3, X.28, X.29 protocol,");
- printf("\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" Reverse charge call %s",
- revcall ? "selected" : "not selected");
- printf (", Closed user group ");
- if (closgr > -1)
- printf ("%d",closgr);
- else
- printf ("not selected");
- printf("\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" Call user data %s.\n", cudata ? udata : "not selected");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- } else if (nettype == NET_VX25) {
- if (ttnproto == NP_X3) printf(", PAD X.3, X.28, X.29 protocol,");
- printf("\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" Reverse charge call %s",
- revcall ? "selected" : "not selected");
- printf (", Closed user group [unsupported]");
- if (closgr > -1)
- printf ("%d",closgr);
- else
- printf ("not selected");
- printf (",");
- printf("\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" Call user data %s.\n", cudata ? udata : "not selected");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- } else if (nettype == NET_IX25) {
- printf("AIX NPI X.25\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf("\n Reverse charge call %s",
- revcall ? "selected" : "not selected");
- printf (", Closed user group [unsupported]");
- if (closgr > -1)
- printf ("%d",closgr);
- else
- printf ("not selected");
- printf (",");
- printf("\n Call user data %s.\n", cudata ? udata : "not selected");
- }
- return(n);
- }
- #ifndef IBMX25
- int
- shopad(n) int n; {
- int i;
- printf("\nX.3 PAD Parameters:\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- for (i = 0; i < npadx3; i++) {
- printf(" [%d] %s %d\n",padx3tab[i].kwval,padx3tab[i].kwd,
- padparms[padx3tab[i].kwval]);
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- }
- return(n);
- }
- #endif /* IBMX25 */
- #endif /* ANYX25 */
- VOID
- shoparc() {
- extern int reliable, stopbits, clsondisc;
- int i; char *s;
- long zz;
- #ifdef NEWFTP
- if (ftpisconnected()) {
- shoftp(1);
- printf("\n");
- }
- #endif /* NEWFTP */
- printf("Communications Parameters:\n");
- if (network
- #ifdef IKSD
- || inserver
- #endif /* IKSD */
- ) {
- printf(" Network Host: %s%s",ttname,
- (reliable == SET_ON || (reliable == SET_AUTO && !local)
- #ifdef TN_COMPORT
- && !istncomport()
- #endif /* TN_COMPORT */
- #ifdef IKSD
- || inserver
- #endif /* IKSD */
- ) ? " (reliable)" : "");
- #ifdef TN_COMPORT
- if (istncomport()) {
- int modemstate;
- char * oflow, * iflow = "", * parity, * stopsize, * signature;
- int baud = tnc_get_baud();
- switch (tnc_get_oflow()) {
- case TNC_CTL_OFLOW_NONE:
- oflow = "none";
- break;
- case TNC_CTL_OFLOW_XON_XOFF:
- oflow = "xon/xoff";
- break;
- case TNC_CTL_OFLOW_RTS_CTS:
- oflow = "rts/cts";
- break;
- case TNC_CTL_OFLOW_DCD:
- oflow = "dcd";
- break;
- case TNC_CTL_OFLOW_DSR:
- oflow = "dsr";
- break;
- default:
- oflow = "(unknown)";
- }
- switch (tnc_get_iflow()) {
- case TNC_CTL_IFLOW_NONE:
- iflow = "none";
- break;
- case TNC_CTL_IFLOW_XON_XOFF:
- iflow = "xon/xoff";
- break;
- case TNC_CTL_IFLOW_RTS_CTS:
- iflow = "rts/cts";
- break;
- case TNC_CTL_IFLOW_DTR:
- break;
- default:
- iflow = oflow;
- }
- switch (tnc_get_parity()) {
- case TNC_PAR_NONE:
- parity = "none";
- break;
- case TNC_PAR_ODD:
- parity = "odd";
- break;
- case TNC_PAR_EVEN:
- parity = "even";
- break;
- case TNC_PAR_MARK:
- parity = "mark";
- break;
- case TNC_PAR_SPACE:
- parity = "space";
- break;
- default:
- parity = "(unknown)";
- }
- switch (tnc_get_stopsize()) {
- case TNC_SB_1:
- stopsize = "1";
- break;
- case TNC_SB_1_5:
- stopsize = "1.5";
- break;
- case TNC_SB_2:
- stopsize = "2";
- break;
- default:
- stopsize = "(unknown)";
- }
- signature = (char *)tnc_get_signature();
- printf("\n Signature : %s\n",signature?signature:"");
- if (baud <= 0)
- printf(" Speed : (unknown)\n");
- else
- printf(" Speed : %d\n", baud);
- printf(" Outbound Flow Control: %s\n", oflow);
- printf(" Inbound Flow Control : %s\n", iflow);
- printf(" Parity : %s\n", parity);
- printf(" Data Size : %d\n", tnc_get_datasize());
- printf(" Stop Bits : %s\n", stopsize);
- printf(" DTR Signal : %d\n", tnc_get_dtr_state());
- printf(" RTS Signal : %d\n", tnc_get_rts_state());
- printf(" Modem State:\n");
- modemstate = tnc_get_ms();
- if (modemstate & TNC_MS_EDGE_RING)
- printf(" Trailing Edge Ring Detector On\n");
- else
- printf(" Trailing Edge Ring Detector Off\n");
- if (modemstate & TNC_MS_CTS_SIG)
- printf(" CTS Signal On\n");
- else
- printf(" CTS Signal Off\n");
- if (modemstate & TNC_MS_DSR_SIG)
- printf(" DSR Signal On\n");
- else
- printf(" DSR Signal Off\n");
- if (modemstate & TNC_MS_RI_SIG)
- printf(" Ring Indicator On\n");
- else
- printf(" Ring Indicator Off\n");
- if (modemstate & TNC_MS_RLSD_SIG)
- printf(" RLSD (CD) Signal On\n");
- else
- printf(" RLSD (CD) Signal Off\n");
- printf("\n");
- }
- #endif /* TN_COMPORT */
- } else {
- printf(" %s: %s%s, speed: ",
- #ifdef OS2
- "Port",
- #else
- "Line",
- #endif /* OS2 */
- ttname,
- #ifdef CK_TTYFD
- (local &&
- #ifdef VMS
- vmsttyfd() < 0
- #else
- ttyfd == -1
- #endif /* VMS */
- ) ?
- " (closed)" :
- (reliable == SET_ON ? " (reliable)" : "")
- #else
- ""
- #endif /* CK_TTYFD */
- );
- if (
- #ifdef CK_TTYFD
- #ifdef VMS
- vmsttyfd() < 0
- #else
- ttyfd == -1
- #endif /* VMS */
- ||
- #endif /* CK_TTYFD */
- (zz = ttgspd()) < 0) {
- printf("unknown");
- } else {
- if (speed == 8880) printf("75/1200");
- else if (speed == 134) printf("134.5");
- else printf("%ld",zz);
- }
- }
- if (network
- #ifdef IKSD
- || inserver
- #endif /* IKSD */
- )
- printf("\n Mode: ");
- else
- printf(", mode: ");
- if (local) printf("local"); else printf("remote");
- if (network == 0
- #ifdef IKSD
- && !inserver
- #endif/* IKSD */
- ) {
- #ifdef CK_TAPI
- if (tttapi && !tapipass )
- printf(", modem: %s","TAPI");
- else
- #endif /* CK_TAPI */
- printf(", modem: %s",gmdmtyp());
- } else {
- #ifdef NETCONN
- if (nettype == NET_TCPA) printf(", TCP/IP");
- if (nettype == NET_TCPB) printf(", TCP/IP");
- if (nettype == NET_DEC) {
- if (ttnproto == NP_LAT) printf(", DECnet LAT");
- else if ( ttnproto == NP_CTERM ) printf(", DECnet CTERM");
- else printf(", DECnet");
- }
- if (nettype == NET_SLAT) printf(", Meridian Technologies' SuperLAT");
- #ifdef NETFILE
- if (nettype == NET_FILE) printf(", local file");
- #endif /* NETFILE */
- #ifdef NETCMD
- if (nettype == NET_CMD) printf(", pipe");
- #endif /* NETCMD */
- #ifdef NETPTY
- if (nettype == NET_PTY) printf(", pseudoterminal");
- #endif /* NETPTY */
- #ifdef NETDLL
- if (nettype == NET_DLL) printf(", dynamic load library");
- #endif /* NETDLL */
- if (nettype == NET_PIPE) printf(", Named Pipes");
- #ifdef SSHBUILTIN
- if (nettype == NET_SSH)
- printf(", Secure Shell protocol (SECURE)");
- #endif /* SSHBUILTIN */
- #ifdef ANYX25
- if (shox25(0) < 0) return;
- #endif /* ANYX25 */
- if (IS_TELNET()) {
- printf(", telnet protocol");
- if (0
- #ifdef CK_ENCRYPTION
- || ck_tn_encrypting() && ck_tn_decrypting()
- #endif /* CK_ENCRYPTION */
- #ifdef CK_SSL
- || tls_active_flag || ssl_active_flag
- #endif /* CK_SSL */
- )
- printf(" (SECURE)");
- }
- #ifdef RLOGCODE
- else if (ttnproto == NP_RLOGIN || ttnproto == NP_K4LOGIN ||
- ttnproto == NP_K5LOGIN)
- printf(", rlogin protocol");
- else if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN)
- printf(", rlogin protocol (SECURE)");
- #endif /* RLOGCODE */
- #ifdef CK_KERBEROS
- #ifdef KRB5
- else if (ttnproto == NP_K5U2U)
- printf(", Kerberos 5 User to User protocol (SECURE)");
- #endif /* KRB5 */
- #endif /* CK_KERBEROS */
- #endif /* NETCONN */
- }
- printf("\n");
- if (hwparity && local && !network)
- s = parnam((char)hwparity);
- else
- s = parnam((char)parity);
- printf(" Parity: %s%s",hwparity ? "hardware " : "", s);
- #ifndef NOLOCAL
- if (local && !network) {
- int sb;
- char c;
- c = s[0];
- if (islower(c)) c = toupper(c);
- sb = stopbits;
- if (sb < 1) {
- sb = (speed > 0 && speed <= 110L) ? 2 : 1;
- printf(", stop-bits: (default)");
- } else {
- printf(", stop-bits: %d",sb);
- }
- if (hwparity)
- printf(" (8%c%d)",c,sb);
- else if (parity)
- printf(" (7%c%d)",c,sb);
- else
- printf(" (8N%d)",sb);
- printf("\n D");
- } else
- printf(", d");
- #endif /* NOLOCAL */
- printf("uplex: %s, ", duplex ? "half" : "full");
- debug(F101,"shoparp flow","",flow);
- printf("flow: %s", floname[flow]);
- printf(", handshake: ");
- if (turn) printf("%d\n",turnch); else printf("none\n");
- #ifdef COMMENT
- if (local && !network) { /* SET CARRIER-WATCH */
- #endif /* COMMENT */
- if (carrier == CAR_OFF) s = "off";
- else if (carrier == CAR_ON) s = "on";
- else if (carrier == CAR_AUT) s = "auto";
- else s = "unknown";
- printf(" Carrier-watch: %s", s);
- if (carrier == CAR_ON) {
- if (cdtimo) printf(", timeout: %d sec", cdtimo);
- else printf(", timeout: none");
- }
- #ifdef COMMENT
- }
- #endif /* COMMENT */
- printf(", close-on-disconnect: %s\n",showoff(clsondisc));
- #ifdef UNIX /* UUCP lockfile, UNIX only */
- if (local) {
- #ifndef NOUUCP
- if (!network && haslock && *flfnam)
- printf(" Lockfile: %s",flfnam);
- #ifndef USETTYLOCK
- if (!network && haslock && lock2[0])
- printf("\n Secondary lockfile: %s",lock2);
- #endif /* USETTYLOCK */
- #else
- #ifdef QNX
- {
- extern int qnxportlock, qnxopencount();
- if (local)
- printf(" Qnx-port-lock: %s, Open count: %d",
- showoff(qnxportlock),
- qnxopencount()
- );
- else
- printf(" Qnx-port-lock: %s", showoff(qnxportlock));
- }
- #endif /* QNX */
- #endif /* NOUUCP */
- printf("\n");
- } else {
- char * s;
- s = ttglckdir();
- if (!s) s = "";
- printf(" Lockfile directory: %s\n", *s ? s : "(none)");
- }
- #endif /* UNIX */
- #ifndef MACOSX
- if (!local) {
- printf(" Typical port device name: %s\n",ttgtpn());
- }
- #endif /* MACOSX */
- if (local) {
- int i;
- i = parity ? 7 : 8;
- if (i == 8) i = (cmask == 0177) ? 7 : 8;
- printf(" Terminal bytesize: %d,",i);
- printf(" escape character: %d (^%c)\n",escape,ctl(escape));
- }
- }
- int
- shotcp(n) int n; {
- #ifdef TCPSOCKET
- if (nettype == NET_TCPA || nettype == NET_TCPB) {
- printf("SET TCP parameters:\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" Reverse DNS lookup: %s\n", showooa(tcp_rdns));
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #ifdef CK_DNS_SRV
- printf(" DNS Service Records lookup: %s\n", showooa(tcp_dns_srv));
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* CK_DNS_SRV */
- #ifndef NOTCPOPTS
- #ifdef SOL_SOCKET
- #ifdef SO_KEEPALIVE
- printf(" Keepalive: %s\n", showoff(tcp_keepalive));
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* SO_KEEPALIVE */
- #ifdef SO_LINGER
- printf(" Linger: %s", tcp_linger ? "on, " : "off\n" );
- if (tcp_linger) {
- if (tcp_linger_tmo)
- printf("%d x 10 milliseconds\n",tcp_linger_tmo);
- else
- printf("no timeout\n");
- }
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* SO_LINGER */
- #ifdef SO_DONTROUTE
- printf(" DontRoute: %s\n", tcp_dontroute ? "on" : "off" );
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* SO_DONTROUTE */
- #ifdef TCP_NODELAY
- printf(" Nodelay: %s\n", showoff(tcp_nodelay));
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* TCP_NODELAY */
- #ifdef SO_SNDBUF
- if (tcp_sendbuf <= 0)
- printf(" Send buffer: (default size)\n");
- else
- printf(" Send buffer: %d bytes\n", tcp_sendbuf);
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* SO_SNDBUF */
- #ifdef SO_RCVBUF
- if (tcp_recvbuf <= 0)
- printf(" Receive buffer: (default size)\n");
- else
- printf(" Receive buffer: %d bytes\n", tcp_recvbuf);
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* SO_RCVBUF */
- #endif /* SOL_SOCKET */
- #endif /* NOTCPOPTS */
- printf(" address: %s\n",tcp_address ? tcp_address : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- #ifndef NOHTTP
- printf(" http-proxy: %s\n",tcp_http_proxy ? tcp_http_proxy : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- #endif /* NOHTTP */
- #ifdef NT
- #ifdef CK_SOCKS
- printf(" socks-server: %s\n",tcp_socks_svr ? tcp_socks_svr : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- #ifdef CK_SOCKS_NS
- printf(" socks-name-server: %s\n",
- tcp_socks_ns ? tcp_socks_ns : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- #endif /* CK_SOCKS_NS */
- #endif /* CK_SOCKS */
- #endif /* NT */
- }
- #endif /* TCPSOCKET */
- return(n);
- }
- #ifdef TNCODE
- int
- shotopt(n) int n; {
- int opt;
- printf("%-21s %12s %12s %12s %12s\n\n",
- "Telnet Option","Me (client)","U (client)",
- "Me (server)","U (server)");
- n += 2;
- if (n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- for ( opt = TELOPT_FIRST; opt <= TELOPT_LAST; opt++) {
- switch (opt) {
- case TELOPT_AUTHENTICATION:
- case TELOPT_ENCRYPTION:
- case TELOPT_TTYPE:
- case TELOPT_NAWS:
- case TELOPT_BINARY:
- case TELOPT_NEWENVIRON:
- case TELOPT_SNDLOC:
- case TELOPT_XDISPLOC:
- case TELOPT_SGA:
- case TELOPT_ECHO:
- case TELOPT_KERMIT:
- case TELOPT_START_TLS:
- case TELOPT_FORWARD_X:
- case TELOPT_COMPORT:
- break;
- default:
- continue;
- }
- printf("%03d %-17s ",
- opt, TELOPT(opt)
- );
- printf("%12s %12s ",
- TELOPT_MODE(TELOPT_DEF_C_ME_MODE(opt)),
- TELOPT_MODE(TELOPT_DEF_C_U_MODE(opt))
- );
- printf("%12s %12s\n",
- TELOPT_MODE(TELOPT_DEF_S_ME_MODE(opt)),
- TELOPT_MODE(TELOPT_DEF_S_U_MODE(opt))
- );
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- if (sstelnet)
- printf("%21s %12s %12s %12s %12s\n",
- "",
- "",
- "",
- (TELOPT_ME(opt)?"WILL":"WONT"),
- (TELOPT_U(opt)?"DO":"DONT")
- );
- else
- printf("%21s %12s %12s %12s %12s\n",
- "",
- (TELOPT_ME(opt)?"WILL":"WONT"),
- (TELOPT_U(opt)?"DO":"DONT"),
- "",
- ""
- );
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- }
- return(n);
- }
- int
- shotel(n) int n; {
- extern int tn_duplex;
- #ifdef CK_ENVIRONMENT
- extern int tn_env_flg;
- extern char tn_env_acct[];
- extern char tn_env_job[];
- extern char tn_env_prnt[];
- extern char tn_env_sys[];
- extern char * tn_env_uservar[8][2];
- int x;
- #endif /* CK_ENVIRONMENT */
- #ifdef CK_SNDLOC
- extern char * tn_loc;
- #endif /* CK_SNDLOC */
- printf("SET TELNET parameters:\n echo: %s\n NVT newline-mode: ",
- tn_duplex ? "local" : "remote");
- switch (tn_nlm) {
- case TNL_CRNUL: printf("%s\n","off (cr-nul)"); break;
- case TNL_CRLF: printf("%s\n","on (cr-lf)"); break;
- case TNL_CR: printf("%s\n","raw (cr)"); break;
- case TNL_LF: printf("%s\n","(lf)"); break;
- }
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- #ifdef CK_AUTHENTICATION
- {
- int type = ck_tn_authenticated();
- printf(" authentication: ");
- switch (sstelnet ?
- TELOPT_U_MODE(TELOPT_AUTHENTICATION) :
- TELOPT_ME_MODE(TELOPT_AUTHENTICATION)
- ) {
- case TN_NG_AC: printf( "accepted " ); break;
- case TN_NG_RF: printf( "refused " ); break;
- case TN_NG_RQ: printf( "requested"); break;
- case TN_NG_MU: printf( "required "); break;
- }
- #ifdef CK_SSL
- if ((ssl_active_flag || tls_active_flag) &&
- ck_tn_auth_valid() == AUTH_VALID &&
- (!TELOPT_U(TELOPT_AUTHENTICATION) ||
- type == AUTHTYPE_NULL ||
- type == AUTHTYPE_AUTO))
- printf(" in use: X.509 certificate\n");
- else
- #endif /* CK_SSL */
- printf(" in use: %s\n",AUTHTYPE_NAME(type));
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- if (forward_flag)
- printf(" credentials forwarding requested %s\n",
- forwarded_tickets ? "and completed" :
- "but not completed");
- else
- printf(" credentials forwarding disabled\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- }
- #endif /* CK_AUTHENTICATION */
- #ifdef CK_ENCRYPTION
- {
- int i,x;
- int e_type = ck_tn_encrypting();
- int d_type = ck_tn_decrypting();
- char * e_str = NULL, * d_str = NULL;
- static struct keytab * tnetbl = NULL;
- static int ntnetbl = 0;
- x = ck_get_crypt_table(&tnetbl,&ntnetbl);
- for (i = 0; i < ntnetbl; i++) {
- if (e_type == tnetbl[i].kwval)
- e_str = tnetbl[i].kwd;
- if (d_type == tnetbl[i].kwval)
- d_str = tnetbl[i].kwd;
- }
- printf(" encryption: ");
- switch (TELOPT_ME_MODE(TELOPT_ENCRYPTION)) {
- /* This should be changed to report both ME and U modes */
- case TN_NG_AC: printf( "accepted " ); break;
- case TN_NG_RF: printf( "refused " ); break;
- case TN_NG_RQ: printf( "requested"); break;
- case TN_NG_MU: printf( "required "); break;
- }
- printf(" in use: ");
- switch ((e_type ? 1 : 0) | (d_type ? 2 : 0)) {
- case 0:
- printf("plain text in both directions");
- break;
- case 1:
- printf("%s output, plain text input",e_str);
- break;
- case 2:
- printf("plain text output, %s input",d_str);
- break;
- case 3:
- printf("%s output, %s input",e_str,d_str);
- break;
- }
- printf("\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- }
- #endif /* CK_ENCRYPTION */
- #ifdef IKS_OPTION
- printf(" kermit: ");
- switch (TELOPT_U_MODE(TELOPT_KERMIT)) {
- case TN_NG_AC: printf( "u, accepted; " ); break;
- case TN_NG_RF: printf( "u, refused; " ); break;
- case TN_NG_RQ: printf( "u, requested; "); break;
- case TN_NG_MU: printf( "u, required; "); break;
- }
- switch (TELOPT_ME_MODE(TELOPT_KERMIT)) {
- case TN_NG_AC: printf( "me, accepted; " ); break;
- case TN_NG_RF: printf( "me, refused; " ); break;
- case TN_NG_RQ: printf( "me, requested; "); break;
- case TN_NG_MU: printf( "me, required; "); break;
- }
- if (TELOPT_U(TELOPT_KERMIT))
- printf(" u, %s",
- TELOPT_SB(TELOPT_KERMIT).kermit.u_start ?
- "started" :
- "stopped"
- );
- else
- printf(" u, n/a");
- if (TELOPT_ME(TELOPT_KERMIT))
- printf(" me, %s;",
- TELOPT_SB(TELOPT_KERMIT).kermit.me_start ?
- "started" :
- "stopped"
- );
- else
- printf(" me, n/a;");
- printf("\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- #endif /* IKS_OPTION */
- printf(" BINARY newline-mode: ");
- switch (tn_b_nlm) {
- case TNL_CRNUL: printf("%s\n","off (cr-nul)"); break;
- case TNL_CRLF: printf("%s\n","on (cr-lf)"); break;
- case TNL_CR: printf("%s\n","raw (cr)"); break;
- case TNL_LF: printf("%s\n","(lf)"); break;
- }
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" binary-mode: ");
- switch (TELOPT_U_MODE(TELOPT_BINARY)) {
- case TN_NG_AC: printf( "u, accepted; " ); break;
- case TN_NG_RF: printf( "u, refused; " ); break;
- case TN_NG_RQ: printf( "u, requested; "); break;
- case TN_NG_MU: printf( "u, required; "); break;
- }
- switch (TELOPT_ME_MODE(TELOPT_BINARY)) {
- case TN_NG_AC: printf( "me, accepted; " ); break ;
- case TN_NG_RF: printf( "me, refused; " ); break;
- case TN_NG_RQ: printf( "me, requested; "); break;
- case TN_NG_MU: printf( "me, required; "); break;
- }
- printf("u, %s; me, %s\n",
- TELOPT_U(TELOPT_BINARY) ? "BINARY" : "NVT",
- TELOPT_ME(TELOPT_BINARY) ? "BINARY" : "NVT"
- );
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" binary-transfer-mode: %s\n",showoff(tn_b_xfer));
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" bug binary-me-means-u-too: %s\n",showoff(tn_b_meu));
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" bug binary-u-means-me-too: %s\n",showoff(tn_b_ume));
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" bug sb-implies-will-do: %s\n",showoff(tn_sb_bug));
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" bug auth-krb5-des: %s\n",showoff(tn_auth_krb5_des_bug));
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" terminal-type: ");
- if (tn_term) {
- printf("%s\n",tn_term);
- } else {
- char *p;
- #ifdef OS2
- p = (tt_type >= 0 && tt_type <= max_tt) ?
- tt_info[tt_type].x_name :
- "UNKNOWN";
- #else
- p = getenv("TERM");
- #endif /* OS2 */
- if (p)
- printf("none (%s will be used)\n",p);
- else printf("none\n");
- }
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- #ifdef CK_ENVIRONMENT
- printf(" environment: %s\n", showoff(tn_env_flg));
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" ACCOUNT: %s\n",tn_env_acct);
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" DISPLAY: %s\n",(char *)tn_get_display() ?
- (char *)tn_get_display() : "");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" JOB : %s\n",tn_env_job);
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" PRINTER: %s\n",tn_env_prnt);
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- #ifndef NOSPL
- printf(" USER : %s\n",uidbuf);
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- #endif /* NOSPL */
- printf(" SYSTEM : %s\n",tn_env_sys);
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- for (x = 0; x < 8; x++) {
- if (tn_env_uservar[x][0] && tn_env_uservar[x][1]) {
- printf(" %-7s: %s\n",tn_env_uservar[x][0],
- tn_env_uservar[x][1]);
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- }
- }
- #endif /* CK_ENVIRONMENT */
- #ifdef CK_SNDLOC
- printf(" LOCATION: %s\n", tn_loc ? tn_loc : "");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- #endif /* CK_SNDLOC */
- #ifdef CK_FORWARD_X
- printf(" .Xauthority-file: %s\n", (char *)XauFileName() ?
- (char *)XauFileName() : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- #endif /* CK_FORWARD_X */
- return(n);
- }
- #endif /* TNCODE */
- #ifdef CK_NETBIOS
- static int
- shonb(n) int n; {
- printf("NETBIOS parameters:\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" API : %s\n",
- NetbeuiAPI ?
- "NETAPI.DLL - IBM Extended Services or Novell Netware Requester"
- : "ACSNETB.DLL - IBM Network Transport Services/2" ) ;
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" Local Name: [%s]\n", NetBiosName);
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- printf(" Adapter : %d\n", NetBiosAdapter);
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- if (NetBiosLSN > 0xFF) {
- printf(" Session : %d\n", NetBiosLSN);
- } else {
- printf(" Session : none active\n");
- }
- if (++n > cmd_rows - 3) if (!askmore()) return(-1); else n = 0;
- return(n);
- }
- #endif /* CK_NETBIOS */
- #ifndef NONET
- int
- shonet() {
- #ifndef NETCONN
- printf("\nNo networks are supported in this version of C-Kermit\n");
- #else
- #ifdef NOLOCAL
- printf("\nNo networks are supported in this version of C-Kermit\n");
- #else /* rest of this routine */
- int i, n = 4;
- #ifndef NODIAL
- if (nnetdir <= 1) {
- printf("\nNetwork directory: %s\n",netdir[0] ? netdir[0] : "(none)");
- n++;
- } else {
- int i;
- printf("\nNetwork directories:\n");
- for (i = 0; i < nnetdir; i++) {
- printf("%2d. %s\n",i,netdir[i]);
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- }
- }
- #endif /* NODIAL */
- #ifdef SSHCMD
- {
- extern char * sshcmd;
- printf("SSH COMMAND: %s\n",sshcmd ? sshcmd : "ssh -e none");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- }
- #endif /* SSHCMD */
- #ifdef OS2
- printf("\nNetwork availability:\n");
- #else
- printf("\nSupported networks:\n");
- #endif /* OS2 */
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #ifdef VMS
- #ifdef TCPWARE
- printf(" Process Software Corporation TCPware for OpenVMS");
- #else
- #ifdef MULTINET
- printf(" TGV MultiNet TCP/IP");
- #else
- #ifdef WINTCP
- printf(" WOLLONGONG WIN/TCP");
- #else
- #ifdef DEC_TCPIP
- {
- static $DESCRIPTOR(tcp_desc,"_TCP0:");
- int status;
- long devclass;
- static int itmcod = DVI$_DEVCLASS;
- #ifdef COMMENT
- status = LIB$GETDVI(&itmcod, 0, &tcp_desc, &devclass);
- #else
- /* Martin Zinser 9/96 */
- status = lib$getdvi(&itmcod, 0, &tcp_desc, &devclass);
- #endif /* COMMENT */
- if ((status & 1) && (devclass == DC$_SCOM))
- printf(" Process Software Corporation TCPware for OpenVMS");
- else
- #ifdef UCX50
- printf(" DEC TCP/IP Services for (Open)VMS 5.0");
- #else
- printf(" DEC TCP/IP Services for (Open)VMS");
- #endif /* UCX50 */
- }
- #else
- #ifdef CMU_TCPIP
- printf(" CMU-OpenVMS/IP");
- #else
- printf(" None");
- #endif /* CMU_TCPIP */
- #endif /* DEC_TCPIP */
- #endif /* WINTCP */
- #endif /* MULTINET */
- #endif /* TCPWARE */
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #ifdef TNCODE
- printf(", TELNET protocol\n\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- n = shotel(n);
- if (n < 0) return(0);
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* TNCODE */
- printf("\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf("\n");
- n = shotcp(++n);
- if (n < 0) return(0);
- #else /* Not VMS */
- #ifdef SUNX25
- printf(" SunLink X.25\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* SUNX25 */
- #ifdef STRATUSX25
- printf(" Stratus VOS X.25\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* STRATUSX25 */
- #ifdef IBMX25
- printf(" IBM AIX X.25\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* IBMX25 */
- #ifdef HPX25
- printf(" HP-UX X.25\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* HPX25 */
- #ifdef SSHBUILTIN
- if (ck_ssleay_is_installed())
- printf(" SSH V1 and V2 protocols\n");
- else
- printf(" SSH V1 and V2 protocols - not available\n");
- #endif /* SSHBUILTIN */
- #ifdef DECNET
- #ifdef OS2
- #ifdef NT
- if (dnet_avail)
- printf(" DECnet, LAT and CTERM protocols\n");
- else
- printf(" DECnet, LAT and CTERM protocols - not available\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #else /* NT */
- if (dnet_avail)
- printf(" DECnet, LAT protocol\n");
- else
- printf(" DECnet, LAT protocol - not available\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* NT */
- #else
- printf(" DECnet\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* OS2 */
- #endif /* DECNET */
- #ifdef NPIPE
- printf(" Named Pipes\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* NPIPE */
- #ifdef CK_NETBIOS
- if (netbiosAvail)
- printf(" NETBIOS\n");
- else
- printf(" NETBIOS - not available\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* CK_NETBIOS */
- #ifdef SUPERLAT
- if (slat_avail)
- printf(" SuperLAT\n");
- else
- printf(" SuperLAT - not available\n") ;
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* SUPERLAT */
- #ifdef TCPSOCKET
- if (
- #ifdef OS2
- tcp_avail
- #else
- 1
- #endif /* OS2 */
- ) {
- char ipaddr[16];
- if (getlocalipaddrs(ipaddr,16,0) < 0) {
- #ifdef OS2ONLY
- printf(" TCP/IP via %s\n", tcpname);
- #else
- printf(" TCP/IP\n");
- #endif /* OS2ONLY */
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- } else {
- int i = 1;
- #ifdef OS2ONLY
- printf(" TCP/IP [%16s] via %s\n", ipaddr, tcpname);
- #else
- printf(" TCP/IP [%16s]\n",ipaddr);
- #endif /* OS2ONLY */
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- while (getlocalipaddrs(ipaddr,16,i++) >= 0) {
- printf(" [%16s]\n",ipaddr);
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- }
- }
- if (nettype == NET_TCPB) {
- printf("\n");
- n = shotcp(++n);
- if (n < 0) return(0);
- #ifdef TNCODE
- printf("\n");
- n = shotel(++n);
- if (n < 0) return(0);
- #endif /* TNCODE */
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- }
- #ifdef OS2
- } else {
- printf(" TCP/IP - not available%s\n",tcpname[0] ? tcpname : "" );
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #endif /* OS2 */
- }
- #endif /* TCPSOCKET */
- #ifdef CK_NETBIOS
- if (netbiosAvail && nettype == NET_BIOS) {
- printf("\n") ;
- if ((n = shonb(++n)) < 0) return(0);
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- }
- #endif /* CK_NETBIOS */
- #endif /* VMS */
- printf("\nActive network connection:\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- if (network) {
- printf(" Host: %s",ttname);
- if ((nettype == NET_TCPA || nettype == NET_TCPB) && *ipaddr)
- printf(" [%s]",ipaddr);
- } else
- printf(" Host: none");
- printf(", via: ");
- if (nettype == NET_TCPA || nettype == NET_TCPB)
- printf("tcp/ip\n");
- else if (nettype == NET_SX25)
- printf("SunLink X.25\n");
- else if (nettype == NET_VX25)
- printf("Stratus VOS X.25\n");
- else if (nettype == NET_IX25)
- printf("IBM AIX X.25\n");
- else if (nettype == NET_HX25)
- printf("HP-UX X.25\n");
- else if (nettype == NET_DEC) {
- if ( ttnproto == NP_LAT )
- printf("DECnet LAT\n");
- else if ( ttnproto == NP_CTERM )
- printf("DECnet CTERM\n");
- else
- printf("DECnet\n");
- } else if (nettype == NET_PIPE)
- printf("Named Pipes\n");
- else if (nettype == NET_BIOS)
- printf("NetBIOS\n");
- else if (nettype == NET_SLAT)
- printf("SuperLAT\n");
- #ifdef NETFILE
- else if ( nettype == NET_FILE )
- printf("local file\n");
- #endif /* NETFILE */
- #ifdef NETCMD
- else if ( nettype == NET_CMD )
- printf("pipe\n");
- #endif /* NETCMD */
- #ifdef NETPTY
- else if ( nettype == NET_PTY )
- printf("pseudoterminal\n");
- #endif /* NETPTY */
- #ifdef NETDLL
- else if ( nettype == NET_DLL )
- printf("dynamic link library\n");
- #endif /* NETDLL */
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- #ifdef ANYX25
- if ((nettype == NET_SX25) ||
- (nettype == NET_VX25) ||
- (nettype == NET_IX25))
- if ((n = shox25(n)) < 0) return(0);
- #endif /* ANYX25 */
- #ifdef SSHBUILTIN
- if (nettype == NET_SSH) {
- printf("Secure Shell protocol\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- }
- #endif /* SSHBUILTIN */
- if (nettype == NET_TCPA || nettype == NET_TCPB) {
- #ifdef RLOGCODE
- if (ttnproto == NP_RLOGIN) {
- printf(" LOGIN (rlogin) protocol\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- }
- #ifdef CK_KERBEROS
- else if (ttnproto == NP_K4LOGIN) {
- printf(" Kerberos 4 LOGIN (klogin) protocol\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- }
- else if (ttnproto == NP_EK4LOGIN) {
- printf(" Encrypted Kerberos 4 LOGIN (eklogin) protocol\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- }
- else if (ttnproto == NP_K5LOGIN) {
- printf(" Kerberos 5 LOGIN (klogin) protocol\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- }
- else if (ttnproto == NP_EK5LOGIN) {
- printf(" Encrypted Kerberos 5 LOGIN (eklogin) protocol\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- }
- #endif /* CK_KERBEROS */
- #endif /* RLOGCODE */
- #ifdef CK_KERBEROS
- if (ttnproto == NP_K5U2U) {
- printf(" Kerberos 5 User to User protocol\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- }
- #endif /* CK_KERBEROS */
- #ifdef TNCODE
- if (IS_TELNET()) {
- printf(" TELNET protocol\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(" Echoing is currently %s\n",duplex ? "local" : "remote");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- }
- #endif /* TNCODE */
- if (ttnproto == NP_TCPRAW) {
- printf(" Raw TCP socket\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- }
- }
- printf("\n");
- #endif /* NOLOCAL */
- #endif /* NETCONN */
- return(0);
- }
- #endif /* NONET */
- #ifndef NODIAL
- VOID
- shodial() {
- if (mdmtyp >= 0 || local != 0) doshodial();
- }
- VOID
- shods(s) char *s; { /* Show a dial-related string */
- char c;
- if (s == NULL || !(*s)) { /* Empty? */
- printf("(none)\n");
- } else { /* Not empty. */
- while ((c = *s++)) /* Can contain controls */
- if (c == '\\') /* a backslash */
- printf("\\\\");
- else if (c > 31 && c < 127) {
- putchar(c);
- } else
- printf("\\{%d}",c);
- printf("\n");
- }
- }
- int
- doshodial() {
- int i, n = 2;
- printf(" Dial status: %d", dialsta);
- #ifdef BIGBUFOK
- if (dialsta > 90)
- printf(" = Unknown error");
- else if (dialsta < 0)
- printf(" = (none)");
- else if (dialsta < 35 && dialmsg[dialsta])
- printf(" = %s", dialmsg[dialsta]);
- #endif /* BIGBUFOK */
- n++;
- if (ndialdir <= 1) {
- printf("\n Dial directory: %s\n",dialdir[0] ? dialdir[0] : "(none)");
- } else {
- int i;
- printf("\n Dial directories:\n");
- for (i = 0; i < ndialdir; i++)
- printf("%2d. %s\n",i+1,dialdir[i]);
- n += ndialdir;
- }
- printf(" Dial method: ");
- if (dialmauto) printf("auto ");
- else if (dialmth == XYDM_D) printf("default");
- else if (dialmth == XYDM_P) printf("pulse ");
- else if (dialmth == XYDM_T) printf("tone ");
- printf(" Dial sort: %s\n",dialsrt ? "on" : "off");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(" Dial hangup: %s Dial display: %s\n",
- dialhng ? "on " : "off", dialdpy ? "on" : "off");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- if (dialrtr > 0) {
- printf(" Dial retries: %-12d Dial interval: %d\n",
- dialrtr, dialint);
- } else {
- printf(" Dial retries: (auto) Dial interval: %d\n", dialint);
- }
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(" Dial timeout: ");
- #ifdef CK_TAPI
- if (tttapi && !tapipass)
- printf("(tapi)");
- else
- #endif /* CK_TAPI */
- if (dialtmo > 0)
- printf("%4d sec", dialtmo);
- else
- printf("0 (auto)");
- printf(" Redial number: %s\n",dialnum ? dialnum : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(" Dial confirmation: %s Dial convert-directory: %s\n",
- dialcnf ? "on " : "off",
- dialcvt ? ((dialcvt == 1) ? "on" : "ask") : "off");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(" Dial ignore-dialtone: %s", dialidt ? "on " : "off");
- printf(" Dial pacing: %d\n",dialpace);
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(
- " Dial prefix: %s\n", dialnpr ? dialnpr : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(
- " Dial suffix: %s\n", dialsfx ? dialsfx : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(
- " Dial country-code: %-12s", diallcc ? diallcc : "(none)");
- printf("Dial connect: %s", dialcon ? ((dialcon == 1) ? "on" : "auto")
- : "off");
- if (dialcon != CAR_OFF)
- printf(" %s", dialcq ? "quiet" : "verbose");
- printf(
- "\n Dial area-code: %-12s", diallac ? diallac : "(none)");
- n++;
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf("Dial restrict: ");
- if (dialrstr == 5) printf("international\n");
- else if (dialrstr == 4) printf("long-distance\n");
- else if (dialrstr == 2) printf("local\n");
- else if (dialrstr == 6) printf("none\n");
- else printf("?\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(" Dial lc-area-codes: ");
- if (nlocalac == 0)
- printf("(none)");
- else
- for (i = 0; i < nlocalac; i++)
- printf("%s ", diallcac[i]);
- printf(
- "\n Dial lc-prefix: %s\n", diallcp ? diallcp : "(none)");
- n++;
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(
- " Dial lc-suffix: %s\n", diallcs ? diallcs : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(
- " Dial ld-prefix: %s\n", dialldp ? dialldp : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(
- " Dial ld-suffix: %s\n", diallds ? diallds : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(
- " Dial force-long-distance %s\n", showoff(dialfld));
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(
- " Dial intl-prefix: %s\n", dialixp ? dialixp : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(
- " Dial intl-suffix: %s\n", dialixs ? dialixs : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(
- " Dial toll-free-area-code: ");
- if (ntollfree == 0)
- printf("(none)");
- else
- for (i = 0; i < ntollfree; i++)
- printf("%s ", dialtfc[i]);
- printf("\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(
- " Dial pulse-countries: ");
- if (ndialpucc == 0)
- printf("(none)");
- else
- for (i = 0; i < ndialpucc; i++)
- printf("%s ", dialpucc[i]);
- printf("\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(
- " Dial tone-countries: ");
- if (ndialtocc == 0)
- printf("(none)");
- else
- for (i = 0; i < ndialtocc; i++)
- printf("%s ", dialtocc[i]);
- printf("\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(
- " Dial toll-free-prefix: %s\n",
- dialtfp ? dialtfp :
- (dialldp ? dialldp : "(none)")
- );
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(" Dial pbx-exchange: ");
- if (ndialpxx == 0)
- printf("(none)");
- else
- for (i = 0; i < ndialpxx; i++)
- printf("%s ", dialpxx[i]);
- printf("\n");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(
- " Dial pbx-inside-prefix: %s\n", dialpxi ? dialpxi : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(
- " Dial pbx-outside-prefix: %s\n", dialpxo ? dialpxo : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return(0); else n = 0;
- printf(
- " Dial macro: %s\n", dialmac ? dialmac : "(none)");
- return(0);
- }
- #endif /* NODIAL */
- #endif /* NOLOCAL */
- /* Show File Parameters */
- static char *
- pathval(x) int x; {
- switch (x) {
- case PATH_OFF: return("off");
- case PATH_ABS: return("absolute");
- case PATH_REL: return("relative");
- case PATH_AUTO: return("auto");
- default: return("unknown");
- }
- }
- VOID
- shofil() {
- char *s; int i = 0, n = 1;
- extern char * ifdnam[];
- extern int wildena;
- #ifdef UNIX
- extern int wildxpand;
- #endif /* UNIX */
- extern char * snd_move, * snd_rename, * rcv_move, * rcv_rename;
- #ifdef PATTERNS
- extern int patterns;
- #endif /* PATTERNS */
- extern char * rfspec, * sfspec;
- #ifdef UNIX
- extern int zobufsize, zofbuffer, zofblock;
- #endif /* UNIX */
- #ifdef CK_CTRLZ
- extern int eofmethod;
- #endif /* CK_CTRLZ */
- printf("\n");
- #ifdef VMS
- printf(" File record-Length: %5d\n",frecl);
- n++;
- #endif /* VMS */
- #ifndef NOXFER
- printf(" Transfer mode: %s\n",
- xfermode == XMODE_A ?
- "automatic" :
- "manual"
- );
- n++;
- #ifdef PATTERNS
- printf(" File patterns: %s", showooa(patterns));
- if (xfermode == XMODE_M && patterns)
- printf(" (but disabled by TRANSFER-MODE MANUAL)");
- else if (patterns)
- printf(" (SHOW PATTERNS for list)");
- printf("\n");
- n++;
- #endif /* PATTERNS */
- if (filepeek)
- printf(" File scan: on %d\n", nscanfile);
- else
- printf(" File scan: off\n");
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- if (xfermode == XMODE_A)
- printf(" Default file type: %s\n",shoxm());
- else
- printf(" File type: %s\n",shoxm());
- n++;
- if (fncnv == XYFN_L)
- s = "literal";
- else if (fncnv == XYFN_C)
- s = "converted";
- else
- s = "(unknown)";
- printf(" File names: %s\n",s);
- n++;
- printf(" Send pathnames: %s\n", pathval(fnspath));
- n++;
- printf(" Receive pathnames: %s\n", pathval(fnrpath));
- n++;
- #ifdef UNIXOROSK
- printf(" Match dot files: %s\n", matchdot ? "yes" : "no");
- n++;
- #ifdef UNIX
- printf(" Wildcard-expansion: %s (%s)\n", showoff(wildena),
- wildxpand ? "shell" : "kermit");
- n++;
- #endif /* UNIX */
- #endif /* UNIXOROSK */
- printf(" File collision: ");
- for (i = 0; i < ncolx; i++)
- if (colxtab[i].kwval == fncact) break;
- printf("%s\n", (i == ncolx) ? "unknown" : colxtab[i].kwd);
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- printf(" File destination: %s\n",
- (dest == DEST_D) ? "disk" :
- ((dest == DEST_S) ? "screen" :
- ((dest == DEST_N) ? "nowhere" :
- "printer"))
- );
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- s = (keep >= 0 && keep <= 2) ? ifdnam[keep] : "keep";
- printf(" File incomplete: %s\n",s);
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- printf(" File bytesize: %d\n",(fmask == 0177) ? 7 : 8);
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- #ifndef NOCSETS
- printf(" File character-set: %s\n",fcsinfo[fcharset].keyword);
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- printf(" File default 7-bit: %s\n",fcsinfo[dcset7].keyword);
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- printf(" File default 8-bit: %s\n",fcsinfo[dcset8].keyword);
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- #ifdef UNICODE
- printf(" File UCS bom: %s\n",showoff(ucsbom));
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- printf(" File UCS byte-order: %s-endian\n",
- ucsorder ? "little" : "big");
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- printf(" Computer byteorder: %s-endian\n",
- byteorder ? "little" : "big");
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- #endif /* UNICODE */
- #endif /* NOCSETS */
- printf(" File end-of-line: ");
- i = feol;
- switch (feol) {
- case XYFA_C: printf("%s\n","cr"); break;
- case XYFA_L: printf("%s\n","lf"); break;
- case XYFA_2: printf("%s\n","crlf"); break;
- default: printf("%d\n",i);
- }
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- #endif /* NOXFER */
- #ifdef CK_CTRLZ
- printf(" File eof: %s\n", eofmethod ? "ctrl-z" : "length");
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- #endif /* CK_CTRLZ */
- #ifndef NOXFER
- #ifdef CK_TMPDIR
- printf(" File download-directory: %s\n", dldir ? dldir : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- #ifdef COMMENT
- i = 256;
- s = line;
- zzstring("\\v(tmpdir)",&s,&i);
- printf(" Temporary directory: %s\n", line);
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- #endif /* COMMENT */
- #endif /* CK_TMPDIR */
- #ifdef VMS
- {
- extern int vmssversions, vmsrversions;
- printf(" Send version-numbers: %s\n",showoff(vmssversions));
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- printf(" Receive version-numbers: %s\n",showoff(vmsrversions));
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- }
- #endif /* VMS */
- printf(" Send move-to: %s\n",
- snd_move ? snd_move : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- printf(" Send rename-to: %s\n",
- snd_rename ? snd_rename : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- printf(" Receive move-to: %s\n",
- rcv_move ? rcv_move : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- printf(" Receive rename-to: %s\n",
- rcv_rename ? rcv_rename : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- #endif /* NOXFER */
- #ifdef KERMRC
- printf(" Initialization file: %s\n", noinit ? "(none)" :
- #ifdef CK_SYSINI
- CK_SYSINI
- #else
- kermrc
- #endif /* CK_SYSINI */
- );
- #endif /* KERMRC */
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- if (k_info_dir) {
- printf(" Kermit doc files: %s\n", k_info_dir);
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- }
- #ifdef CKROOT
- s = zgetroot();
- printf(" Root set: %s\n", s ? s : "(none)");
- #endif /* CKROOT */
- #ifdef UNIX
- printf(" Disk output buffer: %d (writes are %s, %s)\n",
- zobufsize,
- zofbuffer ? "buffered" : "unbuffered",
- zofblock ? "blocking" : "nonblocking"
- );
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- #ifdef DYNAMIC
- printf(" Stringspace: %d\n", zsetfil(0,2));
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- printf(" Listsize: %d\n", zsetfil(0,4));
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- #endif /* DYNAMIC */
- #endif /* UNIX */
- #ifdef OS2ORUNIX
- printf(" Longest filename: %d\n", maxnam);
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- printf(" Longest pathname: %d\n", maxpath);
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- #endif /* OS2ORUNIX */
- printf(" Last file sent: %s\n", sfspec ? sfspec : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- printf(" Last file received: %s\n", rfspec ? rfspec : "(none)");
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- printf("\n Also see:\n");
- n++;
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- printf(" SHOW PROTOCOL, SHOW XFER");
- #ifdef CK_LABELED
- printf(", SHOW LABELED");
- #endif /* CK_LABELED */
- #ifdef PATTERNS
- printf(", SHOW PATTERNS");
- #endif /* PATTERNS */
- #ifdef STREAMING
- printf(", SHOW STREAMING");
- #endif /* STREAMING */
- #ifndef NOCSETS
- printf(", SHOW CHARACTER-SETS");
- #endif /* NOCSETS */
- printf("\n\n");
- }
- #ifndef NOXFER
- VOID
- shoparp() { /* Protocol */
- extern int docrc, skipbup;
- char *s;
- #ifdef CK_TIMERS
- extern int rttflg;
- #endif /* CK_TIMERS */
- printf("Protocol: %s\n",ptab[protocol].p_name);
- if (protocol == PROTO_K) {
- printf("\nProtocol Parameters: Send Receive");
- if (timef)
- printf("\n Timeout (used=%2d):%7d*%8d ", timint, rtimo, pkttim);
- else
- printf("\n Timeout (used=%2d):%7d%9d ", timint, rtimo, pkttim);
- #ifdef XFRCAN
- printf(" Cancellation: %s",showoff(xfrcan));
- if (xfrcan)
- printf(" %d %d", xfrchr, xfrnum);
- #endif /* XFRCAN */
- printf("\n Padding: %11d%9d", npad, mypadn);
- if (bctr == 4)
- printf(" Block Check: blank-free-2\n");
- else
- printf(" Block Check: %6d\n",bctr);
- printf( " Pad Character:%11d%9d", padch, mypadc);
- printf(" Delay: %6d\n",ckdelay);
- printf( " Pause: %11d%9d", pktpaus, pktpaus);
- printf(" Attributes: %s\n",showoff(atcapr));
- printf( " Packet Start: %11d%9d", mystch, stchr);
- printf(" Max Retries: %6d%s\n",
- maxtry,
- (maxtry == 0) ? " (unlimited)" : ""
- );
- printf( " Packet End: %11d%9d", seol, eol);
- if (ebqflg)
- printf(" 8th-Bit Prefix: '%c'",ebq);
- else
- printf(" 8th-Bit Prefix: ('%c' but not used)",ebq);
- printf( "\n Packet Length:%11d ", spmax);
- printf("%8d ", urpsiz);
- if (rptflg)
- printf(" Repeat Prefix: '%c'",rptq);
- else
- printf(" Repeat Prefix: ('%c' but not used)",rptq);
- printf( "\n Maximum Length: %9d%9d", maxsps, maxrps);
- printf(" Window Size:%7d set, %d used\n",wslotr,wmax);
- printf( " Buffer Size: %11d%9d", bigsbsiz, bigrbsiz);
- printf(" Locking-Shift: ");
- if (lscapu == 2) {
- printf("forced");
- } else {
- printf("%s", (lscapr ? "enabled" : "disabled"));
- if (lscapr) printf(",%s%s", (lscapu ? " " : " not "), "used");
- }
- printf("\n\n");
- if (!(s = ptab[protocol].h_b_init)) s = "";
- printf(" Auto-upload command (binary): ");
- if (*s) {
- shostrdef((CHAR *)s);
- printf("\n");
- } else {
- printf("(none)\n");
- }
- if (!(s = ptab[protocol].h_t_init)) s = "";
- printf(" Auto-upload command (text): ");
- if (*s) {
- shostrdef((CHAR *)s);
- printf("\n");
- } else {
- printf("(none)\n");
- }
- if (!(s = ptab[protocol].h_x_init)) s = "";
- printf(" Auto-server command: ");
- if (*s) {
- shostrdef((CHAR *)s);
- printf("\n");
- } else {
- printf("(none)\n");
- }
- tmpbuf[0] = NUL;
- #ifdef CK_TIMERS
- if (rttflg) {
- extern int mintime, maxtime;
- sprintf(tmpbuf," Packet timeouts: dynamic %d:%d", /* SAFE */
- mintime,
- maxtime);
- } else {
- sprintf(tmpbuf," Packet timeouts: fixed"); /* SAFE */
- }
- #endif /* CK_TIMERS */
- if (tmpbuf[0])
- printf("%-31s",tmpbuf);
- printf("Send backup: %s\n",showoff(!skipbup));
- printf(" Transfer mode: %s", xfermode == XMODE_A ?
- "automatic " :
- "manual "
- );
- printf(" Transfer slow-start: %s, crc: %s\n",
- showoff(slostart),
- showoff(docrc)
- );
- #ifdef PIPESEND
- {
- extern int usepipes;
- printf(" Transfer pipes: %s ",usepipes ? "on " : "off");
- }
- #endif /* PIPESEND */
- #ifndef NOCSETS
- printf(" Transfer character-set: ");
- if (tcharset == TC_TRANSP)
- printf("transparent\n");
- else
- printf("%s\n", tcsinfo[tcharset].keyword );
- #endif /* NOCSETS */
- #ifdef PIPESEND
- {
- extern char * sndfilter, * rcvfilter;
- printf(" Send filter: %s\n", sndfilter ? sndfilter : "(none)");
- printf(" Receive filter: %s\n", rcvfilter ? rcvfilter : "(none)");
- }
- #endif /* PIPESEND */
- printf("\nAlso see:\n");
- printf(" SHOW FILE, SHOW XFER");
- #ifdef CK_LABELED
- printf(", SHOW LABELED");
- #endif /* CK_LABELED */
- #ifdef PATTERNS
- printf(", SHOW PATTERNS");
- #endif /* PATTERNS */
- #ifdef STREAMING
- printf(", SHOW STREAMING");
- #endif /* STREAMING */
- #ifndef NOCSETS
- printf(", SHOW CHARACTER-SETS");
- #endif /* NOCSETS */
- }
- #ifdef CK_XYZ
- #ifdef XYZ_INTERNAL
- if (protocol != PROTO_K) {
- int i;
- int x;
- printf(" File type: %s\n", binary ? "binary" : "text");
- if (protocol == PROTO_Z) { /* Zmodem */
- printf(" Window size: ");
- if (ptab[protocol].winsize < 1)
- printf("none\n");
- else
- printf("%d\n",wslotr);
- #ifdef COMMENT
- printf(" Packet (frame) length: ");
- if (ptab[protocol].spktlen < 0)
- printf("none\n");
- else
- printf("%d\n",spmax);
- #endif /* COMMENT */
- } else {
- if (ptab[protocol].spktlen >= 1000)
- printf(" 1K packets\n");
- else
- printf(" 128-byte packets\n");
- }
- printf(" Pathname stripping when sending: %s\n",
- showoff(ptab[protocol].fnsp)
- );
- printf(" Pathname stripping when receiving: %s\n",
- showoff(ptab[protocol].fnrp)
- );
- printf(" Filename collision action: ");
- for (i = 0; i < ncolx; i++)
- if (colxtab[i].kwval == fncact) break;
- printf("%-12s", (i == ncolx) ? "unknown" : colxtab[i].kwd);
- printf("\n Escape control characters: ");
- x = ptab[protocol].prefix;
- if (x == PX_ALL)
- printf("all\n");
- else if (x == PX_CAU || x==PX_WIL)
- printf("minimal\n");
- else
- printf("none\n");
- if (!(s = ptab[protocol].h_b_init))
- s = "";
- printf(" Autoreceive command (binary): %s\n", *s ? s : "(none)");
- if (!(s = ptab[protocol].h_t_init))
- s = "";
- printf(" Autoreceive command (text): %s\n", *s ? s : "(none)");
- }
- #else
- #ifndef NOPUSH
- if (protocol != PROTO_K) {
- _PROTOTYP( VOID shoextern, (void) );
- printf("\nExecuted by external commands:\n\n");
- s = ptab[protocol].p_b_scmd;
- if (!s) s = "";
- printf(" SEND command (binary): %s\n", *s ? s : "(none)");
- s = ptab[protocol].p_t_scmd;
- if (!s) s = "";
- printf(" SEND command (text): %s\n", *s ? s : "(none)");
- s = ptab[protocol].p_b_rcmd;
- if (!s) s = "";
- printf(" RECEIVE command (binary): %s\n", *s ? s : "(none)");
- s = ptab[protocol].p_t_rcmd;
- if (!s) s = "";
- printf(" RECEIVE command (text): %s\n", *s ? s : "(none)");
- s = ptab[protocol].h_b_init;
- if (!s) s = "";
- printf(" Autoreceive command (binary): %s\n", *s ? s : "(none)");
- s = ptab[protocol].h_t_init;
- if (!s) s = "";
- printf(" Autoreceive command (text): %s\n", *s ? s : "(none)");
- (VOID) shoextern();
- }
- #endif /* NOPUSH */
- #endif /* XYZ_INTERNAL */
- #endif /* CK_XYZ */
- }
- #endif /* NOXFER */
- #ifndef NOCSETS
- /* Character-set items */
- extern int s_cset, r_cset, axcset[], afcset[];
- extern struct keytab xfrmtab[];
- VOID
- shoparl() {
- #ifdef COMMENT
- int i;
- /* Misleading... */
- printf("\nAvailable Languages:\n");
- for (i = 0; i < MAXLANG; i++) {
- printf(" %s\n",langs[i].description);
- }
- #else
- printf("\nLanguage-specific translation rules: %s\n",
- language == L_USASCII ? "none" : langs[language].description);
- shocharset();
- printf("\n\n");
- #endif /* COMMENT */
- }
- VOID
- shocharset() {
- int x;
- #ifdef COMMENT
- char * s = "Unknown";
- extern int xlatype;
- #endif /* COMMENT */
- #ifndef NOXFER
- extern int xfrxla;
- #endif /* NOXFER */
- debug(F101,"SHOW FILE CHAR","",fcharset);
- printf("\n");
- #ifndef NOXFER
- printf(" Transfer Translation: %s\n", showoff(xfrxla));
- if (!xfrxla) {
- printf(
- " Because transfer translation is off, the following are ignored:\n\n");
- }
- #endif /* NOXFER */
- printf(" File Character-Set: %s (%s), ",
- fcsinfo[fcharset].keyword,
- fcsinfo[fcharset].name
- );
- if ((x = fcsinfo[fcharset].size) == 128)
- printf("7-bit");
- else if (x == 256)
- printf("8-bit");
- else
- printf("multibyte");
- printf("\n");
- printf(" File Scan: %s\n",showoff(filepeek));
- printf(" Default 7bit-Character-Set: %s\n",fcsinfo[dcset7].keyword);
- printf(" Default 8bit-Character-Set: %s\n",fcsinfo[dcset8].keyword);
- printf(" Transfer Character-Set");
- #ifdef COMMENT
- if (tslevel == TS_L2)
- printf(": (international)");
- else
- #endif /* COMMENT */
- if (tcharset == TC_TRANSP)
- printf(": Transparent");
- else
- printf(": %s (%s)",tcsinfo[tcharset].keyword, tcsinfo[tcharset].name);
- printf("\n");
- #ifdef COMMENT
- switch (xlatype) {
- case XLA_NONE: s = "None"; break;
- case XLA_BYTE: s = "Byte"; break;
- case XLA_JAPAN: s = "Japanese"; break;
- case XLA_UNICODE: s = "Unicode"; break;
- }
- printf("\n Translation type: %s\n",s);
- #endif /* COMMENT */
- printf(" SEND character-set-selection: %s\n",xfrmtab[s_cset].kwd);
- printf(" RECEIVE character-set-selection: %s\n",xfrmtab[r_cset].kwd);
- if (s_cset == XMODE_A || r_cset == XMODE_A)
- printf(
- " (Use SHOW ASSOCIATIONS to list automatic character-set selections.)\n"
- );
- }
- VOID
- showassoc() {
- int i, k, n = 4;
- char * s;
- printf("\nFor incoming files:\n\n");
- printf("Transfer Character-Set File Character-Set\n");
- for (i = 1; i <= MAXTCSETS; i++) {
- k = axcset[i];
- if (k < 0 || k > MAXFCSETS)
- s = "(none)";
- else
- s = fcsinfo[k].keyword;
- if (!s) s = "";
- if (!*s) s = "(none)";
- printf(" %-25s%s\n",tcsinfo[i].keyword,s);
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- }
- printf("\nFor outbound files:\n\n");
- n += 2;
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- printf("File Character-Set Transfer Character-Set\n");
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- for (i = 0; i <= MAXFCSETS; i++) {
- k = afcset[i];
- if (k < 0 || k > MAXTCSETS)
- s = "(none)";
- else
- s = tcsinfo[k].keyword;
- if (!s) s = "";
- if (!*s) s = "(none)";
- printf(" %-25s%s\n",fcsinfo[i].keyword,s);
- if (++n > cmd_rows - 3) if (!askmore()) return; else n = 0;
- }
- }
- #endif /* NOCSETS */
- VOID
- shopar() {
- printf("Show what? (Type \"show ?\" for a list of possibilities.)\n");
- }
- #endif /* NOSHOW */
- #ifndef NOXFER
- /* D O S T A T -- Display file transfer statistics. */
- int
- dostat(brief) int brief; {
- extern long filrej, peakcps;
- extern int lastspmax, streamed, cleared, streamok;
- extern char whoareu[];
- int n = 0, ftp = 0;
- extern int docrc, interrupted, fatalio;
- ftp = lastxfer & W_FTP;
- #ifdef CK_TTGWSIZ
- #ifdef OS2
- if (tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0)
- ttgwsiz();
- #else /* OS2 */
- if (ttgwsiz() > 0) {
- if (tt_rows > 0 && tt_cols > 0) {
- cmd_rows = tt_rows;
- cmd_cols = tt_cols;
- }
- }
- #endif /* OS2 */
- #endif /* CK_TTGWSIZ */
- debug(F101,"dostat xferstat","",xferstat);
- if (xferstat < 0) {
- printf(" No file transfers yet.\n");
- return(1);
- }
- n = 0;
- if (brief) { printf("\n"); n++; };
- printf(" protocol : %s\n",
- ftp ? "ftp" : ptab[protocol].p_name);
- n++;
- printf(" status : ");
- if (xferstat) printf("SUCCESS\n");
- else if (interrupted) printf("FAILURE (interrupted)\n");
- else if (fatalio) printf("FAILURE (i/o error)\n");
- else printf("FAILURE\n");
- #ifndef XYZ_INTERNAL
- if (!ftp && protocol != PROTO_K) {
- printf("\n external protocol statistics not available\n");
- return(1);
- }
- #endif /* XYZ_INTERNAL */
- n++;
- if (!ftp) {
- if (!xferstat > 0) {
- if (docrc)
- printf(" crc-16 of file(s) : %ld\n", crc16);
- else
- printf(" crc-16 of file(s) : (disabled)\n");
- n++;
- }
- if (!xferstat && *epktmsg) {
- printf(" reason : %s\n", epktmsg);
- n++;
- }
- }
- if (!brief) {
- #ifdef NEWFTP
- if (ftp) {
- extern char ftp_srvtyp[];
- printf(" remote system type : %s\n",ftp_srvtyp);
- } else
- #endif /* NEWFTP */
- if (whoareu[0]) {
- printf(" remote system type : %s\n",
- getsysid((char *)whoareu));
- n++;
- }
- printf(" files transferred : %ld\n",filcnt - filrej);
- if (!ftp)
- printf(" files not transferred : %ld\n",filrej);
- printf(" characters last file : %s\n",ckfstoa(ffc));
- printf(" total file characters : %s\n",ckfstoa(tfc));
- n += ftp ? 3 : 4;
- if (!ftp) {
- printf(" communication line in : %s\n",ckfstoa(tlci));
- printf(" communication line out : %s\n",ckfstoa(tlco));
- printf(" packets sent : %d\n", spackets);
- printf(" packets received : %d\n", rpackets);
- n += 4;
- }
- }
- if (ftp) goto dotimes;
- printf(" damaged packets rec'd : %d\n", crunched);
- printf(" timeouts : %d\n", timeouts);
- printf(" retransmissions : %d\n", retrans);
- n += 3;
- if (!brief) {
- if (filcnt > 0) {
- printf(" parity : %s",parnam((char)parity));
- n++;
- if (autopar) { printf(" (detected automatically)"); n++; }
- printf(
- "\n control characters : %ld prefixed, %ld unprefixed\n",
- ccp, ccu);
- n++;
- printf(" 8th bit prefixing : ");
- n++;
- if (ebqflg) printf("yes [%c]\n",ebq); else printf("no\n");
- n++;
- printf(" locking shifts : %s\n", lscapu ? "yes" : "no");
- n++;
- }
- }
- if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
- if (streamed > 0)
- printf(" window slots used : (streaming)\n");
- else
- printf(" window slots used : %d of %d\n", wmax, wslotr);
- if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
- printf(" reliable: : %s%s\n",
- streamok ? "" : "not ", "negotiated");
- if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
- printf(" clearchannel: : %s%s\n",
- cleared ? "" : "not ", "negotiated");
- if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
- if (!brief) {
- printf(" packet length : %d (send), %d (receive)\n",
- lastspmax, urpsiz);
- if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
- printf(" compression : ");
- if (rptflg)
- printf("yes [%c] (%ld)\n",(char) rptq,rptn);
- else
- printf("no\n");
- if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
- if (bctu == 4)
- printf(" block check type used : blank-free-2\n");
- else
- printf(" block check type used : %d\n",bctu);
- if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
- }
- dotimes:
- #ifdef GFTIMER
- #ifdef COMMENT
- printf(" elapsed time : %0.3f sec, %s\n", fptsecs,hhmmss(tsecs));
- #endif /* COMMENT */
- printf(" elapsed time : %s (%0.3f sec)\n",
- hhmmss((long)(fptsecs + 0.5)),fptsecs);
- #else
- #ifdef COMMENT
- printf(" elapsed time : %s (%d sec)\n",hhmmss(tsecs),tsecs);
- #endif /* COMMENT */
- printf(" elapsed time : %d sec, %s\n",tsecs,hhmmss(tsecs));
- #endif /* GFTIMER */
- if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
- if (!ftp && local && !network && !brief) {
- if (speed <= 0L) speed = ttgspd();
- if (speed > 0L) {
- if (speed == 8880)
- printf(" transmission rate : 75/1200 bps\n");
- else
- printf(" transmission rate : %ld bps\n",speed);
- if (++n > cmd_rows - 3) { if (!askmore()) return(1); else n = 0; }
- }
- }
- if (!ftp && local && !network && /* Only makes sense for */
- mdmtyp == 0 && /* direct serial connections */
- speed > 99L && /* when we really know the speed */
- speed != 8880L
- ) {
- int eff;
- eff = (((tfcps * 100L) / (speed / 100L)) + 5L) / 10L;
- printf(" effective data rate : %ld cps (%d%%)\n",tfcps,eff);
- } else
- printf(" effective data rate : %ld cps\n", tfcps);
- if (!ftp && peakcps > 0L && peakcps > tfcps)
- printf(" peak data rate : %ld cps\n", peakcps);
- if (brief)
- printf("\nUse STATISTICS /VERBOSE for greater detail.\n\n");
- return(1);
- }
- #endif /* NOXFER */
- #ifndef NOSPL
- /* The INPUT command */
- /*
- NOTE: An INPUT timeout of 0 means to perform a nonblocking read of the
- material that has already arrived and is waiting to be read, and perform
- matches against it, without doing any further reads. It should succeed
- or fail instantaneously.
- */
- /* Output buffering for "doinput" */
- #ifdef pdp11
- #define MAXBURST 16 /* Maximum size of input burst */
- #else
- #define MAXBURST 1024
- #endif /* pdp11 */
- #ifdef OSK
- static CHAR *conbuf; /* Buffer to hold output for console */
- #else
- static CHAR conbuf[MAXBURST]; /* Buffer to hold output for console */
- #endif /* OSK */
- static int concnt = 0; /* Number of characters buffered */
- #ifdef OSK
- static CHAR *sesbuf; /* Buffer to hold output for session log */
- #else
- static CHAR sesbuf[MAXBURST]; /* Buffer to hold output for session log */
- #endif /* OSK */
- static int sescnt = 0; /* Number of characters buffered */
- extern int debses; /* TERMINAL DEBUG ON/OFF */
- static VOID /* Flush INPUT echoing */
- myflsh() { /* and session log output. */
- if (concnt > 0) {
- if (debses) { /* Terminal debugging? */
- int i;
- for (i = 0; i < concnt; i++)
- conol(dbchr(conbuf[i]));
- } else
- conxo(concnt, (char *) conbuf);
- concnt = 0;
- }
- if (sescnt > 0) {
- logstr((char *) sesbuf, sescnt);
- sescnt = 0;
- }
- }
- /* Execute the INPUT and MINPUT commands */
- int instatus = -1;
- long inetime = -1L;
- int inwait = 0;
- int nowrap = 0;
- /* For returning the input sequence that matched */
- #ifdef BIGBUFOK
- #define MATCHBUFSIZ 8191
- #else
- #define MATCHBUFSIZ 1023
- #endif /* BIGBUFOK */
- static char * matchbuf = NULL;
- static int matchindex = 0;
- static int burst = 0; /* Chars remaining in input burst */
- /*
- timo = How long to wait:
- < 0 = Wait forever
- 0 = Don't wait at all - material must already have arrived
- > 0 = Wait this many seconds
- ms = Array of strings to wait for.
- mp = Array of flags.
- If mp[i] == 0, ms[i] is literal, else it's a pattern.
- flags = bit mask
- INPSW_NOM = /NOMATCH = 1
- INPSW_CLR = /CLEAR = 2
- INPSW_NOW = /NOWRAP = 4
- INPSW_COU = /COUNT = 8
- count = /COUNT: value if a /COUNT switch was given.
- Returns:
- 0 on failure, 1 on success.
- */
- #ifndef ES_NORMAL
- #define ES_NORMAL 0
- #endif /* ES_NORMAL */
- extern int inesc[], oldesc[];
- int
- doinput(timo,ms,mp,flags,count)
- int timo; char *ms[]; int mp[]; int flags; int count; {
- extern int inintr;
- #ifdef CK_AUTODL
- extern int inautodl;
- #endif /* CK_AUTODL */
- int x, y, i, t, rt, icn, anychar = 0, mi[MINPMAX];
- #ifdef GFTIMER
- CKFLOAT fpt = 0.0;
- #endif /* GFTIMER */
- int savecount = 0;
- int nomatch = 0;
- int clearfirst = 0;
- int lastchar = 0;
- int waiting = 0;
- int imask = 0;
- char ch, *xp, *s;
- CHAR c;
- #ifndef NOLOCAL
- #ifdef OS2
- extern int term_io;
- int term_io_save;
- #endif /* OS2 */
- #endif /* NOLOCAL */
- #ifdef TNCODE
- static int cr = 0;
- #endif /* TNCODE */
- int is_tn = 0;
- #ifdef SSHBUILTIN
- extern int ssh_cas;
- extern char * ssh_cmd;
- #endif /* SSHBUILTIN */
- int noescseq = 0; /* Filter escape sequences */
- debug(F101,"input count","",count);
- debug(F101,"input flags","",flags);
- /*
- CK_BURST enables the INPUT speedup code, which depends on ttchk() returning
- accurate information. If INPUT fails with this code enabled, change the
- above "#define" to "#undef".
- */
- #define CK_BURST
- /***** CHANGE THIS TO A SET INPUT PARAMETER *****/
- noescseq = (sessft == XYFT_T); /* Filter escape sequences */
- imask = cmask;
- if (parity) imask = 0x7f;
- inwait = timo; /* For \v(inwait) */
- /* Options from command switches */
- nowrap = flags & INPSW_NOW; /* 4 = /NOWRAP */
- nomatch = flags & INPSW_NOM; /* 1 = /NOMATCH */
- clearfirst = flags & INPSW_CLR; /* 2 = /CLEAR */
- savecount = count;
- makestr(&inpmatch,NULL);
- if (!matchbuf) {
- matchbuf = malloc(MATCHBUFSIZ+1);
- matchbuf[0] = NUL;
- }
- matchindex = 0;
- /* If last time through we returned because of /NOWRAP and buffer full */
- /* now we have to clear the buffer to make room for another load. */
- if (nowrap && instatus == INP_BF)
- clearfirst = 1;
- if (clearfirst) { /* INPUT /CLEAR */
- int i;
- myflsh(); /* Flush screen and log buffers */
- for (i = 0; i < inbufsize; i++)
- inpbuf[i] = NUL;
- inpbp = inpbuf;
- }
- is_tn =
- #ifdef TNCODE
- (local && network && IS_TELNET()) || (!local && sstelnet)
- #else
- 0
- #endif /* TNCODE */
- ;
- #ifdef CK_SSL
- if (is_tn) if (ssl_raw_flag || tls_raw_flag) is_tn = 0;
- #endif /* CK_SSL */
- instatus = INP_IE; /* 3 = internal error */
- kbchar = 0;
- #ifdef OSK
- if (conbuf == NULL) {
- if ((conbuf = (CHAR *)malloc(MAXBURST*2)) == NULL) {
- return(0);
- }
- sesbuf = conbuf + MAXBURST;
- }
- #endif /* OSK */
- #ifndef NOLOCAL
- if (local) { /* In local mode... */
- if ((waiting = ttchk()) < 0) { /* check that connection is open */
- if (!quiet) {
- if ((!network
- #ifdef TN_COMPORT
- || istncomport()
- #endif /* TN_COMPORT */
- ) && carrier != CAR_OFF)
- printf("?Carrier detect failure on %s.\n", ttname);
- else
- printf("?Connection %s %s is not open.\n",
- network ? "to" : "on",
- ttname
- );
- }
- instatus = INP_IO;
- return(0);
- }
- debug(F101,"doinput waiting","",waiting);
- y = ttvt(speed,flow); /* Put line in "ttvt" mode */
- if (y < 0) {
- printf("?INPUT initialization error\n");
- instatus = INP_IO;
- return(0); /* Watch out for failure. */
- }
- }
- #endif /* NOLOCAL */
- #ifdef SSHBUILTIN
- if ( network && nettype == NET_SSH && ssh_cas && ssh_cmd &&
- !(strcmp(ssh_cmd,"kermit") && strcmp(ssh_cmd,"sftp"))) {
- if (!quiet)
- printf("?SSH Subsystem active: %s\n", ssh_cmd);
- instatus = INP_IKS;
- return(0);
- }
- #endif /* SSHBUILTIN */
- debug(F111,"doinput ms[0]",ms[0],waiting);
- if (!ms[0] || isemptystring(ms[0])) { /* No search string was given nor */
- if (count < 2) /* a /COUNT: switch so we just */
- anychar = 1; /* wait for the first character */
- }
- if (nomatch) anychar = 0; /* Don't match anything */
- if (!anychar && waiting == 0 && timo == 0)
- return(0);
- #ifndef NODEBUG
- if (deblog) {
- char xbuf[100];
- debug(F101,"doinput anychar","",anychar);
- debug(F101,"doinput timo","",timo);
- debug(F101,"doinput echo","",inecho);
- #ifdef CK_BURST
- debug(F101,"doinput burst","",burst);
- #endif /* CK_BURST */
- y = -1;
- while (ms[++y]) {
- sprintf(xbuf,"doinput string %2d",y); /* SAFE (24) */
- debug(F111,xbuf,ms[y],mp[y]);
- }
- }
- #endif /* NODEBUG */
- #ifdef IKS_OPTION
- if (is_tn) {
- /* If the remote side is in a state of IKS START-SERVER */
- /* we request that the state be changed. We will detect */
- /* a failure to adhere to the request when we call ttinc() */
- if (TELOPT_U(TELOPT_KERMIT) &&
- TELOPT_SB(TELOPT_KERMIT).kermit.u_start)
- iks_wait(KERMIT_REQ_STOP,0); /* Send Request-Stop */
- #ifdef CK_AUTODL
- /* If we are processing packets during INPUT and we have not */
- /* sent a START message, do so now. */
- if (inautodl && TELOPT_ME(TELOPT_KERMIT) &&
- !TELOPT_SB(TELOPT_KERMIT).kermit.me_start) {
- tn_siks(KERMIT_START); /* Send Kermit-Server Start */
- }
- #endif /* CK_AUTODL */
- }
- #endif /* IKS_OPTION */
- x = 0; /* Return code, assume failure */
- instatus = INP_TO; /* Status, assume timeout */
- for (y = 0; y < MINPMAX; y++) /* Initialize... */
- mi[y] = 0; /* ..string pattern match position */
- if (!inpcas[cmdlvl]) { /* INPUT CASE = IGNORE? */
- y = -1;
- while ((xp = ms[++y])) { /* Convert each target to lowercase */
- while (*xp) {
- if (isupper(*xp)) *xp = (char) tolower(*xp);
- xp++;
- }
- }
- }
- rtimer(); /* Reset timer. */
- #ifdef GFTIMER
- rftimer(); /* Floating-point timer too. */
- #endif /* GFTIMER */
- inetime = -1L; /* Initialize elapsed time. */
- t = 0; /* Time now is 0. */
- m_found = 0; /* Default to timed-out */
- incount = 0; /* Character counter */
- rt = (timo == 0) ? 0 : 1; /* Character-read timeout interval */
- #ifndef NOLOCAL
- #ifdef OS2
- term_io_save = term_io; /* Disable I/O by emulator */
- term_io = 0;
- #endif /* OS2 */
- #endif /* NOLOCAL */
- while (1) { /* Character-getting loop */
- #ifdef CK_APC
- /* Check to see if there is an Autodown or other APC command */
- if (apcactive == APC_LOCAL ||
- (apcactive == APC_REMOTE && apcstatus != APC_OFF)) {
- if (mlook(mactab,"_apc_commands",nmac) == -1) {
- debug(F110,"doinput about to execute APC",apcbuf,0);
- domac("_apc_commands",apcbuf,cmdstk[cmdlvl].ccflgs|CF_APC);
- delmac("_apc_commands",1);
- apcactive = APC_INACTIVE;
- #ifdef DEBUG
- } else {
- debug(F100,"doinput APC in progress","",0);
- #endif /* DEBUG */
- }
- }
- #endif /* CK_APC */
- if (timo == 0 && waiting < 1) { /* Special exit criterion */
- instatus = INP_TO; /* for timeout == 0 */
- break;
- }
- if (local) { /* One case for local */
- y = ttinc(rt); /* Get character from comm device */
- debug(F101,"doinput ttinc(rt) returns","",y);
- if (y < -1) { /* Connection failed. */
- instatus = INP_IO; /* Status = i/o error */
- #ifndef NOLOCAL
- #ifdef OS2
- term_io = term_io_save;
- #endif /* OS2 */
- #endif /* NOLOCAL */
- switch (y) {
- case -2: /* Connection lost */
- if (local && !network && carrier != CAR_OFF) {
- dologend();
- printf("Connection closed.\n");
- ttclos(1);
- }
- break;
- case -3:
- dologend();
- printf("Session Limit exceeded - closing connection.\n");
- ttclos(1);
- default:
- break;
- }
- debug(F111,"doinput Connection failed","returning 0",y);
- return(0);
- }
- if (inintr) {
- debug(F111,"doinput","inintr",inintr);
- if ((icn = conchk()) > 0) { /* Interrupted from keyboard? */
- debug(F101,"input interrupted from keyboard","",icn);
- kbchar = coninc(0);
- if (kbchar >= 0) {
- while (--icn > 0) {
- debug(F110,"doinput","absorbing",0);
- coninc(0); /* Yes, absorb what was typed. */
- }
- instatus = INP_UI; /* Fail and remember why. */
- break;
- }
- }
- }
- } else { /* Another for remote */
- y = coninc(rt);
- debug(F101,"doinput coninc(rt) returns","",y);
- }
- if (y > -1) { /* A character arrived */
- debug(F111,"doinput","a character arrived",y);
- if (timo == 0)
- waiting--;
- #ifndef OS2
- #define TN_NOLO
- #endif /* OS2 */
- #ifdef NOLOCAL
- #define TN_NOLO
- #endif /* NOLOCAL */
- #ifdef TN_NOLO
- debug(F100,"doinput TN_NOLO","",0);
- #ifdef TNCODE
- /* Check for telnet protocol negotiation */
- if (is_tn) {
- switch (y & 0xff) {
- case IAC:
- cr = 0;
- myflsh(); /* Break from input burst for tn_doop() */
- #ifdef CK_BURST
- burst = 0;
- #endif /* CK_BURST */
- waiting -= 2; /* (not necessarily...) */
- switch (tn_doop((CHAR)(y & 0xff),duplex,ttinc)) {
- case 2: duplex = 0; continue;
- case 1: duplex = 1; continue;
- #ifdef IKS_OPTION
- case 4:
- if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
- !tcp_incoming) {
- instatus = INP_IKS;
- printf(
- " Internet Kermit Service in SERVER mode.\n Please use REMOTE commands.\n"
- );
- break;
- }
- continue;
- #endif /* IKS_OPTION */
- case 6: /* TELNET DO LOGOUT received */
- continue;
- case 7:
- case 3: /* A quoted IAC */
- break;
- default:
- continue;
- }
- case CR:
- cr = 1;
- break;
- case NUL:
- if (!TELOPT_U(TELOPT_BINARY) && cr) {
- cr = 0;
- continue;
- }
- cr = 0;
- break;
- default:
- cr = 0;
- }
- /* I'm echoing remote chars */
- if (TELOPT_ME(TELOPT_ECHO) && tn_rem_echo)
- ttoc((char)y);
- }
- #endif /* TNCODE */
- #ifdef CK_AUTODL
- /* Check for file transfer packets */
- if (inautodl) autodown(y);
- #endif /* CK_AUTODL */
- #else /* TN_NOLO */
- debug(F100,"doinput !TN_NOLO","",0);
- #ifdef TNCODE
- /* Check for telnet protocol negotiation */
- if (is_tn) {
- int tx;
- switch (y & 0xff) {
- case IAC:
- myflsh(); /* Break from input burst for tn_doop() */
- #ifdef CK_BURST
- burst = 0;
- #endif /* CK_BURST */
- #ifdef IKS_OPTION
- tx = scriptwrtbuf((USHORT)y);
- if (tx == 4) {
- if (TELOPT_U(TELOPT_KERMIT) &&
- TELOPT_SB(TELOPT_KERMIT).kermit.u_start &&
- !tcp_incoming
- ) {
- instatus = INP_IKS;
- printf(
- " Internet Kermit Service in SERVER mode.\n Please use REMOTE commands.\n"
- );
- break;
- }
- } else if (tx == 6) {
- /* TELNET DO LOGOUT received */
- }
- #else /* IKS_OPTION */
- /* Handles Telnet negotiations */
- tx = scriptwrtbuf((USHORT)y);
- if (tx == 6) {
- /* TELNET DO LOGOUT received */
- }
- #endif /* IKS_OPTION */
- waiting -= 2; /* (not necessarily...) */
- cr = 0;
- continue; /* and autodownload check */
- case CR:
- cr = 1;
- tx = scriptwrtbuf((USHORT)y);
- if (tx == 6) {
- /* TELNET DO LOGOUT received */
- }
- break;
- case NUL:
- cr = 0;
- if (!TELOPT_U(TELOPT_BINARY) && cr)
- continue;
- tx = scriptwrtbuf((USHORT)y);
- if (tx == 6) {
- /* TELNET DO LOGOUT received */
- }
- break;
- default:
- cr = 0;
- tx = scriptwrtbuf((USHORT)y);
- if (tx == 6) {
- /* TELNET DO LOGOUT received */
- }
- }
- /* I'm echoing remote chars */
- if (TELOPT_ME(TELOPT_ECHO) && tn_rem_echo)
- ttoc((CHAR)y);
- } else
- #endif /* TNCODE */
- /* Handles terminal emulation responses */
- scriptwrtbuf((USHORT)y);
- #endif /* TN_NOLO */
- /* Real input character to be checked */
- #ifdef CK_BURST
- burst--; /* One less character waiting */
- debug(F101,"doinput burst","",burst);
- #endif /* CK_BURST */
- c = (CHAR) (imask & (CHAR) y); /* Mask off any parity */
- inchar[0] = c; /* Remember character for \v(inchar) */
- #ifdef COMMENT
- #ifdef CK_BURST
- /* Update "lastchar" time only once during input burst */
- if (burst <= 0)
- #endif /* CK_BURST */
- #endif /* COMMENT */
- lastchar = gtimer(); /* Remember when it came */
- if (c == '\0') { /* NUL, we can't use it */
- if (anychar) { /* Except if any character will do? */
- x = 1; /* Yes, done. */
- instatus = INP_OK;
- incount = 1; /* This must be the first and only. */
- break;
- } else goto refill; /* Otherwise continue INPUTting */
- }
- *inpbp++ = c; /* Store char in circular buffer */
- incount++; /* Count it for \v(incount) */
- if (flags & INPSW_COU) { /* INPUT /COUNT */
- if (--count < 1) {
- x = 1;
- instatus = INP_OK;
- incount = savecount;
- break;
- }
- }
- if (matchbuf) {
- if (matchindex < MATCHBUFSIZ) {
- matchbuf[matchindex++] = c;
- matchbuf[matchindex] = NUL;
- }
- }
- #ifdef MAC
- {
- extern char *ttermw; /* fake pointer cast */
- if (inecho) {
- outchar(ttermw, c); /* echo to terminal window */
- /* this might be too much overhead to do here ? */
- updatecommand(ttermw);
- }
- }
- #else /* Not MAC */
- if (inecho) { /* Buffer console output */
- conbuf[concnt++] = c;
- }
- #endif /* MAC */
- #ifndef OS2
- if (seslog) {
- int dummy = 0, skip = 0;
- #ifndef NOLOCAL
- if (noescseq) {
- dummy = chkaes(c,0);
- if (inesc[0] != ES_NORMAL || oldesc[0] != ES_NORMAL)
- skip = 1;
- }
- #endif /* NOLOCAL */
- #ifdef UNIXOROSK
- if (sessft == XYFT_T) {
- #ifdef UNIX
- if (c == '\r')
- #else
- #ifdef OSK
- if (c == '\012')
- #endif /* OSK */
- #endif /* UNIX */
- skip = 1;
- }
- #endif /* UNIXOROSK */
- if (!skip)
- sesbuf[sescnt++] = c; /* Buffer session log output */
- }
- #endif /* OS2 */
- if (anychar) { /* Any character will do? */
- x = 1;
- instatus = INP_OK;
- break;
- }
- if (!inpcas[cmdlvl]) { /* Ignore alphabetic case? */
- if (isupper(c)) /* Yes, convert input char to lower */
- c = (CHAR) tolower(c);
- }
- debug(F000,"doinput char","",c);
- /* Here is the matching section */
- y = -1; /* Loop thru search strings */
- while (!nomatch && (s = ms[++y])) { /* ...as many as we have. */
- if (mp[y]) { /* Pattern match? */
- #ifdef COMMENT
- int j;
- /* This is gross but it works... */
- /* We could just as easily have prepended '*' to the */
- /* pattern and skipped the loop, except then we would */
- /* not have any way to identify the matching string. */
- for (j = 0; j < matchindex; j++) {
- if (ckmatch(s,&matchbuf[j],1,1)) {
- matchindex = j;
- instatus = INP_OK;
- x = 1;
- break;
- }
- }
- if (x > 0)
- break;
- #else
- /* July 2001 - ckmatch() returns match position. */
- /* It works and it's not gross. */
- /* (4 = floating pattern) */
- x = ckmatch(s,matchbuf,inpcas[cmdlvl],1+4);
- if (x > 0) {
- matchindex = x - 1;
- instatus = INP_OK;
- x = 1;
- break;
- }
- #endif /* COMMENT */
- continue;
- } /* Literal match. */
- i = mi[y]; /* Match-position in search string. */
- debug(F000,"compare char","",(CHAR)s[i]);
- if (c == (CHAR) s[i]) { /* Check for match */
- i++; /* Got one, go to next character */
- } else { /* Don't have a match */
- int j;
- for (j = i; i > 0; ) { /* Back up in search string */
- i--; /* (Do this here to prevent compiler foulup) */
- /* j is the length of the substring that matched */
- if (c == (CHAR) s[i]) {
- if (!strncmp(s,&s[j-i],i)) {
- i++; /* c actually matches -- cfk */
- break;
- }
- }
- }
- }
- if ((CHAR) s[i] == (CHAR) '\0') { /* Matched to end? */
- ckstrncpy(matchbuf,ms[y],MATCHBUFSIZ);
- matchindex = 0;
- instatus = INP_OK; /* Yes, */
- x = 1;
- break; /* done. */
- }
- mi[y] = i; /* No, remember match-position */
- }
- if (x == 1) { /* Set \v(minput) result */
- instatus = INP_OK;
- m_found = y + 1;
- break;
- }
- if (inpbp >= inpbuf + inbufsize) { /* Reached end of buffer? */
- if (nowrap) { /* If /NOWRAP...*/
- instatus = INP_BF; /* ...return indicating buffer full. */
- *inpbp = NUL;
- goto xinput;
- }
- *inpbp = NUL; /* Make it null-terminated */
- inpbp = inpbuf; /* Yes. */
- }
- }
- #ifdef CK_BURST
- else if (y <= -1 && burst > 0) {
- debug(F111,"doinput (y<=-1&&burst>0)","burst",burst);
- /* A timeout occurred so there can't */
- burst = 0; /* be data waiting; must check timo */
- }
- refill:
- if (burst <= 0) { /* No buffered chars remaining... */
- myflsh(); /* Flush buffered output */
- if (local) { /* Get size of next input burst */
- burst = ttchk();
- if (burst < 0) { /* ttchk() says connection is closed */
- instatus = INP_IO; /* Status = i/o error */
- #ifndef NOLOCAL
- #ifdef OS2
- term_io = term_io_save;
- #endif /* OS2 */
- #endif /* NOLOCAL */
- if ((!network
- #ifdef TN_COMPORT
- || istncomport()
- #endif /* TN_COMPORT */
- ) && carrier != CAR_OFF) {
- /* The test is written this way because the Microsoft compiler
- * is producing bad code if written:
- *
- * if (network && (!istncomport() || carrier == CAR_OFF) )
- */
- break;
- } else {
- printf("Fatal error - disconnected.\n");
- ttclos(1);
- break;
- }
- }
- if (inintr) {
- if ((icn = conchk()) > 0) { /* Interrupt from keyboard? */
- kbchar = coninc(0);
- debug(F101,"input interrupted from keyboard","",icn);
- while (--icn > 0) coninc(0); /* Yes, absorb chars. */
- break; /* And fail. */
- }
- }
- } else {
- burst = conchk();
- }
- debug(F101,"doinput burst","",burst);
- /* Prevent overflow of "conbuf" and "sesbuf" */
- if (burst > MAXBURST)
- burst = MAXBURST;
- /* Did not match, timer exceeded? */
- t = gtimer();
- debug(F111,"doinput gtimer","burst",t);
- debug(F101,"doinput timo","",timo);
- if ((t >= timo) && (timo > 0))
- break;
- else if (insilence > 0 && (t - lastchar) > insilence)
- break;
- } else {
- debug(F111,"doinput (burst > 0)","burst",burst);
- }
- #else /* CK_BURST */
- refill:
- myflsh(); /* Flush buffered output */
- /* Did not match, timer exceeded? */
- t = gtimer();
- debug(F111,"doinput gtimer","no burst",t);
- debug(F101,"doinput timo","",timo);
- if ((t >= timo) && (timo > -1))
- break;
- else if (insilence > 0 && (t - lastchar) > insilence)
- break;
- #endif /* CK_BURST */
- } /* Still have time left, continue. */
- xinput:
- myflsh(); /* Flush buffered output */
- if (instatus == INP_BF) { /* Buffer full and /NOWAIT */
- x = 0; /* Must not succeed */
- } else { /* Buffer full and /NOWAIT */
- if (nomatch) x = 1; /* Succeed if nomatch and timed out */
- if (x > 0 && !nomatch)
- instatus = 0;
- }
- #ifndef NOLOCAL
- #ifdef OS2
- term_io = term_io_save;
- #endif /* OS2 */
- #endif /* NOLOCAL */
- #ifdef COMMENT
- #ifdef IKS_OPTION
- #ifdef CK_AUTODL
- if (is_tn && TELOPT_ME(TELOPT_KERMIT) && inautodl) {
- tn_siks(KERMIT_STOP); /* Send Kermit-Server Stop */
- }
- #endif /* CK_AUTODL */
- #endif /* IKS_OPTION */
- #endif /* COMMENT */
- #ifdef GFTIMER
- fpt = gftimer(); /* Get elapsed time */
- /* If a long is 32 bits, it would take about 50 days for this to overflow. */
- inetime = (int)(fpt * (CKFLOAT)1000.0);
- #else
- inetime = (int)(gtimer() * 1000);
- #endif /* GFTIMER */
- if (x > 0)
- makestr(&inpmatch,&matchbuf[matchindex]); /* \v(inmatch) */
- return(x); /* Return the return code. */
- }
- #endif /* NOSPL */
- #ifndef NOSPL
- /* REINPUT Command */
- /*
- Note, the timeout parameter is required, but ignored. Syntax is compatible
- with MS-DOS Kermit except timeout can't be omitted. This function only
- looks at the characters already received and does not read any new
- characters from the connection.
- */
- int
- doreinp(timo,s,pat) int timo; char *s; int pat; {
- int x, y, i;
- char *xx, *xp, *xq = (char *)0;
- CHAR c;
- if (!s) s = "";
- debug(F101,"doreinput pat","",pat);
- y = (int)strlen(s);
- debug(F111,"doreinput search",s,y);
- if (y > inbufsize) { /* If search string longer than */
- debug(F101,"doreinput inbufsize","",inbufsize);
- return(0); /* input buffer, fail. */
- }
- makestr(&inpmatch,NULL);
- if (!matchbuf)
- matchbuf = malloc(MATCHBUFSIZ+1);
- matchindex = 0;
- x = 0; /* Return code, assume failure */
- i = 0; /* String pattern match position */
- if (!inpcas[cmdlvl]) { /* INPUT CASE = IGNORE? */
- xp = malloc(y+2); /* Make a separate copy of the */
- if (!xp) { /* search string. */
- printf("?malloc error 6\n");
- return(x);
- } else xq = xp; /* Keep pointer to beginning. */
- while (*s) { /* Yes, convert to lowercase */
- *xp = *s;
- if (isupper(*xp)) *xp = (char) tolower(*xp);
- xp++; s++;
- }
- *xp = NUL; /* Terminate it! */
- s = xq; /* Move search pointer to it. */
- }
- xx = *inpbp ? inpbp : inpbuf; /* Current INPUT buffer pointer */
- do {
- c = *xx++; /* Get next character */
- if (!c) break;
- if (xx >= inpbuf + inbufsize) /* Wrap around if necessary */
- xx = inpbuf;
- if (!inpcas[cmdlvl]) { /* Ignore alphabetic case? */
- if (isupper(c)) c = (CHAR) tolower(c); /* Yes */
- }
- if (pat) {
- int j;
- if (matchbuf) {
- if (matchindex < MATCHBUFSIZ) {
- matchbuf[matchindex++] = c;
- matchbuf[matchindex] = NUL;
- }
- for (j = 0; j < matchindex; j++) { /* Gross but effective */
- if (ckmatch(s,&matchbuf[j],1,1)) {
- debug(F101,"GOT IT","",j);
- matchindex = j;
- x = 1;
- break;
- }
- }
- }
- if (x > 0)
- break;
- continue;
- }
- debug(F000,"doreinp char","",c);
- debug(F000,"compare char","",(CHAR) s[i]);
- if (((char) c) == ((char) s[i])) { /* Check for match */
- i++; /* Got one, go to next character */
- } else { /* Don't have a match */
- int j;
- for (j = i; i > 0; ) { /* [jrs] search backwards for it */
- i--;
- if (((char) c) == ((char) s[i])) {
- if (!strncmp(s,&s[j-i],i)) {
- i++;
- break;
- }
- }
- }
- } /* [jrs] or return to zero from -1 */
- if (s[i] == '\0') { /* Matched all the way to end? */
- ckstrncpy(matchbuf,s,MATCHBUFSIZ);
- matchindex = 0;
- x = 1; /* Yes, */
- break; /* done. */
- }
- } while (xx != inpbp && x < 1); /* Until back where we started. */
- if (!inpcas[cmdlvl]) if (xq) free(xq); /* Free this if it was malloc'd. */
- makestr(&inpmatch,&matchbuf[matchindex]); /* \v(inmatch) */
- return(x); /* Return search result. */
- }
- /* X X S T R I N G -- Interpret strings containing backslash escapes */
- /* Z Z S T R I N G -- (new name...) */
- /*
- Copies result to new string.
- strips enclosing braces or doublequotes.
- interprets backslash escapes.
- returns 0 on success, nonzero on failure.
- tries to be compatible with MS-DOS Kermit.
- Syntax of input string:
- string = chars | "chars" | {chars}
- chars = (c*e*)*
- where c = any printable character, ascii 32-126
- and e = a backslash escape
- and * means 0 or more repetitions of preceding quantity
- backslash escape = \operand
- operand = {number} | number | fname(operand) | v(name) | $(name) | m(name)
- number = [r]n[n[n]]], i.e. an optional radix code followed by 1-3 digits
- radix code is oO (octal), xX (hex), dD or none (decimal) (see xxesc()).
- */
- #ifndef NOFRILLS
- int
- yystring(s,s2) char *s; char **s2; { /* Reverse a string */
- int x;
- static char *new;
- new = *s2;
- if (!s || !new) return(-1); /* Watch out for null pointers. */
- if ((x = (int)strlen(s)) == 0) { /* Recursion done. */
- *new = '\0';
- return(0);
- }
- x--; /* Otherwise, call self */
- *new++ = s[x]; /* to reverse rest of string. */
- s[x] = 0;
- return(yystring(s,&new));
- }
- #endif /* NOFRILLS */
- static char ipabuf[16] = { NUL }; /* IP address buffer */
- static char *
- getip(s) char *s; {
- char c=NUL; /* Workers... */
- int i=0, p=0, d=0;
- int state = 0; /* State of 2-state FSA */
- while ((c = *s++)) {
- switch(state) {
- case 0: /* Find first digit */
- i = 0; /* Output buffer index */
- ipabuf[i] = NUL; /* Initialize output buffer */
- p = 0; /* Period counter */
- d = 0; /* Digit counter */
- if (isdigit(c)) { /* Have first digit */
- d = 1; /* Count it */
- ipabuf[i++] = c; /* Copy it */
- state = 1; /* Change state */
- }
- break;
- case 1: /* In numeric field */
- if (isdigit(c)) { /* Have digit */
- if (++d > 3) /* Too many */
- state = 0; /* Start over */
- else /* Not too many */
- ipabuf[i++] = c; /* Keep it */
- } else if (c == '.' && p < 3) { /* Have a period */
- p++; /* Count it */
- if (d == 0) /* Not preceded by a digit */
- state = 0; /* Start over */
- else /* OK */
- ipabuf[i++] = c; /* Keep it */
- d = 0; /* Reset digit counter */
- } else if (p == 3 && d > 0) { /* Not part of address */
- ipabuf[i] = NUL; /* If we have full IP address */
- return((char *)ipabuf); /* Return it */
- } else { /* Otherwise */
- state = 0; /* Start over */
- ipabuf[0] = NUL; /* (in case no more chars left) */
- }
- }
- } /* Fall thru at end of string */
- ipabuf[i] = NUL; /* Maybe we have one */
- return((p == 3 && d > 0) ? (char *)ipabuf : "");
- }
- #endif /* NOSPL */
- /* Date Routines */
- /* Z J D A T E -- Convert yyyymmdd date to Day of Year */
- static int jdays[12] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
- static int ldays[12] = { 0,31,60,91,121,152,182,213,244,274,305,335 };
- static char zjdbuf[12] = { NUL, NUL };
- /*
- Deinde, ne in posterum a XII kalendas aprilis aequinoctium recedat,
- statuimus bissextum quarto quoque anno (uti mos est) continuari debere,
- praeterquam in centesimis annis; qui, quamvis bissextiles antea semper
- fuerint, qualem etiam esse volumus annum MDC, post eum tamen qui deinceps
- consequentur centesimi non omnes bissextiles sint, sed in quadringentis
- quibusque annis primi quique tres centesimi sine bissexto transigantur,
- quartus vero quisque centesimus bissextilis sit, ita ut annus MDCC, MDCCC,
- MDCCCC bissextiles non sint. Anno vero MM, more consueto dies bissextus
- intercaletur, februario dies XXIX continente, idemque ordo intermittendi
- intercalandique bissextum diem in quadringentis quibusque annis perpetuo
- conservetur. - Gregorius XIII, Anno Domini MDLXXXII.
- */
- char *
- zjdate(date) char * date; { /* date = yyyymmdd */
- char year[5];
- char month[3];
- char day[3];
- int d, m, x, y;
- int leapday, j;
- char * time = NULL;
- if (!date) date = ""; /* Validate arg */
- x = strlen(date);
- if (x < 1) return("0");
- if (x < 8) return("-1");
- for (x = 0; x < 8; x++)
- if (!isdigit(date[x]))
- return("-1");
- if (date[8]) if (date[9])
- time = date + 9;
- year[0] = date[0]; /* Isolate year */
- year[1] = date[1];
- year[2] = date[2];
- year[3] = date[3];
- year[4] = '\0';
- month[0] = date[4]; /* Month */
- month[1] = date[5];
- month[2] = '\0';;
- day[0] = date[6]; /* And day */
- day[1] = date[7];
- day[2] = '\0';
- leapday = 0; /* Assume no leap day */
- y = atoi(year);
- m = atoi(month);
- d = atoi(day);
- if (m > 2) { /* No Leap day before March */
- if (y % 4 == 0) { /* If year is divisible by 4 */
- leapday = 1; /* It's a Leap year */
- if (y % 100 == 0) { /* Except if divisible by 100 */
- if (y % 400 != 0) /* but not by 400 */
- leapday = 0;
- }
- }
- }
- j = jdays[m - 1] + d + leapday; /* Day of year */
- if (time)
- sprintf(zjdbuf,"%04d%03d %s",y,j,time); /* SAFE */
- else
- sprintf(zjdbuf,"%04d%03d",y,j); /* SAFE */
- return((char *)zjdbuf);
- }
- static char jzdbuf[32];
- /* J Z D A T E -- Convert Day of Year to yyyyddmm date */
- char *
- jzdate(date) char * date; { /* date = yyyyddd */
- char year[5]; /* with optional time */
- char day[4];
- char * time = NULL, * p;
- int d, m, x, y;
- int leapday, j;
- int * zz;
- if (!date) date = ""; /* Validate arg */
- x = strlen(date);
- debug(F111,"jzdate len",date,x);
- if (x < 1) return("0");
- if (x < 7) return("-1");
- if (x > 8) time = date + 8;
- for (x = 0; x < 7; x++)
- if (!isdigit(date[x]))
- return("-1");
- year[0] = date[0]; /* Isolate year */
- year[1] = date[1];
- year[2] = date[2];
- year[3] = date[3];
- year[4] = '\0';
- debug(F110,"jzdate year",year,0);
- day[0] = date[4]; /* And day */
- day[1] = date[5];
- day[2] = date[6];
- day[3] = '\0';
- debug(F110,"jzdate day",day,0);
- j = atoi(day);
- if (j > 366)
- return("-1");
- leapday = 0; /* Assume no leap day */
- y = atoi(year);
- if (y % 4 == 0) { /* If year is divisible by 4 */
- leapday = 1; /* It's a Leap year */
- if (y % 100 == 0) { /* Except if divisible by 100 */
- if (y % 400 != 0) /* but not by 400 */
- leapday = 0;
- }
- }
- debug(F101,"jzdate leapday","",leapday);
- zz = leapday ? ldays : jdays;
- for (x = 0; x < 11; x++)
- if (j > zz[x] && j <= zz[x+1])
- break;
- m = x + 1;
- debug(F101,"jzdate m","",m);
- d = j - zz[x];
- debug(F101,"jzdate d","",d);
- if (time)
- sprintf(jzdbuf,"%04d%02d%02d %s",y,m,d,time); /* SAFE */
- else
- sprintf(jzdbuf,"%04d%02d%02d",y,m,d); /* SAFE */
- debug(F101,"jzdate jzdbuf",jzdbuf,0);
- p = ckcvtdate((char *)jzdbuf, 0); /* Convert to standard form */
- ckstrncpy(jzdbuf,p,32);
- if (!time) jzdbuf[8] = NUL; /* Remove time if not wanted */
- return((char *)jzdbuf);
- }
- /* M J D -- Modified Julian Date */
- /*
- Call with:
- Standard-format date-time string: yyyymmdd[ hh:mm:ss].
- The time, if any, is ignored.
- Returns:
- -1L on error, otherwise:
- The number of days since 17 Nov 1858 as a whole number:
- 16 Nov 1858 = -1, 17 Nov 1858 = 0, 18 Nov 1858 = 1, 19 Nov 1858 = 2, ...
- The Modified Julian Date is defined by the International Astronomical
- Union as the true Julian date minus 2400000.5 days. The true Julian
- date is the number days since since noon of 1 January 4713 BCE of the
- Julian proleptic calendar. Conversions between calendar dates and
- Julian dates, however, assume Gregorian dating. The day of the week
- is MJD mod 7: 0=We, 1=Th, 2=Fr, 3=Sa, 4=Su, 5=Mo, 6=Tu.
- */
- long
- mjd(date) char * date; {
- char year[5];
- char month[3];
- char day[3];
- int x, a, d, m, y;
- long z;
- if (!date) date = ""; /* Validate arg */
- x = strlen(date);
- if (x < 1) return(0L);
- if (x < 8) return(-1L);
- for (x = 0; x < 8; x++)
- if (!isdigit(date[x]))
- return(-1L);
- year[0] = date[0]; /* Isolate year */
- year[1] = date[1];
- year[2] = date[2];
- year[3] = date[3];
- year[4] = '\0';
- month[0] = date[4]; /* Month */
- month[1] = date[5];
- month[2] = '\0';;
- m = atoi(month);
- day[0] = date[6]; /* And day */
- day[1] = date[7];
- day[2] = '\0';
- d = atoi(day);
- a = (14-m)/12; /* Calculate true Julian date */
- y = atoi(year) + 4800 - a;
- m = m + 12 * a - 3;
- z = d + (long)(306*m+5)/10 + (long)(y*365) + y/4 - y/100 + y/400 - 32045L;
- z -= 2400001L; /* Convert JD to MJD */
- return(z);
- }
- static char mjd2dbuf[32];
- /* M J D 2 D A T E -- Converts MJD to yyyymmdd */
- char *
- #ifdef CK_ANSIC
- mjd2date(long mjd)
- #else
- mjd2date(mjd) long mjd;
- #endif /* CK_ANSIC */
- /* mjd2date */ {
- long jd, l, n;
- int d, m, y;
- jd = (long)(mjd + 2400001L);
- l = jd + 68569;
- n = 4 * l / 146097L;
- l = l - (146097 * n + 3) / 4;
- y = 4000 * (l + 1) / 1461001L;
- l = l - 1461 * y / 4 + 31;
- m = 80 * l / 2447;
- d = l - 2447 * m / 80;
- l = m / 11;
- m = m + 2 - 12 * l;
- y = 100 * (n - 49) + y + l;
- sprintf(mjd2dbuf,"%04d%02d%02d",y,m,d); /* SAFE */
- return((char *)mjd2dbuf);
- }
- #ifndef NOSPL
- static char ** flist = (char **) NULL; /* File list for \fnextfile() */
- static int flistn = 0; /* Number of items in file list */
- /*
- The function return-value buffer must be global, since fneval() returns a
- pointer to it. fneval() is called only by zzstring(), which always copies
- the result out of this buffer to somewhere else, so it's OK to have only
- one buffer for this in most cases. However, since function calls can be
- nested -- e.g. functions whose arguments are functions, or recursive
- functions, at some point we should convert this to an array of buffers,
- indexed by function depth (which might or might not be the same as the
- "depth" variable). Also, since function results are potentially quite big,
- we'd need to allocate and deallocate dynamically as we descend and ascend
- function depth. Left for a future release...
- */
- char fnval[FNVALL+2]; /* Function return value */
- static int fndepth = 0; /* (we don't actually use this yet) */
- int fnsuccess = 1;
- extern int fnerror;
- /* f p f o r m a t -- Floating-point number nicely formatted. */
- /*
- Returns results from a circular 1K buffer.
- Don't count on too many results remaining available at once; it could
- be anywhere from 5 to maybe 100, depending on the sizes of the results.
- */
- #ifdef CKFLOAT
- #define FPFMTSIZ 1024
- static char fpfmtbuf[FPFMTSIZ] = { NUL, NUL };
- static int fpfbufpos = 0; /* (why was this char before?) */
- char *
- fpformat(fpresult,places,round) CKFLOAT fpresult; int places, round; {
- char fbuf[16]; /* For creating printf format */
- int nines = 0, sign = 0, x, y, i, j, size = 0;
- char * buf;
- CKFLOAT ftmp;
- x = places ? places : (fp_digits ? fp_digits : 6);
- debug(F101,"fpformat fpresult","",fpresult);
- debug(F101,"fpformat places","",places);
- debug(F101,"fpformat fpfbufpos 1","",fpfbufpos);
- ftmp = fpresult;
- if (ftmp < 0.0) ftmp = 0.0 - fpresult;
- #ifdef FNFLOAT
- if (!fp_rounding && /* If printf doesn't round, */
- (places > 0 || /* round result to decimal places. */
- (places == 0 && round)))
- fpresult += (0.5 / pow(10.0,(CKFLOAT)places));
- y = (ftmp == 0.0) ? 1 : (int)log10(ftmp);
- size = y + x + 3; /* Estimated length of result */
- if (fpresult < 0.0) size++;
- #else
- size = 200; /* No way to estimate, be generous */
- #endif /* FNFLOAT */
- debug(F101,"fpformat size","",size);
- if (fpfbufpos > (FPFMTSIZ - size)) /* Wrap around if necessary */
- fpfbufpos = 0;
- debug(F101,"fpformat fpfbufpos 1","",fpfbufpos);
- buf = &fpfmtbuf[fpfbufpos];
- if (places > 0) { /* If places specified */
- /* use specified places to write given number of digits */
- sprintf(fbuf,"%%0.%df",places); /* SAFE */
- sprintf(buf,fbuf,fpresult); /* SAFE */
- } else { /* Otherwise... */
- /* Go for max precision */
- sprintf(fbuf,"%%0.%df",fp_digits); /* SAFE */
- sprintf(buf,fbuf,fpresult); /* SAFE */
- }
- if (buf[0] == '-') sign = 1;
- debug(F111,"fpresult 1 errno",buf,errno); /* Check for over/underflow */
- debug(F111,"fpresult 1 fpfbufpos",buf,fpfbufpos);
- /* Give requested decimal places */
- for (i = sign; i < FPFMTSIZ && buf[i]; i++) {
- if (buf[i] == '.') /* First find the decimal point */
- break;
- else if (i > fp_digits + sign - 1) /* replacing garbage */
- buf[i] = '0'; /* digits with 0... */
- }
- if (buf[i] == '.') { /* Have decimal point */
- int gotend = 0;
- /* places < 0 so truncate fraction */
- if (places < 0 || (places == 0 && round)) {
- buf[i] = NUL;
- } else if (places > 0) { /* d > 0 so this many decimal places */
- i++; /* First digit after decimal */
- for (j = 0; j < places; j++) { /* Truncate after d decimal */
- if (!buf[j+i]) /* places or extend to d */
- gotend = 1; /* decimal places. */
- if (gotend || j+i+sign > fp_digits)
- buf[j+i] = '0';
- }
- buf[j+i] = NUL;
- } else { /* places == 0 so Do The Right Thing */
- for (j = (int)strlen(buf) - 1; j > i+1; j--) {
- if ((j - sign) > fp_digits)
- buf[j] = '0';
- if (buf[j] == '0')
- buf[j] = NUL; /* Strip useless trailing 0's. */
- else
- break;
- }
- }
- }
- fpfmtbuf[FPFMTSIZ-1] = NUL;
- j = strlen(buf);
- sign = 0;
- for (i = j-1; i >= 0; i--) {
- if (buf[i] == '9')
- nines++;
- else
- break;
- }
- /* Do something about xx.xx99999999... */
- if (nines > 5) {
- if (isdigit(buf[i]) && i < FPFMTSIZ - 2) {
- buf[i] = buf[i] + 1;
- buf[i+1] = '0';
- buf[i+2] = '\0';
- }
- }
- if (!strncmp(buf,"-0.0",FPFMTSIZ))
- ckstrncpy(buf,"0.0",FPFMTSIZ);
- fpfbufpos += (int)strlen(buf) + 1;
- return((char *)buf);
- }
- #endif /* CKFLOAT */
- static VOID
- evalerr(fn) char * fn; {
- if (fndiags) {
- if (divbyzero)
- ckmakmsg(fnval,FNVALL,"<ERROR:DIVIDE_BY_ZERO:\\f",fn,"()>",NULL);
- else
- ckmakmsg(fnval,FNVALL,"<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- }
- }
- static int
- ckcindex(c,s) char c, *s; {
- int rc;
- if (!c || !s) return(0);
- for (rc = 0; s[rc]; rc++) {
- if (c == s[rc]) return(rc+1);
- }
- return(0);
- }
- static char *
- dokwval(s,sep) char * s, * sep; {
- char c = '\0', * p, * kw = NULL, * vp = NULL;
- char * rc = "0"; /* Return code */
- int x = 0;
- if (!s) return(rc);
- if (!*s) return(rc);
- debug(F110,"kwval arg",s,0);
- debug(F110,"kwval sep",sep,0);
- p = (char *)malloc((int)strlen(s)+1);
- if (!p) goto xdokwval;
- strcpy(p,s); /* SAFE */
- s = p;
- while (*s < '!' && *s > '\0') /* Get first nonblank */
- s++;
- if (!*s) goto xdokwval;
- if (ckcindex(*s,sep)) /* Separator but no keyword */
- goto xdokwval;
- kw = s; /* Keyword */
- while (*s > ' ') {
- if (ckcindex(*s,sep)) { /* keyword=... */
- c = *s;
- break;
- }
- s++;
- }
- if (*kw) rc = "1"; /* Have keyword, promote return code */
- *s++ = NUL; /* Terminate keyword */
- while (*s < '!' && *s > '\0') /* Skip blanks */
- s++;
- if (!c && ckcindex(*s,sep)) {
- c = *s++; /* Have separator */
- while (*s < '!' && *s > '\0') /* Skip blanks */
- s++;
- }
- if (c) {
- vp = s;
- if (*vp) rc = "2"; /* Have value, another promotion */
- #ifdef COMMENT
- while (*s > ' ') /* Skip to end */
- s++;
- *s = NUL; /* Terminate value */
- #endif /* COMMENT */
- }
- debug(F110,"kwval c",ckctoa(c),0);
- debug(F110,"kwval keyword",kw,0);
- debug(F110,"kwval value",vp,0);
- makestr(&lastkwval,kw);
- vp = brstrip(vp);
- debug(F110,"kwval value",vp,0);
- x = addmac(kw,vp);
- debug(F111,"kwval addmac",kw,x);
- xdokwval:
- if (p) free(p);
- return((x < 0) ? "-1" : rc);
- }
- static int
- isaarray(s) char * s; { /* Is s an associative array element */
- int state = 0;
- CHAR c;
- if (!s) return(0);
- while ((c = *s++)) {
- if (!isprint(c)) {
- return(0);
- } else if (c == '<') {
- if (state != 0)
- return(0);
- state = 1;
- } else if (c == '>') {
- return((state != 1 || *s) ? 0 : 1);
- }
- }
- return(0);
- }
- /* J P G D A T E -- Get "date taken" from JPG file Exif data */
- /*
- This routine doesn't follow the Exif spec, it just hunts for
- date-time strings in the first 8K of the JPG and keeps the earliest one.
- Call with file pointer, returns Exif date-time string "yyyy:mm:dd hh:mm:ss"
- or an empty string if none found.
- */
- #define JPGYEAR 1
- #define JPGMONTH 2
- #define JPGDAY 3
- #define JPGHOUR 4
- #define JPGMIN 5
- #define JPGSEC 6
- #define JPGDATEBUF 8192 /* Should be more than enough bytes to find date */
- static char *
- jpgdate(fp) FILE * fp; {
- static char datebuf[20];
- char tmpbuf[20];
- CHAR buf[JPGDATEBUF+1];
- CHAR * p;
- CHAR * z;
- CHAR c;
- int i;
- int k = 0;
- int n = 0;
- int count = 0;
- int state = 0;
- if (fp == NULL)
- return("");
- rewind(fp);
- for (i = 0; i < 20; i++) { datebuf[i] = NUL; tmpbuf[i] = NUL; }
- datebuf[0] = NUL;
- tmpbuf[0] = NUL;
- count = fread(buf,1,JPGDATEBUF,fp); /* Read a buffer */
- if (count == EOF || count == 0) {
- return("");
- }
- p = (CHAR *) buf;
- z = p + JPGDATEBUF;
- while (p < z) {
- c = *p++;
- n++;
- if (c != ' ' && c != ':' && !isdigit(c)) {
- state = 0;
- k = 0;
- continue;
- }
- switch (state) {
- case 0:
- if (c == '1' && *p == '9') state = JPGYEAR;
- else if (c == '2' && *p == '0') state = JPGYEAR;
- if (state == JPGYEAR) {
- k = 0;
- tmpbuf[k++] = c;
- }
- continue;
- case JPGYEAR:
- if (c == ':' && k == 4) {
- tmpbuf[k++] = c;
- state = JPGMONTH;
- continue;
- }
- if (k > 3 || !isdigit(c))
- state = k = 0;
- else
- tmpbuf[k++] = c;
- continue;
- case JPGMONTH:
- if (c == ':' && k == 7) {
- tmpbuf[k++] = c;
- state = JPGDAY;
- continue;
- }
- if (k > 6 || !isdigit(c))
- state = k = 0;
- else
- tmpbuf[k++] = c;
- continue;
- case JPGDAY:
- if (c == ' ' && k == 10) {
- tmpbuf[k++] = c;
- state = JPGHOUR;
- continue;
- }
- if (k > 9 || !isdigit(c))
- state = k = 0;
- else
- tmpbuf[k++] = c;
- continue;
- case JPGHOUR:
- if (c == ':' && k == 13) {
- tmpbuf[k++] = c;
- state = JPGMIN;
- continue;
- }
- if (k > 12 || !isdigit(c))
- state = k = 0;
- else
- tmpbuf[k++] = c;
- continue;
- case JPGMIN:
- if (c == ':' && k == 16) {
- tmpbuf[k++] = c;
- state = JPGSEC;
- continue;
- }
- if (k > 15 || !isdigit(c))
- state = k = 0;
- else
- tmpbuf[k++] = c;
- continue;
- case JPGSEC:
- if (!isdigit(c) || !isdigit(*p)) {
- state = k = 0;
- continue;
- }
- tmpbuf[k++] = c;
- tmpbuf[k++] = *p;
- tmpbuf[k] = NUL;
- }
- if (!datebuf[0]) { /* First date */
- strncpy(datebuf,tmpbuf,19);
- } else if (strncmp(tmpbuf,datebuf,19) < 0) { /* Earlier date */
- strncpy(datebuf,tmpbuf,19);
- }
- }
- return((char *) datebuf);
- }
- int /* Is character alphnumeric? */
- cisalphanum(ch) CHAR ch; { /* i.e. a letter, digit, @, $, or _ */
- /* All 8-bit characters are counted as alphanumeric */
- int c;
- c = (int)ch; /* Avoid C-language character syntax */
- if (c == 36) return(1); /* '$' is alphanumeric */
- if (c == 95) return(1); /* '_' is alphanumeric */
- if (c < 48) return(0); /* Space, punctuation, math */
- if (c > 57 && c < 64) return(0); /* Between '9' and '@' */
- if (c > 90 && c < 97) return(0); /* Between 'Z' and 'a' */
- if (c > 122 && c < 127) return(0); /* Between 'z' and DEL */
- return(1);
- }
- int /* Is character non-alphanumeric */
- cnonalphanum(ch) CHAR ch; { /* i.e. not letter, digit, [$@_] */
- int c;
- c = (int)ch; /* Avoid C-language character syntax */
- if (c == 36) return(0); /* '$' is alphanumeric */
- if (c == 95) return(0); /* '_' is alphanumeric */
- if (c < 48) return(1); /* Space, punctuation, math */
- if (c > 57 && c < 64) return(1); /* Between '9' and '@' */
- if (c > 90 && c < 97) return(1); /* Between 'Z' and 'a' */
- if (c > 122 && c < 127) return(1); /* Between 'z' and DEL */
- return(0);
- }
- /* Tell if a string contains only alphanumeric characters */
- int
- isalphanum(s) char *s; {
- CHAR c;
- while ((c = (int)(*s++))) {
- if (!cisalphanum(c)) return(0);
- }
- return(1);
- }
- /* Tell if a string contains only non-alphanumeric characters */
- int
- nonalphanum(s) char *s; {
- CHAR c;
- while ((c = (int)(*s++))) {
- if (!cnonalphanum(c)) return(0);
- }
- return(1);
- }
- static char * /* Evaluate builtin functions */
- fneval(fn,argp,argn,xp) char *fn, *argp[]; int argn; char * xp; {
- int i=0, j=0, k=0, len1=0, len2=0, len3=0, n=0, t=0, x=0, y=0;
- int cx, failed = 0; /* Return code, 0 = ok */
- long z = 0L;
- char *bp[FNARGS + 1]; /* Pointers to malloc'd strings */
- char c = NUL;
- char *p = NULL, *s = NULL;
- char *val1 = NULL, *val2 = NULL; /* Pointers to numeric string values */
- #ifdef RECURSIVE
- int rsave = recursive;
- #endif /* RECURSIVE */
- #ifdef OS2
- int zsave = zxpn;
- #endif /* OS2 */
- if (!fn) fn = ""; /* Protect against null pointers */
- if (!*fn) return("");
- for (i = 0; i < FNARGS; i++) /* Initialize argument pointers */
- bp[i] = NULL;
- /*
- IMPORTANT: Note that argn is not an accurate count of the number of
- arguments. We can't really tell if an argument is null until after we
- execute the code below. So argn is really the maximum number of arguments
- we might have. Argn should always be at least 1, even if the function is
- called with empty parentheses (but don't count on it).
- */
- debug(F111,"fneval",fn,argn);
- debug(F110,"fneval",argp[0],0);
- if (argn > FNARGS) /* Discard excess arguments */
- argn = FNARGS;
- fndepth++;
- debug(F101,"fneval fndepth","",fndepth);
- p = fnval;
- fnval[0] = NUL;
- y = lookup(fnctab,fn,nfuncs,&x); /* Look up the function name */
- cx = y; /* Because y is too generic... */
- if (cx < 0) { /* Not found */
- failed = 1;
- if (fndiags) { /* FUNCTION DIAGNOSTIC ON */
- int x;
- x = strlen(fn);
- /* The following sprintf's are safe */
- switch (cx) {
- case -1:
- if (x + 32 < FNVALL)
- sprintf(fnval,"<ERROR:NO_SUCH_FUNCTION:\\f%s()>",fn);
- else
- sprintf(fnval,"<ERROR:NO_SUCH_FUNCTION>");
- break;
- case -2:
- if (x + 26 < FNVALL)
- sprintf(fnval,"<ERROR:NAME_AMBIGUOUS:\\f%s()>",fn);
- else
- sprintf(fnval,"<ERROR:NAME_AMBIGUOUS>");
- break;
- case -3:
- sprintf(fnval,"<ERROR:FUNCTION_NAME_MISSING:\\f()>");
- break;
- default:
- if (x + 26 < FNVALL)
- sprintf(fnval,"<ERROR:LOOKUP_FAILURE:\\f%s()>",fn);
- else
- sprintf(fnval,"<ERROR:LOOKUP_FAILURE>");
- break;
- }
- }
- goto fnend; /* Always leave via common exit */
- }
- fn = fnctab[x].kwd; /* Full name of function */
- if (argn < 0) {
- failed = 1;
- p = fnval;
- if (fndiags)
- sprintf(fnval,"<ERROR:MISSING_ARG:\\f%s()>",fn);
- goto fnend;
- }
- if (cx == FN_LIT) { /* literal(arg1) */
- debug(F010,"flit",xp,0);
- p = xp ? xp : ""; /* Return a pointer to arg itself */
- goto fnend;
- }
- #ifdef DEBUG
- if (deblog) {
- int j;
- for (j = 0; j < argn; j++)
- debug(F111,"fneval arg",argp[j],j);
- }
- #endif /* DEBUG */
- for (j = argn-1; j >= 0; j--) { /* Uncount empty trailing args */
- if (!argp[j])
- argn--;
- else if (!*(argp[j]))
- argn--;
- else break;
- }
- debug(F111,"fneval argn",fn,argn);
- /*
- \fliteral() and \fcontents() are special functions that do not evaluate
- their arguments, and are treated specially here. After these come the
- functions whose arguments are evaluated in the normal way.
- */
- #ifdef COMMENT
- /* (moved up) */
- if (cx == FN_LIT) { /* literal(arg1) */
- debug(F110,"flit",xp,0);
- p = xp ? xp : ""; /* Return a pointer to arg itself */
- goto fnend;
- }
- #endif /* COMMENT */
- if (cx == FN_CON) { /* Contents of variable, unexpanded. */
- char c;
- int subscript = 0;
- if (!(p = argp[0]) || !*p) {
- failed = 1;
- p = fnval;
- if (fndiags)
- sprintf(fnval,"<ERROR:MISSING_ARG:\\fcontents()>");
- goto fnend;
- }
- p = brstrip(p);
- if (*p == CMDQ) p++;
- if ((c = *p) == '%') { /* Scalar variable. */
- c = *++p; /* Get ID character. */
- p = ""; /* Assume definition is empty */
- if (!c) { /* Double paranoia */
- failed = 1;
- p = fnval;
- if (fndiags)
- sprintf(fnval,"<ERROR:ARG_BAD_VARIABLE:\\fcontents()>");
- goto fnend;
- }
- if (c >= '0' && c <= '9') { /* Digit for macro arg */
- if (maclvl < 0) /* Digit variables are global */
- p = g_var[c]; /* if no macro is active */
- else /* otherwise */
- p = m_arg[maclvl][c - '0']; /* they're on the stack */
- } else if (c == '*') {
- #ifdef COMMENT
- p = (maclvl > -1) ? m_line[maclvl] : topline;
- if (!p) p = "";
- #else
- int nx = FNVALL;
- char * sx = fnval;
- p = fnval;
- #ifdef COMMENT
- if (cmdsrc() == 0 && topline)
- p = topline;
- else
- #endif /* COMMENT */
- if (zzstring("\\fjoin(&_[],{ },1)",&sx,&nx) < 0) {
- failed = 1;
- p = fnval;
- if (fndiags)
- sprintf(fnval,"<ERROR:OVERFLOW:\\fcontents()>");
- debug(F110,"zzstring fcontents(\\%*)",p,0);
- }
- #endif /* COMMENT */
- } else {
- if (isupper(c)) c -= ('a'-'A');
- p = g_var[c]; /* Letter for global variable */
- }
- if (!p) p = "";
- goto fnend;
- } else if (c == '&') { /* Array reference. */
- int vbi, d;
- if (arraynam(p,&vbi,&d) < 0) { /* Get name and subscript */
- failed = 1;
- p = fnval;
- if (fndiags)
- sprintf(fnval,"<ERROR:ARG_BAD_ARRAY:\\fcontents()>");
- goto fnend;
- }
- subscript = chkarray(vbi,d); /* Check the array */
- if (subscript >= 0) { /* Array is declared? */
- vbi -= ARRAYBASE; /* Convert name to index */
- if (a_dim[vbi] >= d) { /* If subscript in range */
- char **ap;
- ap = a_ptr[vbi]; /* get data pointer */
- if (ap) { /* and if there is one */
- p = ap[d]; /* return it */
- goto fnend;
- }
- }
- } else { /* Array not declared or element */
- fnval[0] = NUL; /* out of range - return null string */
- p = fnval; /* fdc 2010-12-30 */
- goto fnend;
- }
- } else {
- failed = 1;
- p = fnval;
- if (fndiags)
- sprintf(fnval,"<ERROR:ARG_NOT_VARIABLE:\\fcontents()>");
- goto fnend;
- }
- }
- p = fnval; /* Default result pointer */
- fnval[0] = NUL; /* Default result = empty string */
- for (i = 0; i < argn; i++) { /* Loop to expand each argument */
- n = MAXARGLEN; /* Allow plenty of space */
- bp[i] = s = malloc(n+1); /* Allocate space for this argument */
- if (bp[i] == NULL) { /* Handle failure to get space */
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:MALLOC_FAILURE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- p = argp[i] ? argp[i] : ""; /* Point to this argument */
- /*
- Trim leading and trailing spaces from the original argument, before
- evaluation. This code new to edit 184. Fixed in edit 199 to trim
- blanks BEFORE stripping braces.
- */
- {
- int x, j;
- x = strlen(p);
- j = x - 1; /* Trim trailing whitespace */
- while (j > 0 && (*(p + j) == SP || *(p + j) == HT))
- *(p + j--) = NUL;
- while (*p == SP || *p == HT) /* Strip leading whitespace */
- p++;
- x = strlen(p);
- if (*p == '{' && *(p+x-1) == '}') { /* NOW strip braces */
- p[x-1] = NUL;
- p++;
- x -= 2;
- }
- }
- /* Now evaluate the argument */
- debug(F111,"fneval calling zzstring",p,n);
- t = zzstring(p,&s,&n); /* Expand arg into new space */
- debug(F101,"fneval zzstring","",t);
- debug(F101,"fneval zzstring","",n);
- if (t < 0) {
- debug(F101,"fneval zzstring fails, arg","",i);
- failed = 1;
- if (fndiags) {
- if (n == 0)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_TOO_LONG:\\f",fn,"()>",NULL);
- else
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_EVAL_FAILURE:\\f",fn,"()>",NULL);
- }
- goto fnend;
- }
- debug(F111,"fneval arg",bp[i],i);
- }
- #ifdef DEBUG
- if (deblog) {
- int j;
- debug(F110,"fneval",fn,0);
- for (j = 0; j < argn; j++) {
- debug(F111,"fneval arg post eval",argp[j],j);
- debug(F111,"fneval evaluated arg",bp[j],j);
- }
- }
- #endif /* DEBUG */
- {
- /* Adjust argn for empty trailing arguments. */
- /* For example when an arg is a variable name but the */
- /* variable has no value. July 2006. */
- int j, old; char *p;
- old = argn;
- for (j = argn - 1; j >= 0; j--) {
- p = bp[j];
- if (!p)
- argn--;
- else if (!*p)
- argn--;
- else
- break;
- }
- #ifdef DEBUG
- if (argn != old)
- debug(F101,"fneval adjusted argn","",argn);
- #endif /* DEBUG */
- }
- /*
- From this point on, bp[0..argn-1] are not NULL and all must be freed
- before returning. BUT NOTE: if no arguments were given, bp[0] *is* NULL.
- */
- if (argn < 1) { /* Catch required args missing */
- switch (cx) {
- case FN_DEF:
- case FN_EVA:
- case FN_EXE:
- case FN_CHR:
- /* case FN_COD: */
- case FN_MAX:
- case FN_MIN:
- case FN_MOD:
- case FN_FD:
- case FN_FS:
- case FN_TOD:
- case FN_FFN:
- case FN_BSN:
- case FN_RAW:
- case FN_CMD:
- case FN_2HEX:
- case FN_2OCT:
- case FN_DNAM:
- #ifdef FN_ERRMSG
- case FN_ERRMSG:
- #endif /* FN_ERRMSG */
- #ifdef CK_KERBEROS
- case FN_KRB_TK:
- case FN_KRB_NX:
- case FN_KRB_IV:
- case FN_KRB_TT:
- case FN_KRB_FG:
- #endif /* CK_KERBEROS */
- case FN_MJD2:
- case FN_N2TIM:
- case FN_DIM:
- case FN_DATEJ:
- case FN_PNCVT:
- case FN_PERM:
- case FN_ALOOK:
- case FN_TLOOK:
- case FN_ABS:
- case FN_AADUMP:
- case FN_JOIN:
- #ifdef CKFLOAT
- case FN_FPABS:
- case FN_FPEXP:
- case FN_FPLOG:
- case FN_FPLN:
- case FN_FPMOD:
- case FN_FPSQR:
- case FN_FPADD:
- case FN_FPDIV:
- case FN_FPMUL:
- case FN_FPPOW:
- case FN_FPSUB:
- case FN_FPINT:
- case FN_FPROU:
- case FN_FPSIN:
- case FN_FPCOS:
- case FN_FPTAN:
- #endif /* CKFLOAT */
- #ifdef TCPSOCKET
- case FN_HSTADD:
- case FN_HSTNAM:
- #endif /* TCPSOCKET */
- case FN_DELSEC:
- #ifdef COMMENT
- case FN_KWVAL:
- case FN_SLEEP:
- case FN_MSLEEP:
- #endif /* COMMENT */
- #ifdef NT
- case FN_SNAME:
- case FN_LNAME:
- #endif /* NT */
- case FN_FILEINF:
- case FN_FILECMP:
- failed = 1;
- p = fnval;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
- goto fnend;
- }
- }
- p = fnval; /* Reset these again. */
- fnval[0] = NUL;
- switch (cx) { /* Do function on expanded args. */
- #ifdef TCPSOCKET
- case FN_HSTADD:
- p = ckaddr2name(bp[0]);
- goto fnend;
- case FN_HSTNAM:
- p = ckname2addr(bp[0]);
- goto fnend;
- #endif /* TCPSOCKET */
- case FN_DEF: /* \fdefinition(arg1) */
- k = isaarray(bp[0]) ?
- mxxlook(mactab,bp[0],nmac) :
- mxlook(mactab,bp[0],nmac);
- p = (k > -1) ? mactab[k].mval : "";
- goto fnend;
- case FN_EVA: /* \fevaluate(arg1) */
- p = *(bp[0]) ? evalx(bp[0]) : "";
- if (!*p && fndiags) {
- failed = 1;
- p = fnval;
- evalerr(fn);
- }
- goto fnend;
- case FN_EXE: /* \fexecute(arg1) */
- j = (int)strlen(s = bp[0]); /* Length of macro invocation */
- p = ""; /* Initialize return value to null */
- if (j) { /* If there is a macro to execute */
- while (*s == SP) s++,j--; /* strip leading spaces */
- p = s; /* remember beginning of macro name */
- for (i = 0; i < j; i++) { /* find end of macro name */
- if (*s == SP)
- break;
- s++;
- }
- if (*s == SP) { /* if there was a space after */
- *s++ = NUL; /* terminate the macro name */
- while (*s == SP) s++; /* skip past any extra spaces */
- } else
- s = ""; /* maybe there are no arguments */
- if (p && *p) {
- k = mlook(mactab,p,nmac); /* Look up the macro name */
- debug(F111,"fexec mlook",p,k);
- } else
- k = -1;
- if (k < 0) {
- char * p2 = p;
- failed = 1;
- p = fnval;
- if (fndiags)
- ckmakxmsg(fnval,FNVALL,
- "<ERROR:NO_SUCH_MACRO:\\f",fn,"(",p2,")>",
- NULL,NULL,NULL,NULL,NULL,NULL,NULL);
- goto fnend;
- }
- /*
- This is just a WEE bit dangerous because we are copying up to 9 arguments
- into the space reserved for one. It won't overrun the buffer, but if there
- are lots of long arguments we might lose some. The other problem is that if
- the macro has more than 3 arguments, the 4th through last are all
- concatenated onto the third. (The workaround is to use spaces rather than
- commas to separate them.) Leaving it like this to avoid having to allocate
- tons more buffers.
- */
- if (argn > 1) { /* Commas used instead of spaces */
- int i;
- char *p = bp[0]; /* Reuse this space */
- *p = NUL; /* Make into dodo() arg list */
- for (i = 1; i < argn; i++) {
- ckstrncat(p,bp[i],MAXARGLEN);
- ckstrncat(p," ",MAXARGLEN);
- }
- s = bp[0]; /* Point to new list */
- }
- p = ""; /* Initialize return value */
- if (k >= 0) { /* If macro found in table */
- /* Go set it up (like DO cmd) */
- if ((j = dodo(k,s,cmdstk[cmdlvl].ccflgs)) > 0) {
- if (cmpush() > -1) { /* Push command parser state */
- extern int ifc;
- int ifcsav = ifc; /* Push IF condition on stack */
- k = parser(1); /* Call parser to execute the macro */
- cmpop(); /* Pop command parser */
- ifc = ifcsav; /* Restore IF condition */
- if (k == 0) { /* No errors, ignore action cmds. */
- p = mrval[maclvl+1]; /* If OK, set return value. */
- if (p == NULL) p = "";
- }
- } else { /* Can't push any more */
- debug(F100,"zzstring fneval fexec failure","",0);
- printf("\n?\\fexec() too deeply nested\n");
- while (cmpop() > -1) ;
- p = "";
- }
- }
- }
- }
- debug(F110,"zzstring fneval fexecute final p",p,0);
- goto fnend;
- #ifdef RECURSIVE
- case FN_RDIR: /* \frdir..() - Recursive dir count */
- case FN_RFIL: /* \frfiles() - Recursive file count */
- /* recursive = 2; */ /* fall thru... */
- #endif /* RECURSIVE */
- case FN_FC: /* \ffiles() - File count. */
- case FN_DIR: { /* \ffdir.() - Directory count. */
- char abuf[16], *s;
- char ** ap = NULL;
- int x, xflags = 0;
- if (matchdot)
- xflags |= ZX_MATCHDOT;
- if (cx == FN_RDIR || cx == FN_RFIL) {
- xflags |= ZX_RECURSE;
- #ifdef CKSYMLINK
- /* Recursive - don't follow symlinks */
- xflags |= ZX_NOLINKS;
- #endif /* CKSYMLINK */
- }
- failed = 0;
- if (argn < 1) {
- p = "0";
- goto fnend;
- }
- if (cx == FN_DIR || cx == FN_RDIR) { /* Only list directories */
- debug(F100,"FN_DIR or FN_RDIR","",0);
- xflags |= ZX_DIRONLY;
- #ifdef OS2
- zxpn = 1; /* Use the alternate list */
- #endif /* OS2 */
- } else { /* List only files */
- debug(F100,"Not FN_DIR or FN_RDIR","",0);
- xflags |= ZX_FILONLY;
- #ifdef OS2
- zxpn = 1; /* Use the alternate list */
- #endif /* OS2 */
- }
- if (*(bp[0])) {
- k = nzxpand(bp[0],xflags);
- if (k < 0) k = 0;
- sprintf(fnval,"%d",k); /* SAFE */
- p = fnval;
- } else
- p = "0";
- if (argn > 1) { /* Assign list to array */
- fnval[0] = NUL; /* Initial return value */
- ckstrncpy(abuf,bp[1],16); /* Get array reference */
- s = abuf;
- if (*s == CMDQ) s++;
- failed = 1; /* Assume it's bad */
- p = fnval; /* Point to result */
- if (fndiags) /* Default is this error message */
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
- if (s[0] != '&') /* "Address" of array */
- goto fnend;
- if (s[2])
- if (s[2] != '[' || s[3] != ']')
- goto fnend;
- if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
- s[1] += 32;
- if ((x = dclarray(s[1],k)) < 0) /* File list plus count */
- goto fnend;
- failed = 0; /* Unset failure flag */
- ap = a_ptr[x]; /* Point to array we just declared */
- sprintf(fnval,"%d",k); /* SAFE */
- }
- #ifdef OS2
- if (ap) { /* We are making an array */
- int i;
- char tmp[16];
- ap[0] = NULL; /* Containing number of files */
- makestr(&(ap[0]),ckitoa(k));
- ckstrncpy(tmp,fnval,16); /* Save return value */
- for (i = 1; i <= k; i++) { /* Fill it */
- ap[i] = NULL;
- znext(fnval); /* Next filename */
- if (!*fnval) /* No more, done */
- break; /* In case a premature end */
- makestr(&(ap[i]),fnval);
- }
- #ifdef ZXREWIND
- k = zxrewind(); /* Reset the file expansion */
- #else
- k = nzxpand(bp[0],xflags);
- #endif /* ZXREWIND */
- ckstrncpy(fnval,tmp,FNVALL); /* Restore return value */
- }
- #else /* OS2 */
- { /* Make copies of the list */
- int i; char tmp[16];
- if (flist) { /* Free old file list, if any */
- for (i = 0; flist[i]; i++) { /* and each string */
- free(flist[i]);
- flist[i] = NULL;
- }
- free((char *)flist);
- }
- ckstrncpy(tmp,fnval,16); /* Save our return value */
- flist = (char **) malloc((k+1) * sizeof(char *)); /* New array */
- if (flist) {
- for (i = 0; i <= k; i++) { /* Fill it */
- flist[i] = NULL;
- znext(fnval); /* Next filename */
- if (!*fnval) /* No more, done */
- break;
- makestr(&(flist[i]),fnval);
- }
- if (ap) { /* If array pointer given */
- ap[0] = NULL;
- makestr(&(ap[0]),ckitoa(k));
- for (i = 0; i < k; i++) { /* Copy file list to array */
- ap[i+1] = NULL;
- makestr(&(ap[i+1]),flist[i]);
- }
- }
- }
- ckstrncpy(fnval,tmp,FNVALL); /* Restore return value */
- flistn = 0; /* Reset global list pointer */
- }
- #endif /* OS2 */
- #ifdef RECURSIVE
- recursive = rsave;
- #endif /* RECURSIVE */
- #ifdef OS2
- zxpn = zsave;
- #endif /* OS2 */
- }
- goto fnend;
- case FN_FIL: /* \fnextfile() - Next file in list. */
- p = fnval; /* (no args) */
- *p = NUL;
- #ifdef OS2
- zxpn = 1; /* OS/2 - use the alternate list */
- znext(p); /* Call system-dependent function */
- zxpn = zsave; /* Restore original list */
- #else
- if (flist) /* Others, use our own list. */
- if (flist[flistn])
- p = flist[flistn++];
- #endif /* OS2 */
- goto fnend;
- } /* Break up big switch... */
- switch (cx) {
- case FN_IND: /* \findex(s1,s2,start,occurrence) */
- case FN_RIX: /* \frindex(s1,s2,start,occurrence) */
- case FN_SEARCH: /* \fsearch(pat,string,start,occ) */
- case FN_RSEARCH: /* \frsearch(pat,string,start,occ) */
- case FN_COUNT: { /* \fcount(s1,s2,start) */
- int i = 0, right = 0, search = 0, count = 0;
- int desired = 1;
- right = (cx == FN_RIX || cx == FN_RSEARCH);
- search = (cx == FN_SEARCH || cx == FN_RSEARCH);
- count = (cx == FN_COUNT);
- p = "0";
- if (argn > 1) { /* Only works if we have 2 or 3 args */
- int start = 0;
- char * pat = NULL;
- len1 = (int)strlen(pat = bp[0]); /* length of string to look for */
- len2 = (int)strlen(s = bp[1]); /* length of string to look in */
- if (len1 < 1 || len2 < 1) /* Watch out for empty strings */
- goto fnend;
- start = right ? -1 : 0; /* Default starting position */
- if (argn > 2) {
- val1 = *(bp[2]) ? evalx(bp[2]) : "1";
- if (argn > 3) { /* Occurrence */
- val2 = *(bp[3]) ? evalx(bp[3]) : "1";
- if (chknum(val2)) desired = atoi(val2);
- if (desired * len1 > len2) goto fnend;
- }
- if (chknum(val1)) {
- int t;
- t = atoi(val1);
- if (!search) { /* Index or Rindex */
- j = len2 - len1; /* Length difference */
- t--; /* Convert position to 0-based */
- if (t < 0) t = 0;
- start = t;
- if (!right && start < 0) start = 0;
- } else { /* Search or Rsearch */
- int x;
- if (t < 0) t = 0;
- if (right) { /* Right to left */
- if (t > len2) t = len2;
- start = len2 - t - 1;
- if (start < 0)
- goto fnend;
- x = len2 - t;
- s[x] = NUL;
- } else { /* Left to right */
- start = t - 1;
- if (start < 0) start = 0;
- if (start >= len2)
- goto fnend;
- }
- }
- } else {
- failed = 1;
- evalerr(fn);
- p = fnval;
- goto fnend;
- }
- }
- if (count) { /* \fcount() */
- int j;
- for (i = 0; start < len2; i++) {
- j = ckindex(pat,bp[1],start,0,inpcas[cmdlvl]);
- if (j == 0) break;
- start = j;
- }
- } else if (search) { /* \fsearch() or \frsearch() */
- if (right && pat[0] == '^') {
- right = 0;
- start = 0;
- }
- if (right) { /* From right */
- int k, j = 1;
- if (start < 0)
- start = len2 - 1;
- i = 0;
- while (start >= 0 && j <= desired) {
- for (i = start;
- (i >= 0) &&
- !(k = ckmatch(pat,s+i,inpcas[cmdlvl],1+4));
- i--) ;
- if (k < 1) { /* No match */
- i = 0;
- break;
- }
- if (j == desired) { /* The match we want? */
- i += k; /* Yes, return string index */
- break;
- }
- j++; /* No, count this match */
- s[i] = NUL; /* null it out */
- start = i-1; /* move left and look again */
- }
- } else { /* From left */
- int j;
- i = 0;
- for (j = 1; j <= desired && start < len2; j++) {
- i = ckmatch(pat,&s[start],inpcas[cmdlvl],1+4);
- if (i == 0 || j == desired) break;
- start += i + 1;
- }
- if (j == desired && i != 0)
- i += start;
- else
- i = 0;
- }
- } else { /* index or rindex */
- int j = 0;
- i = 0;
- for (j = 1; j <= desired && start < len2; j++) {
- i = ckindex(pat,bp[1],start,right,inpcas[cmdlvl]);
- if (i == 0 || j == desired) break;
- start = (right) ? len2 - i + 1 : i;
- }
- if (j != desired)
- i = 0;
- }
- sprintf(fnval,"%d",i); /* SAFE */
- p = fnval;
- }
- goto fnend;
- }
- case FN_RPL: /* \freplace(s1,s2,s3) */
- /*
- s = bp[0] = source string (len1)
- bp[1] = match string (len2)
- bp[2] = replacement string (len3)
- bp[3] = which occurrence (default = all);
- bp[4] = context sensitive ("word mode") 20171005
- fnval = p = destination (result) string
- */
- if (argn < 1) /* Nothing */
- goto fnend;
- if (argn < 2) { /* Need at least two args */
- ckstrncpy(p,bp[0],FNVALL);
- } else {
- int occur = 0, xx = 0, context = 0, j2;
- int left = 0, right = 0, ok = 0;
- len1 = (int)strlen(bp[0]); /* length of string to look in */
- len2 = (int)strlen(bp[1]); /* length of string to look for */
- len3 = (argn < 3) ? 0 : (int)strlen(bp[2]); /* Len of replacemnt */
- j = len1 - len2 + 1; /* source - match + 1 */
- j2 = j;
- if (argn > 3) {
- if (chknum(bp[3])) {
- occur = atoi(bp[3]);
- } else {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- }
- /*
- Context-sensitive "word mode" replace, new for C-Kermit 9.0.304 Dev.23,
- October 2017. Can be removed by defining NORPLWORDMODE.
- */
- #ifdef RPLWORDMODE
- if (argn > 4) {
- if (chknum(bp[4])) {
- context = atoi(bp[4]);
- } else {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- }
- #endif /* RPLWORDMODE */
- /* If args out of whack... */
- if (j < 1 || len1 == 0 || len2 == 0) {
- ckstrncpy(p,bp[0],FNVALL); /* just return original string */
- p[FNVALL] = NUL;
- } else {
- ragain:
- s = bp[0]; /* Point to beginning of source string */
-
- xx = 0; /* Match counter */
- while (*s) { /* For each character in it...*/
- /* Compare current segment with target string */
- if (!ckstrcmp(bp[1],s,len2,inpcas[cmdlvl])) {
- ok = 1; /* Assume OK to replace */
- #ifdef RPLWORDMODE
- if (context) { /* New 2017-10-05 */
- CHAR c;
- left = 0;
- right = 0;
- ok = 0; /* Mustcheck context before replacing */
- if (!strncmp(bp[1],"...",len2)) {
- /* Special case for ellipsis */
- if (s > bp[0]) { /* Can't begin a line */
- c = *(s-1); /* Check preceding char */
- if (c != 32 && c != '.')
- left = 1;
- }
- c = *(s+len2); /* Check following char */
- if (c != '.' && (c == SP || c == '\0'))
- right = 1;
- } else if (isalphanum(bp[1])) {
- /* Target string is alphanumeric... */
- if (s == bp[0]) { /* At beginning of string */
- left = 1; /* So left boundary ok */
- } else { /* Otherwise */
- c = *(s-1); /* Check preceding char */
- if (cnonalphanum(c)) /* If not alphamum */
- left = 2; /* left boundary ok */
- }
- c = *(s+len2); /* Check following character */
- if (c == '\0') /* If end of string */
- right = 1; /* Right boundary OK */
- else if (cnonalphanum(c))
- right = 2; /* Right boundary OK */
- } else if (nonalphanum(bp[1])) {
- /* Target is non-salphanumeric */
- if (s == bp[0]) { /* At beginning of line */
- left = 1; /* Left OK */
- } else { /* Otherwise */
- c = *(s-1); /* Check preceding char */
- if (cisalphanum(c) || c == SP)
- left = 2; /* Left OK */
- }
- c = *(s+len2); /* Check char after target */
- if (c == '\0') { /* At end of string */
- right = 1; /* Right OK */
- } else { /* Otherwise */
- if (cisalphanum(c) || c <= SP)
- right = 2; /* Right ok */
- }
- }
- /* If none of the above nothing is replaced */
- if (left && right) { /* Match accepted */
- ok = 1; /* OK to replace */
- xx++; /* Count this match */
- }
- } else
- #endif /* RPLWORDMODE */
- xx++; /* Straight replace - count every match */
- if (ok && (occur == 0 || occur == xx)) {
- if (len3) {
- ckstrncpy(p,bp[2],FNVALL);
- p += len3;
- }
- s += len2; /* and skip past it. */
- } else { /* matched but not selected */
- *p++ = *s++; /* Just copy this character */
- }
- } else { /* Didn't match */
- *p++ = *s++; /* just copy this character */
- }
- }
- *p = NUL;
- while ((*p++ = *s++)); /* Append the rest */
- if (occur < 0) { /* cheap... */
- occur = xx + occur + 1;
- xx = 0;
- p = fnval;
- j = j2;
- if (occur > 0)
- goto ragain;
- }
- }
- }
- p = fnval;
- goto fnend;
- case FN_CHR: /* \fcharacter(arg1) */
- val1 = *(bp[0]) ? evalx(bp[0]) : "";
- if (chknum(val1)) { /* Must be numeric */
- i = atoi(val1);
- if (i >= 0 && i < 256) { /* Must be an 8-bit value */
- p = fnval;
- *p++ = (char) i;
- *p = NUL;
- p = fnval;
- } else {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
- }
- } else {
- failed = 1;
- evalerr(fn);
- }
- goto fnend;
- case FN_COD: /* \fcode(string) */
- /*
- returns decimal character value of first char in string.
- or 0 if string empty or no string given.
- */
- p = "0";
- if (!bp[0]) goto fnend; /* No argument given */
- if ((int)strlen(bp[0]) < 1) /* Empty argument */
- goto fnend;
- i = (int) bp[0][0];
- debug(F111,"FN_CODE",bp[0],i);
- p = fnval;
- sprintf(p,"%d",(i & 0xff)); /* SAFE */
- debug(F111,"FN_CODE fnval",fnval,i);
- goto fnend;
- case FN_LEN: /* \flength(arg1) */
- if (argn > 0) {
- p = fnval;
- sprintf(p,"%d",(int)strlen(bp[0])); /* SAFE */
- } else p = "0";
- goto fnend;
- case FN_LOW: /* \flower(arg1) */
- s = bp[0] ? bp[0] : "";
- p = fnval;
- while (*s) {
- if (isupper(*s))
- *p = (char) tolower(*s);
- else
- *p = *s;
- p++; s++;
- }
- *p = NUL;
- p = fnval;
- goto fnend;
- case FN_MAX: /* \fmax(arg1,arg2) */
- case FN_MIN: /* \fmin(arg1,arg2) */
- case FN_MOD: /* \fmod(arg1,arg2) */
- val1 = *(bp[0]) ? evalx(bp[0]) : "";
- #ifdef COMMENT
- /* No longer necessary because evalx() no longer overwrites its */
- /* result every time it's called (2000/09/23). */
- free(bp[0]);
- bp[0] = NULL;
- #endif /* COMMENT */
- if (argn > 1) {
- #ifdef COMMENT
- /* Ditto... */
- bp[0] = malloc((int)strlen(val1)+1);
- if (bp[0])
- strcpy(bp[0],val1); /* safe */
- val1 = bp[0];
- #endif /* COMMENT */
- val2 = *(bp[1]) ? evalx(bp[1]) : "";
- if (chknum(val1) && chknum(val2)) {
- i = atoi(val1);
- j = atoi(val2);
- switch (y) {
- case FN_MAX:
- if (j < i) j = i;
- break;
- case FN_MIN:
- if (j > i) j = i;
- break;
- case FN_MOD:
- if (j == 0) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:DIVIDE_BY_ZERO:\\f",fn,"()>",NULL);
- else
- fnval[0] = NUL;
- goto fnend;
- } else
- j = i % j;
- }
- p = fnval;
- sprintf(p,"%d",j); /* SAFE */
- } else {
- failed = 1;
- evalerr(fn);
- }
- } else p = val1;
- goto fnend;
- } /* Break up big switch... */
- switch (y) {
- case FN_SUB: /* \fsubstr(arg1,arg2,arg3) */
- case FN_RIG: /* \fright(arg1,arg2) */
- case FN_LEF: /* \fleft(arg1,arg2) */
- if (argn < 1)
- goto fnend;
- val1 = "";
- if (argn > 1)
- if (*(bp[1]))
- val1 = evalx(bp[1]);
- #ifdef COMMENT
- if (bp[1]) free(bp[1]); /* Have to copy this */
- bp[1] = malloc((int)strlen(val1)+1);
- if (!bp[1]) {
- failed = 1;
- if (fndiags) {
- p = fnval;
- ckmakmsg(fnval,FNVALL,
- "<ERROR:MALLOC_FAILURE:\\f",fn,"()>",NULL);
- }
- goto fnend;
- }
- strcpy(bp[1],val1); /* safe */
- val1 = bp[1];
- #endif /* COMMENT */
- val2 = "";
- if (argn > 2)
- if (*(bp[2]))
- val2 = evalx(bp[2]);
- if (
- ((argn > 1) && (int)strlen(val1) && !rdigits(val1)) ||
- ((cx == FN_SUB) &&
- ((argn > 2) && (int)strlen(val2) && !rdigits(val2)))
- ) {
- failed = 1;
- evalerr(fn);
- } else {
- int lx;
- p = fnval; /* pointer to result */
- lx = strlen(bp[0]); /* length of arg1 */
- if (cx == FN_SUB) { /* substring */
- k = (argn > 2) ? atoi(val2) : MAXARGLEN; /* length */
- j = (argn > 1) ? atoi(val1) : 1; /* start pos for substr */
- } else if (cx == FN_LEF) { /* left */
- k = (argn > 1) ? atoi(val1) : lx;
- j = 1;
- } else { /* right */
- k = (argn > 1) ? atoi(val1) : lx; /* length */
- j = lx - k + 1; /* start pos for right */
- if (j < 1) j = 1;
- }
- if (k > 0 && j <= lx) { /* if start pos in range */
- s = bp[0]+j-1; /* point to source string */
- for (i = 0; (i < k) && (*p++ = *s++); i++) ; /* copy */
- }
- *p = NUL; /* terminate the result */
- p = fnval; /* and point to it. */
- }
- goto fnend;
- case FN_UPP: /* \fupper(arg1) */
- s = bp[0] ? bp[0] : "";
- p = fnval;
- while (*s) {
- if (islower(*s))
- *p = (char) toupper(*s);
- else
- *p = *s;
- p++; s++;
- }
- *p = NUL;
- p = fnval;
- goto fnend;
- case FN_REP: /* \frepeat(text,number) */
- if (argn < 1)
- goto fnend;
- val1 = "1";
- if (argn > 1)
- if (*(bp[1]))
- val1 = evalx(bp[1]);
- if (chknum(val1)) { /* Repeat count */
- n = atoi(val1);
- debug(F111,"SUNDAY frepeat n",val1,n);
- if (n > 0) { /* Make n copies */
- p = fnval;
- *p = '\0';
- k = (int)strlen(bp[0]); /* Make sure string has some length */
- debug(F111,"SUNDAY frepeat k","",k);
- debug(F111,"SUNDAY frepeat FNVALL","",FNVALL);
- if (k * n >= FNVALL) { /* But not too much... */
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:RESULT_TOO_LONG:\\f",fn,"()>",NULL);
- else
- fnval[0] = NUL;
- p = fnval;
- goto fnend;
- }
- if (k > 0) { /* If there is something to copy */
- for (i = 0; i < n; i++) { /* Copy loop */
- s = bp[0];
- for (j = 0; j < k; j++) {
- if ((p - fnval) >= FNVALL)
- break; /* shouldn't happen... */
- else
- *p++ = *s++;
- }
- }
- *p = NUL;
- }
- }
- } else {
- failed = 1;
- evalerr(fn);
- }
- p = fnval;
- goto fnend;
- #ifndef NOFRILLS
- case FN_REV: /* \freverse() */
- if (argn < 1)
- goto fnend;
- yystring(bp[0],&p);
- goto fnend;
- #endif /* NOFRILLS */
- case FN_RPA: /* \frpad() and \flpad() */
- case FN_LPA:
- if (argn < 1)
- goto fnend;
- val1 = "";
- if (argn > 1)
- if (*(bp[1]))
- val1 = evalx(bp[1]);
- if (argn == 1) { /* If a number wasn't given */
- p = fnval; /* just return the original string */
- ckstrncpy(p,bp[0],FNVALL);
- } else if (argn > 1 && !*val1) {
- failed = 1;
- evalerr(fn);
- } else /* if (chknum(val1)) */ { /* Repeat count */
- char pc;
- n = atoi(val1);
- if (n >= 0) {
- p = fnval;
- k = (int)strlen(bp[0]); /* Length of string to be padded */
- if (k >= n) { /* It's already long enough */
- ckstrncpy(p,bp[0],FNVALL);
- } else {
- if (n + k <= FNVALL) {
- pc = (char) ((argn < 3) ? SP : *bp[2]);
- if (!pc) pc = SP;
- if (cx == FN_RPA) { /* RPAD */
- strncpy(p,bp[0],k); /* (leave it like this) */
- p[k] = NUL;
- p += k;
- for (i = k; i < n; i++)
- *p++ = pc;
- } else { /* LPAD */
- n -= k;
- for (i = 0; i < n; i++)
- *p++ = pc;
- strncpy(p,bp[0],k); /* (leave it like this) */
- p[k] = NUL;
- p += k;
- }
- }
- *p = NUL;
- }
- }
- }
- p = fnval;
- goto fnend;
- #ifdef ZFCDAT
- case FN_FD: /* \fdate(filename) */
- p = fnval;
- s = zfcdat(bp[0]);
- if (!s) s = "";
- if (!*s) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:FILE_NOT_FOUND:\\f",fn,"()>",NULL);
- goto fnend;
- }
- ckstrncpy(fnval,s,FNVALL);
- #endif /* ZFCDAT */
- goto fnend;
- } /* Break up big switch... */
- switch (y) {
- case FN_FS: { /* \fsize(filename) */
- CK_OFF_T z;
- p = fnval;
- z = zchki(bp[0]);
- if (z < (CK_OFF_T)0) {
- failed = 1;
- if (fndiags) {
- if (z == (CK_OFF_T)-1)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:FILE_NOT_FOUND:\\f",fn,"()>",NULL);
- else if (z == (CK_OFF_T)-2)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:FILE_NOT_READABLE:\\f",fn,"()>",NULL);
- else if (z == (CK_OFF_T)-3)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:FILE_NOT_ACCESSIBLE:\\f",fn,"()>",NULL);
- else
- ckmakmsg(fnval,FNVALL,
- "<ERROR:FILE_ERROR:\\f",fn,"()>",NULL);
- }
- goto fnend;
- }
- ckstrncpy(fnval,ckfstoa(z),FNVALL);
- goto fnend;
- }
- case FN_VER: /* \fverify() */
- p = "-1";
- if (argn == 1) /* No second arg */
- goto fnend;
- else if (!bp[1]) /* Or second arg null */
- goto fnend;
- else if (!*(bp[1])) /* or empty. */
- goto fnend;
- p = "0";
- if (argn > 1) { /* Only works if we have 2 or 3 args */
- int start;
- char *s2, ch1, ch2;
- start = 0;
- if (argn > 2) { /* Starting position specified */
- val1 = *(bp[2]) ? evalx(bp[2]) : "0";
- if (chknum(val1)) {
- start = atoi(val1) /* - 1 */;
- if (start < 0) start = 0;
- if (start > (int)strlen(bp[1]))
- goto verfin;
- } else {
- failed = 1;
- evalerr(fn);
- goto fnend;
- }
- }
- i = start;
- p = "0";
- for (s = bp[1] + start; *s; s++,i++) {
- ch1 = *s;
- if (!inpcas[cmdlvl]) if (islower(ch1)) ch1 = toupper(ch1);
- j = 0;
- for (s2 = bp[0]; *s2; s2++) {
- ch2 = *s2;
- if (!inpcas[cmdlvl]) if (islower(ch2)) ch2 = toupper(ch2);
- if (ch1 == ch2) {
- j = 1;
- break;
- }
- }
- if (j == 0) {
- sprintf(fnval,"%d",i+1); /* SAFE */
- p = fnval;
- break;
- }
- }
- }
- verfin:
- goto fnend;
- case FN_IPA: /* Find and return IP address */
- if (argn > 0) { /* in argument string. */
- int start = 0;
- if (argn > 1) { /* Starting position specified */
- if (chknum(bp[1])) {
- start = atoi(bp[1]) - 1;
- if (start < 0) start = 0;
- } else {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- }
- p = getip(bp[0]+start);
- } else p = "";
- goto fnend;
- #ifdef OS2
- case FN_CRY:
- p = "";
- if (argn > 0) {
- p = fnval;
- ckstrncpy(p,bp[0],FNVALL);
- ck_encrypt(p);
- }
- goto fnend;
- case FN_OOX:
- p = "";
- if (argn > 0)
- p = (char *) ck_oox(bp[0], (argn > 1) ? bp[1] : "");
- goto fnend;
- #endif /* OS2 */
- case FN_HEX: /* \fhexify(arg1) */
- if (argn < 1)
- goto fnend;
- if ((int)strlen(bp[0]) < (FNVALL / 2)) {
- s = bp[0];
- p = fnval;
- while (*s) {
- x = (*s >> 4) & 0x0f;
- *p++ = hexdigits[x];
- x = *s++ & 0x0f;
- *p++ = hexdigits[x];
- }
- *p = NUL;
- p = fnval;
- }
- goto fnend;
- case FN_UNTAB: /* \funtab(arg1) */
- if (argn < 1)
- goto fnend;
- if ((int)strlen(bp[0]) < (FNVALL * 2)) {
- s = bp[0];
- p = fnval;
- if (untabify(bp[0],p,FNVALL) < 0) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:OVERFLOW:\\f",fn,"()>",NULL);
- }
- goto fnend;
- }
- case FN_UNH: { /* \funhex(arg1) */
- int c[2], i;
- if (argn < 1)
- goto fnend;
- if ((int)strlen(bp[0]) < (FNVALL * 2)) {
- s = bp[0];
- p = fnval;
- while (*s) {
- for (i = 0; i < 2; i++) {
- c[i] = *s++;
- if (!c[i]) { p = ""; goto unhexfin; }
- if (islower(c[i])) c[i] = toupper(c[i]);
- if (c[i] >= '0' && c[i] <= '9') {
- c[i] -= 0x30;
- } else if (c[i] >= 'A' && c[i] <= 'F') {
- c[i] -= 0x37;
- } else {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,
- FNVALL,
- "<ERROR:ARG_OUT_OF_RANGE:\\f",
- fn,
- "()>",
- NULL
- );
- goto fnend;
- }
- }
- *p++ = ((c[0] << 4) & 0xf0) | (c[1] & 0x0f);
- }
- *p = NUL;
- p = fnval;
- }
- unhexfin:
- goto fnend;
- }
- case FN_BRK: { /* \fbreak() */
- char * c; /* Characters to break on */
- char c2, s2;
- int start = 0;
- int done = 0;
- if (argn < 1)
- goto fnend;
- if (argn > 2) {
- s = bp[2] ? bp[2] : "0";
- if (chknum(s)) {
- start = atoi(s);
- if (start < 0) start = 0;
- if (start > (int)strlen(bp[0]))
- goto brkfin;
- } else {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- }
- s = bp[0] + start; /* Source pointer */
- while (*s && !done) {
- s2 = *s;
- if (!inpcas[cmdlvl] && islower(s2)) s2 = toupper(s2);
- c = bp[1] ? bp[1] : ""; /* Character to break on */
- while (*c) {
- c2 = *c;
- if (!inpcas[cmdlvl] && islower(c2)) c2 = toupper(c2);
- if (c2 == s2) {
- done = 1;
- break;
- }
- c++;
- }
- if (done) break;
- *p++ = *s++;
- }
- *p = NUL; /* terminate the result */
- p = fnval; /* and point to it. */
- brkfin:
- goto fnend;
- }
- case FN_SPN: { /* \fspan() */
- char *q;
- char c1, c2;
- int start = 0;
- if (argn < 1)
- goto fnend;
- if (argn > 2) { /* Starting position */
- s = bp[2] ? bp[2] : "0";
- if (chknum(s)) {
- start = atoi(s);
- if (start < 0) start = 0;
- } else {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- }
- s = bp[0] + start; /* Source pointer */
- if (argn > 1 &&
- (int)strlen(bp[1]) > 0 &&
- start <= (int)strlen(bp[0])) {
- while (*s) { /* Loop thru source string */
- q = bp[1]; /* Span string */
- c1 = *s;
- if (!inpcas[cmdlvl])
- if (islower(c1)) c1 = toupper(c1);
- x = 0;
- while ((c2 = *q++)) {
- if (!inpcas[cmdlvl])
- if (islower(c2)) c2 = toupper(c2);
- if (c1 == c2) { x = 1; break; }
- }
- if (!x) break;
- *p++ = *s++;
- }
- *p = NUL; /* Terminate and return the result */
- p = fnval;
- }
- goto fnend;
- }
- } /* Break up big switch... */
- switch (y) {
- case FN_TRM: /* \ftrim(s1[,s2]) */
- case FN_LTR: /* \fltrim(s1[,s2]) */
- if (argn < 1)
- goto fnend;
- if ((len1 = (int)strlen(bp[0])) > 0) {
- if (len1 > FNVALL)
- len1 = FNVALL;
- s = " \t\r\n";
- if (argn > 1) /* Trim list given */
- s = bp[1];
- len2 = (int)strlen(s);
- if (len2 < 1) { /* or not... */
- s = " \t\r\n"; /* Default is to trim whitespace */
- len2 = 2;
- }
- if (cx == FN_TRM) { /* Trim from right */
- char * q, p2, q2;
- ckstrncpy(fnval,bp[0],FNVALL); /* Copy string to output */
- p = fnval + len1 - 1; /* Point to last character */
- while (p >= (char *)fnval) { /* Go backwards */
- q = s; /* Point to trim list */
- p2 = *p;
- if (!inpcas[cmdlvl])
- if (islower(p2)) p2 = toupper(p2);
- while (*q) { /* Is this char in trim list? */
- q2 = *q;
- if (!inpcas[cmdlvl])
- if (islower(q2)) q2 = toupper(q2);
- if (p2 == q2) { /* Yes, null it out */
- *p = NUL;
- break;
- }
- q++;
- }
- if (!*q) /* Trim list exhausted */
- break; /* So we're done. */
- p--; /* Else keep trimming */
- }
- } else { /* Trim from left */
- char * q, p2, q2;
- p = bp[0]; /* Source */
- while (*p) {
- p2 = *p;
- if (!inpcas[cmdlvl])
- if (islower(p2)) p2 = toupper(p2);
- q = s;
- while (*q) { /* Is this char in trim list? */
- q2 = *q;
- if (!inpcas[cmdlvl])
- if (islower(q2)) q2 = toupper(q2);
- if (p2 == q2) { /* Yes, point past it */
- p++; /* and try next source character */
- break;
- }
- q++; /* No, try next trim character */
- }
- if (!*q) /* Trim list exhausted */
- break; /* So we're done. */
- }
- ckstrncpy(fnval,p,FNVALL);
- }
- p = fnval;
- } else p = "";
- goto fnend;
- case FN_CAP: /* \fcapitalize(arg1) */
- if (argn < 1)
- goto fnend;
- s = bp[0];
- p = fnval;
- x = 0;
- while ((c = *s++)) {
- if (isalpha(c)) {
- if (x == 0) {
- x = 1;
- if (islower(c))
- c = toupper(c);
- } else if (isupper(c))
- c = tolower(c);
- }
- *p++ = c;
- }
- *p = NUL;
- p = fnval;
- goto fnend;
- #ifdef COMMENT
- case FN_TOD: /* Time of day to secs since midnite */
- sprintf(fnval,"%ld",tod2sec(bp[0])); /* SAFE */
- goto fnend;
- #endif /* COMMENT */
- case FN_FFN: /* Full pathname of file */
- zfnqfp(bp[0],FNVALL,p);
- if (!p) p = "";
- goto fnend;
- case FN_CHK: { /* \fchecksum() */
- long chk = 0;
- p = (argn > 0) ? bp[0] : "";
- while (*p) chk += *p++;
- sprintf(fnval,"%lu",chk); /* SAFE */
- p = fnval;
- goto fnend;
- }
- #ifndef NOXFER
- case FN_CRC: /* \fcrc16() */
- if (argn > 0)
- sprintf(fnval,"%u", /* SAFE */
- chk3((CHAR *)bp[0],(int)strlen(bp[0])));
- else
- p = "0";
- goto fnend;
- #endif /* NOXFER */
- case FN_BSN: /* \fbasename() */
- zstrip(bp[0],&p);
- goto fnend;
- #ifndef NOLOCAL
- #ifdef OS2
- case FN_SCRN_CX: /* \fscrncurx() */
- p = fnval;
- sprintf(p,"%d",(int)VscrnGetCurPos(VTERM)->x); /* SAFE */
- goto fnend;
- case FN_SCRN_CY: /* \fscrncury() */
- p = fnval;
- sprintf(p,"%d",(int)VscrnGetCurPos(VTERM)->y); /* SAFE */
- goto fnend;
- case FN_SCRN_STR: { /* \fscrnstr() */
- videoline * line = NULL;
- viocell * cells = NULL;
- int row = 0, col = 0, len = 0;
- /* NOTE: On Unicode systems, the screen contents are stored in */
- /* in Unicode. Therefore, we should really be performing a */
- /* conversion to the local character set. */
- /* 6/18/2000 - added the translation to lcs */
- if (bp[0] == NULL || bp[0][0] == '\0') {
- row = 0;
- } else {
- if (chknum(bp[0])) {
- row = atoi(bp[0]);
- if (row < 0)
- row = 0;
- } else {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- }
- line = VscrnGetLineFromTop( VTERM, (USHORT) row );
- if (line != NULL) {
- if (bp[1] == NULL || bp[1][0] == '\0')
- col = 0;
- else {
- if (chknum(bp[0])) {
- col = atoi(bp[1]);
- if (col < 0 || col >= line->width)
- col = 0;
- } else {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- }
- if (bp[2] == NULL || bp[2][0] == '\0') {
- len = line->width - (col+1);
- } else {
- if (!chknum(bp[2])) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- len = atoi(bp[2]);
- if (len < 0 || len > line->width)
- len = line->width;
- }
- cells = line->cells;
- for (i = 0; i < len; i++) {
- int pos = i + col;
- if (pos < line->width) {
- if (isunicode())
- fnval[i] = (CHAR) utolxlat(cells[pos].c);
- else
- fnval[i] = (CHAR) (cells[pos].c & 0xFF);
- if (fnval[i] == 0)
- fnval[i] = SP;
- } else
- fnval[i] = SP;
- }
- fnval[i] = '\0';
- } else {
- fnval[0] = '\0';
- }
- p = fnval;
- goto fnend;
- }
- #endif /* OS2 */
- #endif /* NOLOCAL */
- #ifndef NOPUSH
- case FN_RAW: /* \frawcommand() */
- case FN_CMD: { /* \fcommand() */
- int x, c, n = FNVALL;
- x = 0; /* Completion flag */
- /*
- ZIFILE can be safely used because we can't possibly be transferring a file
- while executing this function.
- */
- if (!nopush && zxcmd(ZIFILE,bp[0]) > 0) { /* Open the command */
- while (n-- > -1) { /* Read from it */
- if ((c = zminchar()) < 0) {
- x = 1; /* EOF - set completion flag */
- if (cx == FN_CMD) { /* If not "rawcommand" */
- p--; /* remove trailing newlines */
- while (*p == CR || *p == LF)
- p--;
- p++;
- }
- *p = NUL; /* Terminate the string */
- break;
- } else /* Command still running */
- *p++ = c; /* Copy the bytes */
- }
- zclose(ZIFILE); /* Close the command */
- }
- /* Return null string if command's output was too long. */
- p = fnval;
- if (!x) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:RESULT_TOO_LONG:\\f",fn,"()>",NULL);
- }
- goto fnend;
- }
- #endif /* NOPUSH */
- } /* Break up big switch... */
- switch (y) {
- case FN_STX: /* \fstripx(string,c) */
- if (!(s = bp[0])) /* Make sure there is a string */
- goto fnend;
- c = '.'; /* Character to strip from */
- if (argn > 1) if (*bp[1]) c = *bp[1];
- n = ckstrncpy(fnval,bp[0],FNVALL);
- while (--n >= 0) {
- if (fnval[n] == c) {
- fnval[n] = NUL;
- break;
- }
- }
- p = fnval;
- goto fnend;
- case FN_STL: /* \flop(string,c) */
- case FN_LOPX: { /* \flopx(string,c) */
- int n = 1;
- if (!(s = bp[0])) /* Make sure there is a string */
- goto fnend;
- c = '.'; /* Character to strip to */
- if (argn > 1) if (*bp[1]) c = *bp[1];
- if (argn > 2) if (*bp[2]) {
- #ifndef NOFLOAT
- n = 0;
- if (isfloat(bp[2],0)) {
- n = (int)floatval;
- if (n < 0) n = 0;
- } else
- #endif /* NOFLOAT */
- n = atoi(bp[2]);
- }
- x = 0;
- if (cx == FN_LOPX) { /* Lopx (from right) */
- if (n == 0)
- goto fnend;
- s += strlen(s) - 1; /* We already know it's > 0 */
- while (s-- >= bp[0]) {
- if (*s == c) {
- n--;
- if (n == 0) {
- s++;
- x = 1;
- break;
- }
- }
- }
- if (!x) s = "";
- } else { /* Lop (from left) */
- if (n == 0) {
- p = bp[0];
- goto fnend;
- }
- while (*s++) {
- if (*(s-1) == c) {
- if (--n == 0) {
- x = 1;
- break;
- }
- }
- }
- if (!x) s = bp[0];
- }
- ckstrncpy(fnval,s,FNVALL);
- p = fnval;
- goto fnend;
- }
- case FN_STN: /* \fstripn(string,n) */
- if (argn < 1) /* Remove n chars from right */
- goto fnend;
- val1 = "0";
- if (argn > 1)
- if (*(bp[1]))
- val1 = evalx(bp[1]);
- if (!chknum(val1)) {
- failed = 1;
- evalerr(fn);
- goto fnend;
- }
- n = atoi(val1);
- if (n < 0) n = 0;
- k = (int)strlen(s = bp[0]) - n;
- if (k < 0) k = 0;
- p = fnval;
- while (k-- > 0)
- *p++ = *s++;
- *p = NUL;
- p = fnval;
- goto fnend;
- case FN_STB: { /* \fstripb(string,c) */
- char c2 = NUL;
- int i, k = 0;
- char * gr_opn = "\"{'([<"; /* Group open brackets */
- char * gr_cls = "\"}')]>"; /* Group close brackets */
- p = fnval;
- *p = NUL;
- if (!(s = bp[0])) /* Make sure there is a string */
- goto fnend;
- if ((x = strlen(s)) < 1)
- goto fnend;
- c = NUL; /* Brace/bracket kind */
- if (argn > 1) {
- if (*bp[1]) {
- if (chknum(bp[1])) {
- k = atoi(bp[1]);
- if (k < 0) k = 63;
- for (i = 0; i < 6; i++) {
- if (k & (1<<i)) {
- if (s[0] == gr_opn[i] && s[x-1] == gr_cls[i]) {
- ckstrncpy(fnval,s+1,FNVALL);
- fnval[x-2] = NUL;
- goto fnend;
- }
- }
- }
- ckstrncpy(fnval,s,FNVALL); /* No match */
- goto fnend;
- }
- }
- }
- c = !bp[1] ? 0 : *bp[1];
- if (!c) c = s[0];
- if (argn > 2) if (*bp[2]) c2 = *bp[2];
- if (*s == c) {
- if (!c2) {
- switch (c) {
- case '(': c2 = ')'; break;
- case '[': c2 = ']'; break;
- case '{': c2 = '}'; break;
- case '<': c2 = '>'; break;
- case '"': c2 = '"'; break;
- case 39: c2 = 39; break;
- case 96: c2 = 39; break;
- default:
- if (argn == 2) {
- c2 = c;
- } else {
- strncpy(fnval,s,x); /* Leave it like this */
- fnval[x] = NUL;
- goto fnend;
- }
- }
- }
- if (s[x-1] == c2) {
- strncpy(fnval,s+1,x-2); /* Leave it like this */
- fnval[x-2] = NUL;
- goto fnend;
- }
- }
- strncpy(fnval,s,x);
- fnval[x] = NUL;
- goto fnend;
- }
- case FN_2HEX: /* Number to hex */
- case FN_2OCT: /* Number to octal */
- val1 = evalx(bp[0]);
- if (!*val1) {
- failed = 1;
- evalerr(fn);
- goto fnend;
- }
- sprintf(fnval, cx == FN_2HEX ? "%lx" : "%lo", atol(val1)); /* SAFE */
- if (cx == FN_2HEX && (int)(strlen(fnval)&1))
- sprintf(fnval,"0%lx",atol(val1)); /* SAFE */
- p = fnval;
- goto fnend;
- case FN_DNAM: { /* Directory part of file name */
- char *s;
- zfnqfp(bp[0],FNVALL,p); /* Get full name */
- if (!isdir(p)) { /* Is it already a directory? */
- zstrip(p,&s); /* No get basename */
- if (*s) {
- x = ckindex(s,p,0,0,0); /* Pos of latter in former */
- if (x > 0) p[x-1] = NUL;
- }
- }
- if (!p) p = "";
- goto fnend;
- }
- #ifndef NORANDOM
- case FN_RAND: /* Random number */
- #ifdef CK_SSL
- if (RAND_bytes((unsigned char *)&k,sizeof(k)) < 0)
- #endif /* CK_SSL */
- k = rand();
- x = 0;
- if (argn > 0) {
- if (!chknum(bp[0])) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- x = atoi(bp[0]);
- }
- #ifdef COMMENT
- sprintf(fnval,"%d", (x > 0 && k > 0) || (x < 0 && k < 0) ? k % x :
- (x == 0 ? 0 : (0 - (k % (-x)))));
- #else
- debug(F111,"rand",ckitoa(x),k);
- #ifdef SUNOS4
- /* This is really strange but on SunOS, if we are requesting random numbers */
- /* between 0 and 4 or less, they always come out in sequence: 0 1 2 3 0 1 2 */
- /* Shifting the result of rand() in this case gives a more random result. */
- if (x < 5)
- k = k >> 5;
- #endif /* SUNOS4 */
- if ((x > 0 && k > 0) || (x < 0 && k < 0))
- x = k % x;
- else if (x == 0)
- x = 0;
- else
- x = 0 - (k % (-x));
- debug(F101,"rand x","",x);
- sprintf(fnval,"%d", x); /* SAFE */
- #endif /* COMMENT */
- p = fnval;
- goto fnend;
- #endif /* NORANDOM */
- } /* Break up big switch... */
- switch (y) {
- case FN_SPLIT: /* \fsplit(s1,a,s2,s3,mask) */
- case FN_WORD: { /* \fword(s1,n,s2,s3,mask) */
- int wordnum = 0;
- int splitting = 0;
- int x;
- int array = 0;
- int grouping = 0;
- int nocollapse = 0;
- char * sep = "";
- char * notsep = "";
- char * bp0 = NULL;
- char * bp1 = NULL;
- char abuf[16];
- struct stringarray * q = NULL;
- splitting = (cx == FN_SPLIT); /* Our job */
- debug(F101,"FN_SPLIT splitting","",splitting);
- fnval[0] = splitting ? '0' : NUL; /* Initial return value */
- fnval[1] = NUL;
- p = fnval;
- bp0 = bp[0]; /* Source string */
- if (!bp0) bp0 = "";
- debug(F111,"fsplit bp[0]",bp0,argn);
- if (argn < 1 || !*bp0) /* If none, return default value */
- goto fnend;
- bp1 = bp[1]; /* Function-dependent arg */
- if (!bp1) bp1 = ""; /* (array or number) */
- debug(F110,"fsplit bp[1]",bp1,0);
- if (bp[5]) {
- if (!chknum(bp[5])) {
- failed = 1;
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- x = atoi(bp[5]);
- nocollapse = x;
- }
- if (!splitting) { /* \fword(): n = desired word number */
- val1 = "1"; /* Default is first word */
- if (argn > 1) /* Word number supplied */
- if (*bp1)
- val1 = evalx(bp1);
- if (!chknum(val1)) {
- failed = 1;
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- n = atoi(val1);
- } else if (argn > 1 && *bp1) { /* \fsplit(): n = word count */
- ckstrncpy(abuf,bp1,16); /* Get array reference */
- debug(F110,"fsplit abuf 1",abuf,0);
- failed = 1; /* Assume it's bad */
- if (fndiags) /* Default is this error message */
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
- if (abuf[0] != '&') /* "Address" of array */
- goto fnend; /* It's bad */
- if (abuf[2]) { /* Check for brackets */
- if (abuf[2] != '[' || abuf[3] != ']') {
- goto fnend; /* Bad */
- }
- }
- debug(F110,"fsplit abuf 2",abuf,0);
- if (abuf[1] > 64 && abuf[1] < 91) /* Convert upper to lower */
- abuf[1] += 32;
- if (abuf[1] < 97 || abuf[1] > 122) { /* Check for a-z */
- goto fnend;
- }
- debug(F110,"fsplit abuf 3",abuf,0);
- array = 1;
- fnval[0] = NUL; /* No error, erase message */
- failed = 0; /* Unset failure flag */
- n = 0; /* Initialize word counter */
- }
- if (argn > 2) /* Have break set? */
- sep = bp[2];
- debug(F111,"fsplit sep",sep,argn);
- if (argn > 3) /* Have include set? */
- notsep = bp[3];
- debug(F111,"fsplit notsep",notsep,argn);
- if (argn > 4) { /* Have grouping set? */
- char * bp4 = bp[4];
- debug(F111,"fsplit bp4",bp4,argn);
- if (!bp4) bp4 = "0";
- if (!*bp4) bp4 = "0";
- if (chknum(bp4)) {
- grouping = atoi(bp4);
- if (grouping == -1)
- grouping = 127;
- } else {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- }
- /* Args parsed, now do the work */
- debug(F111,"fsplit bp0",bp0,n);
- q = cksplit(splitting,n,bp0,sep,notsep,grouping,0,nocollapse,0);
- wordnum = q ? q->a_size : -1; /* Check result */
- if (wordnum < 0) {
- failed = 1; /* Failure */
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- (wordnum == -1) ?
- "<ERROR:MALLOC_FAILURE:\\f" :
- "<ERROR:TOO_MANY_WORDS:\\f",
- fn,
- "()>",
- NULL
- );
- goto fnend;
- }
- if (splitting) { /* \fsplit() result */
- ckstrncpy(fnval,ckitoa(wordnum),FNVALL);
- if (array) { /* Array was not declared. */
- int i;
- if ((x = dclarray(abuf[1],wordnum)) < 0) { /* Declare it. */
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:MALLOC_FAILURE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- for (i = 1; i <= wordnum; i++) { /* Copy results */
- makestr(&(a_ptr[x][i]),q->a_head[i]);
- }
- a_ptr[x][0] = NULL; /* Array is 1-based */
- makestr(&(a_ptr[x][0]),fnval); /* Element = size */
- }
- } else { /* \fword() result */
- char * s;
- s = q->a_head[1];
- if (!s) s = "";
- ckstrncpy(fnval,s,FNVALL);
- }
- goto fnend; /* Done */
- }
- } /* Break up big switch... */
- switch (y) {
- #ifdef CK_KERBEROS
- case FN_KRB_TK: /* Kerberos tickets */
- case FN_KRB_NX: /* Kerberos next ticket */
- case FN_KRB_IV: /* Kerberos ticket is valid */
- case FN_KRB_FG: /* Kerberos Ticket flags */
- case FN_KRB_TT: { /* Kerberos ticket time */
- int kv = 0; /* Kerberos version */
- int n = 0;
- char * s = NULL;
- if (rdigits(bp[0])) {
- kv = atoi(bp[0]);
- } else {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- if (kv != 4 && kv != 5) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- if ((cx == FN_KRB_IV || cx == FN_KRB_TT || cx == FN_KRB_FG) &&
- argn < 2) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
- goto fnend;
- }
- switch (y) {
- case FN_KRB_TK: /* Number of Kerberos tickets */
- #ifdef CK_AUTHENTICATION
- switch (kv) {
- case 4:
- n = ck_krb4_get_tkts();
- sprintf(fnval, "%d", (n >= 0) ? n : 0); /* SAFE */
- goto fnend;
- case 5: {
- extern char * krb5_d_cc;
- n = ck_krb5_get_tkts(krb5_d_cc);
- sprintf(fnval, "%d", (n >= 0) ? n : 0); /* SAFE */
- goto fnend;
- }
- }
- #else
- sprintf(fnval,"%d",0); /* SAFE */
- #endif /* CK_AUTHENTICATION */
- goto fnend;
- case FN_KRB_NX: /* Kerberos next ticket */
- #ifdef CK_AUTHENTICATION
- switch (kv) {
- case 4:
- s = ck_krb4_get_next_tkt();
- ckstrncpy(fnval, s ? s : "",FNVALL);
- goto fnend;
- case 5:
- s = ck_krb5_get_next_tkt();
- ckstrncpy(fnval, s ? s : "",FNVALL);
- goto fnend;
- }
- #else
- sprintf(fnval,"k%d next-ticket-string",kv); /* SAFE */
- #endif /* CK_AUTHENTICATION */
- goto fnend;
- case FN_KRB_IV: /* Kerberos ticket is valid */
- #ifdef CK_AUTHENTICATION
- /* Return 1 if valid, 0 if not */
- switch (kv) {
- case 4:
- n = ck_krb4_tkt_isvalid(bp[1]);
- sprintf(fnval, "%d", n > 0 ? 1 : 0); /* SAVE */
- goto fnend;
- case 5: {
- extern char * krb5_d_cc;
- n = ck_krb5_tkt_isvalid(krb5_d_cc,bp[1]);
- sprintf(fnval,"%d", n > 0 ? 1 : 0); /* SAFE */
- goto fnend;
- }
- }
- #else
- sprintf(fnval,"%d",0); /* SAFE */
- #endif /* CK_AUTHENTICATION */
- goto fnend;
- case FN_KRB_TT: /* Kerberos ticket time */
- #ifdef CK_AUTHENTICATION
- switch (kv) {
- case 4:
- n = ck_krb4_tkt_time(bp[1]);
- sprintf(fnval,"%d", n >= 0 ? n : 0); /* SAFE */
- goto fnend;
- case 5: {
- extern char * krb5_d_cc;
- n = ck_krb5_tkt_time(krb5_d_cc,bp[1]);
- sprintf(fnval,"%d", n >= 0 ? n : 0); /* SAFE */
- goto fnend;
- }
- }
- #else
- ckstrncpy(fnval,"600",FNVALL); /* Some time */
- #endif /* CK_AUTHENTICATION */
- goto fnend;
- case FN_KRB_FG: /* Kerberos ticket flags */
- #ifdef CK_AUTHENTICATION
- switch (kv) {
- case 4:
- fnval[0] = '\0';
- goto fnend;
- case 5: {
- extern char * krb5_d_cc;
- ckstrncpy(fnval,ck_krb5_tkt_flags(krb5_d_cc,bp[1]),FNVALL);
- goto fnend;
- }
- }
- #else
- fnval[0] = '\0';
- #endif /* CK_AUTHENTICATION */
- goto fnend;
- }
- p = fnval;
- goto fnend;
- }
- #endif /* CK_KERBEROS */
- #ifdef FN_ERRMSG
- case FN_ERRMSG:
- if (rdigits(bp[0])) {
- k = atoi(bp[0]);
- } else {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- #ifdef VMS
- ckstrncpy(fnval,ckvmserrstr(k),FNVALL);
- #else
- x = errno;
- errno = k;
- ckstrncpy(fnval,ck_errstr(),FNVALL);
- errno = x;
- #endif /* VMS */
- p = fnval;
- goto fnend;
- #endif /* FN_ERRMSG */
- case FN_DIM: {
- int max;
- char abuf[16], *s;
- fnval[0] = NUL; /* Initial return value */
- ckstrncpy(abuf,bp[0],16); /* Get array reference */
- s = abuf;
- if (*s == CMDQ) s++;
- failed = 1; /* Assume it's bad */
- p = fnval; /* Point to result */
- if (fndiags) /* Default is this error message */
- ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
- if (s[0] != '&') { /* "Address" of array */
- goto fnend;
- }
- if (s[2]) {
- if (s[2] != '[' || s[3] != ']') {
- goto fnend;
- }
- }
- if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
- s[1] += 32;
- if (s[1] < 95 || s[1] > 122) { /* Check for a-z */
- goto fnend; /* Bad */
- }
- if ((max = chkarray(s[1],1)) < 1) /* (second arg was 1) */
- max = 0;
- failed = 0; /* Unset failure flag */
- sprintf(fnval,"%d",max); /* SAFE */
- goto fnend;
- }
- case FN_FILEINF: { /* File information */
- #ifdef UNIX
- /* from zgetfs in ckufio.c */
- extern int zgfs_dir, zgfs_link;
- extern char linkname[];
- char * tx; /* For tilde expansion */
- #else
- int zgfs_dir = 0, zgfs_link = 0;
- #endif /* UNIX */
- char abuf[16], *s;
- char ** ap = NULL;
- char workbuf[MAXPATHLEN];
- int attrs = 9; /* Number of attributes defined */
- int k = 0; /* current attribute index */
- int i,j,n;
- int m; /* For scanfile() */
- int dir = -1; /* 1 = arg is a directory file */
- CK_OFF_T z, z2; /* For file size */
- workbuf[0] = NUL;
- workbuf[1] = NUL;
- if (argn < 2) { /* An array designator is required */
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:ARRAY_REQUIRED:\\f",fn,"()>",NULL);
- goto fnend;
- }
- #ifdef UNIX
- if (*(bp[0]) == '~') { /* Expand any tildes in filenames. */
- tx = tilde_expand(bp[0]); /* We recycle bp[0] */
- if (tx) if (*tx) { /* this way so they will be freed */
- free(bp[0]); /* automatically later. */
- bp[0] = NULL;
- makestr(&(bp[0]),tx);
- }
- }
- #endif /* UNIX */
- j = ckstrncpy(workbuf,bp[0],MAXPATHLEN); /* Strip any trailing '/' */
- if (workbuf[j-1] == '/') {
- workbuf[j-1] = NUL;
- makestr(&(bp[0]),workbuf);
- }
- z = zchki(bp[0]); /* Check accessibility */
- if (z == -1L || z == -3L) { /* Access denied or whatever */
- p = "0";
- goto fnend;
- /* Note: z > 0 is the file size but only of regular files */
- /* Thus the zgetfs call just below */
- }
- #ifdef UNIX
- if ((z2 = zgetfs(bp[0])) > 0) { /* Get size and some attributes */
- z = z2; /* Have size */
- dir = zgfs_dir; /* File is/isn't a directory */
- }
- #endif /* UNIX */
- if (dir < 0) /* Check if file is a a directory */
- dir = isdir(bp[0]); /* if previous clause didn't already */
- fnval[0] = NUL; /* Initial return value */
- ckstrncpy(abuf,bp[1],16); /* Get array reference */
- s = abuf;
- if (*s == CMDQ) s++;
- failed = 1; /* Assume it's bad */
- p = fnval; /* Point to result */
- if (fndiags) /* Default is this error message */
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
- if (s[0] != '&') /* "Address" of array */
- goto fnend;
- if (s[2])
- if (s[2] != '[' || s[3] != ']')
- goto fnend;
- if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
- s[1] += 32;
- if ((x = dclarray(s[1],attrs)) < 0) /* One element per attribute */
- goto fnend;
- failed = 0; /* Unset failure flag */
- ap = a_ptr[x]; /* Point to array we just declared */
- sprintf(fnval,"%d",k); /* SAFE */
- /* Element 1 = filename */
- s = bp[0]; /* Argument (might include path) */
- n = strlen(s);
- for (i = n; i > 0; i--) { /* Get filename without path */
- if (ISDIRSEP(s[i-1])) { /* Platform independent way */
- s += i;
- break;
- }
- }
- a_ptr[x][1] = NULL; /* Filename */
- makestr(&(a_ptr[x][1]),s);
- /* Element 2 - Full pathname */
- s = workbuf;
- zfnqfp(bp[0],FNVALL,s);
- n = strlen(s);
- for (i = n; i > 0; i--) { /* Get filename without path */
- if (ISDIRSEP(s[i-1])) { /* Platform independent way */
- s[i] = NUL;
- break;
- }
- }
- a_ptr[x][2] = NULL;
- makestr(&(a_ptr[x][2]),s);
- /* Element 3 - Modification date-time */
- s = zfcdat(bp[0]);
- a_ptr[x][3] = NULL;
- makestr(&(a_ptr[x][3]),s);
- /* Element 4 - Permissions string */
- #ifdef UNIX
- if (zgfs_link)
- s = "lrwxrwxrwx";
- else
- #endif /* UNIX */
- /* [jt] 2013/11/21:
- * K-95 doesn't have ziperm. However, I have not read through this
- * code thoroughly, and this needs double checked to see if there are
- * any side effects of commenting this out.
- */
- #ifdef CK_PERMS
- s = ziperm(bp[0]);
- a_ptr[x][4] = NULL;
- makestr(&(a_ptr[x][4]),s);
- ckstrncpy(workbuf,s,32); /* Save for later */
- #endif /* CK_PERMS */
- /* Element 5 - Permissions numeric code */
- s = zgperm(bp[0]);
- a_ptr[x][5] = NULL;
- makestr(&(a_ptr[x][5]),s);
- /* Element 6 - Size in bytes */
-
- #ifdef OS2 /* [jt] 2013/11/21 - K-95 doesn't have linkname */
- s = ckfstoa(z);
- #else
- s = zgfs_link ? ckitoa((int)strlen((char *)linkname)) : ckfstoa(z);
- #endif /* OS2 */
- a_ptr[x][6] = NULL;
- makestr(&(a_ptr[x][6]),s);
-
- /* Element 7 - File type */
- j = 0;
- if (dir) j = 3;
- #ifdef UNIX
- else if (zgfs_link) j = 4;
- else if (ckindex("x",(char *)workbuf,0,0,1)) j = 2;
- else if (workbuf[1] != '-') j = 1;
- #else
- #ifdef VMS
- else if (ckindex("E",(char *)workbuf,0,0,1)) j = 2;
- else j = 1;
- #endif /* VMS */
- #endif /* UNIX */
- a_ptr[x][7] = NULL;
- switch (j) {
- case 0: s = "unknown"; break;
- case 1: s = "regular"; break;
- case 2: s = "executable"; break;
- case 3: s = "directory"; break;
- case 4: s = "link"; break;
- default: s = "unknown";
- }
- makestr(&(a_ptr[x][7]),s);
- k = 7;
- /* Element 8 - Name of linked-to file (if link) */
- a_ptr[x][8] = NULL;
- #ifdef UNIX
- if (zgfs_link) {
- makestr(&(a_ptr[x][8]),(char *)linkname);
- k++;
- }
- #endif /* UNIX */
- /* Element 9 - File scan result */
- if (j == 1 || j == 2) { /* Regular file */
- m = scanfile(bp[0],NULL,nscanfile);
- if (m > -1) {
- if (k < 8) k = 8; /* Insert empty element for link */
- makestr(&(a_ptr[x][8]),"");
- k++;
- switch (m) {
- case FT_7BIT: s = "text:7bit"; break;
- case FT_UTF8: s = "text:utf8"; break;
- case FT_UCS2: s = "text:ucs2"; break;
- case FT_8BIT: s = "text:8bit"; break;
- case FT_TEXT: s = "text:unknown"; break;
- case FT_BIN: s = "binary"; break;
- default: s = "unknown";
- }
- a_ptr[x][9] = NULL;
- makestr(&(a_ptr[x][9]),s);
- }
- }
- /* If adding another change attrs declaration to match */
- /* Element 0 = array size */
- p = ckitoa(k); /* Number of elements */
- a_ptr[x][0] = NULL; /* Put number of elements in [0] */
- makestr(&(a_ptr[x][0]),p);
- debug(F101,"FILEINF","",attrs);
- goto fnend;
- }
- case FN_FILECMP: { /* File comparison */
- FILE *fp1 = NULL;
- FILE *fp2 = NULL;
- char * s, * s1 = NULL, * s2 = NULL;
- #ifdef UNIX
- char * tx; /* For tilde expansion */
- #endif /* UNIX */
- int c1, c2;
- int eof1 = 0, eof2 = 0;
- failed = 1; /* Assume files differ */
- p[0] = '1'; /* Default return value = differ */
- p[1] = NUL;
- if (argn != 2) { /* Need two args */
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:ARG_COUNT:\\f",fn,"()>",NULL);
- goto fnend;
- }
- s1 = bp[0];
- s2 = bp[1];
- #ifdef UNIX
- if (*s1 == '~') { /* Expand any tildes in filenames. */
- tx = tilde_expand(bp[0]); /* We recycle bp[0] and bp[1] */
- if (tx) if (*tx) { /* this way so they will be freed */
- free(bp[0]); /* automatically later. */
- bp[0] = NULL;
- makestr(&(bp[0]),tx);
- }
- s1 = bp[0];
- }
- if (*s2 == '~') {
- tx = tilde_expand(bp[1]);
- if (tx) if (*tx) {
- free(bp[1]);
- bp[1] = NULL;
- makestr(&(bp[1]),tx);
- }
- s2 = bp[1];
- }
- #endif /* UNIX */
- fp1 = fopen(s1, "r"); /* Open it first file*/
- fp2 = fopen(s2, "r"); /* Open it first file*/
- failed = 0; /* No failure from here down */
- if (fp1 == NULL || fp2 == NULL) { /* Open failure */
- p[0] = '-';
- p[1] = '1';
- p[2] = NUL; /* Return -1 */
- if (fp1) fclose(fp1);
- if (fp1) fclose(fp2);
- goto fnend;
- }
- while (1) {
- if (!eof1) {
- c1 = getc(fp1);
- if (c1 == (unsigned int)EOF) {
- eof1++;
- fclose(fp1);
- }
- }
- if (!eof2) {
- c2 = getc(fp2);
- if (c2 == (unsigned int)EOF) {
- eof2++;
- fclose(fp2);
- }
- }
- if (eof1 && eof2) {
- p[0] = '0'; /* Success */
- p[1] = NUL;
- failed = 0;
- goto fnend;
- }
- if (eof1 || eof2 || (c1 != c2)) {
- if (!eof1) fclose(fp1);
- if (!eof2) fclose(fp2);
- goto fnend;
- }
- }
- }
- } /* Break up big switch... */
- switch (y) {
- case FN_JDATE:
- if (argn < 1) /* Check number of args */
- p = ckdate(); /* None, get today's date-time */
- else /* Some */
- p = bp[0]; /* Use first */
- p = ckcvtdate(p,0); /* Convert to standard form */
- ckstrncpy(fnval,zjdate(p),FNVALL); /* Convert to Julian */
- p = fnval; /* Point to result */
- failed = 0;
- if (*p == '-') {
- failed = 1;
- if (fndiags) /* Default is this error message */
- ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_DATE:\\f",fn,"()>",NULL);
- }
- goto fnend;
- case FN_DATEJ:
- ckstrncpy(fnval,jzdate(bp[0]),FNVALL); /* Convert to yyyy<dayofyear> */
- p = fnval; /* Point to result */
- failed = 0;
- if (*p == '-') {
- failed = 1;
- if (fndiags) /* Default is this error message */
- ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_DATE:\\f",fn,"()>",NULL);
- }
- goto fnend;
- case FN_DTIM: /* \fcvtdate() */
- case FN_TIME: /* Free-format time to hh:mm:ss */
- case FN_NTIM: /* Time to sec since midnight */
- s = (argn > 0) ? bp[0] : "";
- if (!s) s = "";
- if (!*s)
- p = ckdate(); /* None, get today's date */
- else /* Some */
- p = bp[0]; /* Use first */
- {
- char * s;
- s = p;
- while (*s) { /* Strip leading spaces/ctrls */
- if (*s < 32) {
- *s = NUL;
- break;
- }
- s++;
- }
- /* do { if (*s < '!') *s = NUL; break; } while (*s++); */
- }
- p = ckcvtdate(p,2); /* Convert to standard form */
- if (*p == '<') {
- failed = 1;
- if (fndiags) /* Default is this error message */
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_BAD_DATE_OR_TIME:\\f",fn,"()>",NULL);
- p = fnval;
- goto fnend;
- }
- if (argn > 1) { /* Format code */
- s = evalx(bp[1]);
- if (!s) s = "";
- if (!*s) s = "0";
- if (!chknum(s)) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- p = fnval;
- goto fnend;
- }
- x = atoi(s);
- /* if (x) */ p = shuffledate(p,x);
- }
- if (cx == FN_TIME) {
- p += 9;
- } else if (cx == FN_NTIM) {
- long sec = 0L;
- p[11] = NUL;
- p[14] = NUL;
- sec = atol(p+9) * 3600L + atol(p+12) * 60L + atol(p+15);
- sprintf(fnval,"%ld",sec); /* SAFE */
- p = fnval;
- }
- goto fnend;
- case FN_MJD: /* Modified Julian Date */
- if (argn < 1) /* Check number of args */
- p = zzndate(); /* None, get today's date-time */
- else /* Some */
- p = bp[0]; /* Use first */
- p = ckcvtdate(p,0); /* Convert to standard form */
- if (*p == '-') {
- failed = 1;
- if (fndiags) /* Default is this error message */
- ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_DATE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- /* Convert to modified Julian date */
- sprintf(fnval,"%ld",mjd(p)); /* SAFE */
- p = fnval; /* Point to result */
- goto fnend;
- case FN_MJD2: {
- long k = 0L;
- int n = 0;
- p = evalx(bp[0]);
- if (*p == '-') {
- p++;
- n = 1;
- }
- if (!rdigits(p)) {
- failed = 1;
- evalerr(fn);
- p = fnval;
- goto fnend;
- } else {
- k = atol(p);
- if (n) k = -k;
- }
- ckstrncpy(fnval,mjd2date(k),FNVALL); /* Convert to Date */
- p = fnval; /* Point to result */
- failed = 0;
- goto fnend;
- }
- #ifndef NODIAL
- case FN_PNCVT: { /* Convert phone number */
- extern char * pncvt();
- failed = 0;
- p = pncvt(bp[0]);
- if (!p) p = "";
- if (!*p) {
- failed = 1;
- if (fndiags) /* Default is this error message */
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_BAD_PHONENUM:\\f",fn,"()>",NULL);
- }
- goto fnend;
- }
- #endif /* NODIAL */
- case FN_DAY:
- case FN_NDAY:
- if (argn < 1) /* Check number of args */
- p = zzndate(); /* None, get today's date-time */
- else /* Some */
- p = bp[0]; /* Use first */
- p = ckcvtdate(p,0); /* Convert to standard form */
- if (*p == '-') {
- failed = 1;
- if (fndiags) /* Default is this error message */
- ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_DATE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- failed = 0;
- z = mjd(p); /* Convert to modified Julian date */
- z = z % 7L;
- if (z < 0) {
- z = 0 - z;
- k = 6 - ((int)z + 3) % 7;
- } else {
- k = ((int)z + 3) % 7; /* Day of week */
- }
- p = fnval; /* Point to result */
- if (cx == FN_NDAY)
- sprintf(fnval,"%d",k); /* SAFE */
- else
- ckstrncpy(fnval,wkdays[k],FNVALL);
- goto fnend;
- case FN_N2TIM: { /* Sec since midnight to hh:mm:ss */
- long k = 0L;
- int n = 0, hh, mm, ss;
- char * s = bp[0];
- if (argn < 1) /* If no arg substitute 0 */
- s = "0";
- p = evalx(s); /* Evaluate expression silently */
- if (*p == '-') { /* Check result for minus sign */
- p++;
- n = 1;
- }
- if (!rdigits(p)) { /* Check for numeric */
- failed = 1;
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- p = fnval;
- goto fnend;
- } else {
- k = atol(p);
- if (n) k = -k;
- }
- if (k < 0) { /* Check for negative */
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
- p = fnval;
- goto fnend;
- }
- hh = k / 3600L; /* Have positive number */
- mm = (k % 3600L) / 60L; /* break it down... */
- ss = ((k % 3600L) % 60L);
- sprintf(fnval,"%02d:%02d:%02d",hh,mm,ss); /* SAFE */
- p = fnval;
- failed = 0;
- goto fnend;
- }
- case FN_PERM: { /* File permissions */
- p = fnval;
- z = zchki(bp[0]);
- if (z < 0) {
- failed = 1;
- if (fndiags) {
- if (z == -1)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:FILE_NOT_FOUND:\\f",fn,"()>",NULL);
- else if (z == -2)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:FILE_NOT_READABLE:\\f",fn,"()>",NULL);
- else if (z == -3)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:FILE_NOT_ACCESSIBLE:\\f",fn,"()>",NULL);
- else
- ckmakmsg(fnval,FNVALL,
- "<ERROR:FILE_ERROR:\\f",fn,"()>",NULL);
- }
- goto fnend;
- }
- #ifdef CK_PERMS
- ckstrncpy(fnval,ziperm(bp[0]),FNVALL);
- #else
- ckstrncpy(fnval,"(unknown)",FNVALL);
- #endif /* CK_PERMS */
- goto fnend;
- }
- case FN_TLOOK: /* tablelook() */
- case FN_ALOOK: { /* arraylook() */
- int i, x, hi, lo, max, cmdlen;
- char abuf[16], *s, *pat;
- char kwbuf[256];
- char delim = ':';
- failed = 1; /* Assume failure */
- ckstrncpy(fnval,"-1",FNVALL);
- pat = bp[0]; /* Point to search pattern */
- if (!pat) pat = ""; /* Watch out for NULL pointer */
- cmdlen = strlen(pat); /* Get pattern length */
- if (argn < 2 /* || cmdlen < 1 */ ) { /* Need two args */
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
- goto fnend;
- }
- ckstrncpy(abuf,bp[1],16); /* Get array reference */
- if (argn > 2)
- delim = *(bp[2]);
- s = abuf;
- if ((x = arraybounds(s,&lo,&hi)) < 0) { /* Get index and bounds */
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
- goto fnend;
- }
- p = fnval; /* Point to result */
- max = a_dim[x]; /* Size of array */
- if (lo < 0) lo = 0; /* Use given range if any */
- if (lo > max) lo = max;
- if (hi < 0) hi = max;
- if (hi > max) hi = max;
- failed = 0; /* Unset failure flag */
- if (max < 1)
- goto fnend;
- kwbuf[255] = NUL;
- for (i = lo; i <= hi; i++) {
- if (!a_ptr[x][i])
- continue;
- if (cx == FN_ALOOK) {
- if (ckmatch(pat,a_ptr[x][i],inpcas[cmdlvl],1+4)) {
- sprintf(fnval,"%d",i); /* SAFE */
- goto fnend;
- }
- } else if (cx == FN_TLOOK) {
- char * aa;
- int j = 0, v = 0, len;
- if (i == hi)
- break;
- aa = a_ptr[x][i]; /* Point to this array element */
- if (!aa) aa = "";
- while (j < 254 && *aa) { /* Isolate keyword */
- if (*aa == delim)
- break;
- kwbuf[j++] = *aa++;
- }
- kwbuf[j] = NUL;
- len = j;
- v = 0;
- if ((len == cmdlen && !ckstrcmp(kwbuf,pat,len,0)) ||
- ((v = !ckstrcmp(kwbuf,pat,cmdlen,0)) &&
- ckstrcmp(a_ptr[x][i+1],pat,cmdlen,0))) {
- sprintf(fnval,"%d",i); /* SAFE */
- goto fnend;
- }
- if (v) { /* Ambiguous */
- ckstrncpy(fnval,"-2",FNVALL);
- goto fnend;
- }
- }
- }
- if (cx == FN_TLOOK) { /* tablelook() last element */
- ckstrncpy(fnval,"-1",FNVALL);
- if (!ckstrcmp(a_ptr[x][hi],pat,cmdlen,0))
- sprintf(fnval,"%d",hi); /* SAFE */
- }
- goto fnend;
- }
- case FN_TOB64: /* Base-64 conversion */
- case FN_FMB64:
- p = fnval;
- *p = NUL;
- if (argn < 1)
- goto fnend;
- if (cx == FN_TOB64) {
- x = b8tob64(bp[0],-1,fnval,FNVALL);
- } else {
- x = strlen(bp[0]);
- if (x % 4) { /* length must be multiple of 4 */
- failed = 1;
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_INCOMPLETE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- b64tob8(NULL,0,NULL,0); /* Reset */
- x = b64tob8(bp[0],-1,fnval,FNVALL);
- b64tob8(NULL,0,NULL,0); /* Reset again */
- }
- if (x < 0) {
- failed = 1;
- if (fndiags) {
- char * m = "INTERNAL_ERROR";
- switch (x) {
- case -1: m = "ARG_TOO_LONG"; break;
- case -2: m = "ARG_OUT_OF_RANGE"; break;
- }
- if (ckmakmsg(fnval,FNVALL,"<ERROR:",m,"\\f",fn) > 0)
- ckstrncat(fnval,"()>",FNVALL);
- }
- }
- goto fnend;
- case FN_ABS: {
- char * s;
- s = bp[0];
- if (*s == '-' || *s == '+')
- s++;
- if (!rdigits(s)) {
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- ckstrncpy(fnval,s,FNVALL);
- goto fnend;
- }
- case FN_AADUMP: {
- char abuf[16], *s = NULL, **ap = NULL, **vp = NULL;
- char pattern[VNAML];
- int slen, i, j, k, first = -1;
- extern int xdelmac();
- p = fnval;
- if (argn < 2) {
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG2:\\f",fn,"()>",NULL);
- goto fnend;
- }
- debug(F101,"aaconvert argn","",argn);
- s = bp[0];
- slen = strlen(s);
- /* Count elements so we can create the array */
- ckmakmsg(pattern,VNAML,s,"<*>",NULL,NULL);
- for (k = 0, i = 0; i < nmac; i++) {
- if (ckmatch(pattern,mactab[i].kwd,0,1)) {
- if (first < 0) /* Remember location of first match */
- first = i;
- k++;
- }
- }
- debug(F101,"aaconvert matches","",k);
- debug(F101,"aaconvert first","",first);
- fnval[0] = NUL; /* Initial return value */
- ckstrncpy(abuf,bp[1],16); /* Get array reference */
- s = abuf;
- if (*s == CMDQ) s++;
- p = fnval; /* Point to result */
- if (fndiags) /* Default is this error message */
- ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
- if (s[0] != '&') /* Address of array */
- goto fnend;
- if (s[2])
- if (s[2] != '[' || s[3] != ']')
- goto fnend;
- if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
- s[1] += 32;
- if ((x = dclarray(s[1],k)) < 0) /* Declare array to size */
- goto fnend;
- ap = a_ptr[x]; /* Point to array we just declared */
- /* debug(F111,"aaconvert array 1",abuf,ap); */
- abuf[0] = NUL;
- if (argn > 2) {
- ckstrncpy(abuf,bp[2],16); /* Get value array reference */
- s = abuf;
- if (*s == CMDQ) s++;
- if (s[0] != '&') /* Address of array */
- goto fnend;
- if (s[2])
- if (s[2] != '[' || s[3] != ']')
- goto fnend;
- if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
- s[1] += 32;
- if ((x = dclarray(s[1],k)) < 0)
- goto fnend;
- vp = a_ptr[x]; /* Point to array we just declared */
- }
- /* debug(F111,"aaconvert array 2",abuf,vp); */
- makestr(&ap[0],ckitoa(k));
- if (vp) makestr(&vp[0],ckitoa(k));
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:ASSOCIATIVE_ARRAY:\\f",fn,"()>",NULL);
- /* Copy macro index & value to the arrays and then remove the */
- /* macro, so the 'first' pointer keeps indicating the next one. */
- /* We could combine the initial counting loop with this one but */
- /* then it would be harder to create the array and anyway this */
- /* function is plenty fast as it is. */
- for (i = 1; i <= k; ) {
- if (!ckmatch(pattern,mactab[first].kwd,0,1)) {
- debug(F111,"aaconvert oddball",mactab[first].kwd,first);
- first++;
- continue;
- }
- ckstrncpy(tmpbuf,mactab[first].kwd,TMPBUFSIZ); /* Macro name */
- s = tmpbuf; /* Make writeable copy */
- s += slen; /* Isolate "index" */
- j = strlen(s) - 1;
- if (*s != '<' || *(s+j) != '>') { /* Check syntax */
- /* This shouldn't happen */
- debug(F111,"aaconvert ERROR",mactab[first].kwd,first);
- goto fnend;
- }
- *(s+j) = NUL; /* Remove final '>' */
- debug(F111,"aaconvert",s+1,i);
- makestr(&(ap[i]),s+1); /* Set first array to index */
- if (vp)
- makestr(&(vp[i]),mactab[first].mval); /* 2nd to value */
- if (xdelmac(first) < 0)
- goto fnend;
- i++;
- }
- sprintf(fnval,"%d",k); /* SAFE */
- p = fnval; /* Return size of array */
- debug(F110,"aaconvert return",p,0);
- failed = 0; /* Unset failure flag */
- goto fnend;
- }
- } /* End of switch() */
- #ifdef FNFLOAT
- /*
- Floating-point functions. To be included only if FNFLOAT is defined, which
- should happen only if CKFLOAT is also defined, and if the math library is
- linked in. Even then, we might have float-vs-double confusion as well as
- confusion about what the final "%f" format effector is supposed to reference
- (32 bits, 64 bits, etc). Expect trouble if CKFLOAT does not match the data
- type of math library functions or args.
- */
- if (cx == FN_FPABS || /* Floating-point functions */
- cx == FN_FPADD ||
- cx == FN_FPDIV ||
- cx == FN_FPEXP ||
- cx == FN_FPLOG ||
- cx == FN_FPLN ||
- cx == FN_FPMOD ||
- cx == FN_FPMAX ||
- cx == FN_FPMIN ||
- cx == FN_FPMUL ||
- cx == FN_FPPOW ||
- cx == FN_FPSQR ||
- cx == FN_FPINT ||
- cx == FN_FPSUB ||
- cx == FN_FPROU ||
- cx == FN_FPSIN ||
- cx == FN_FPCOS ||
- cx == FN_FPTAN) {
- CKFLOAT farg[2], fpresult = 0.0;
- char fpbuf[64], * bp0;
- double dummy;
- /* int sign = 0; */
- int i, j, places = 0;
- int argcount = 1;
- failed = 1;
- p = fnval;
- bp0 = bp[0];
- if (!bp0)
- bp0 = "0";
- else if (!*bp0)
- bp0 = "0";
- if (!isfloat(bp0,0)) {
- k = mxlook(mactab,bp0,nmac);
- bp0 = (k > -1) ? mactab[k].mval : NULL;
- if (bp0) {
- if (!isfloat(bp0,0)) {
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_FLOAT:\\f",fn,"()>",NULL);
- goto fnend;
- }
- }
- }
- if (cx == FN_FPINT) { /* Float to int */
- failed = 0;
- ckstrncpy(fnval,bp0,FNVALL);
- for (i = 0; fnval[i]; i++) {
- if (fnval[i] == '.') {
- fnval[i] = NUL;
- break;
- }
- }
- goto fnend;
- }
- switch (y) { /* These need 2 args */
- case FN_FPADD:
- case FN_FPDIV:
- case FN_FPMOD:
- case FN_FPMAX:
- case FN_FPMIN:
- case FN_FPMUL:
- case FN_FPPOW:
- case FN_FPSUB:
- argcount = 2;
- }
- /* Missing arguments are supplied as 0.0 */
- debug(F111,fn,"argcount",argcount);
- for (i = 0; i < argcount; i++) { /* Get floating-point args */
- #ifdef DEBUG
- if (deblog) {
- ckmakmsg(fpbuf,
- 64,
- "bp[",
- ckitoa(i),
- bp[i] ? bp[i] : "(null)",
- "]"
- );
- debug(F100,fpbuf,"",0);
- }
- #endif /* DEBUG */
- if (!bp[i]) {
- farg[i] = 0.0;
- } else if (!*(bp[i])) {
- farg[i] = 0.0;
- } else if (!isfloat(bp[i],0)) {
- char * tmp;
- k = mxlook(mactab,bp[i],nmac);
- tmp = (k > -1) ? mactab[k].mval : NULL;
- if (tmp) {
- if (!isfloat(tmp,0)) {
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_FLOAT:\\f",fn,"()>",NULL);
- goto fnend;
- }
- }
- }
- farg[i] = floatval;
- #ifdef DEBUG
- if (deblog) {
- sprintf(fpbuf,"farg[%d]=%f",i,farg[i]); /* SAFE */
- debug(F100,fpbuf,"",0);
- }
- #endif /* DEBUG */
- }
- if (bp[argcount]) { /* Get decimal places */
- char * s;
- s = bp[argcount];
- if (!s) s = "";
- if (!*s) s = "0";
- s = evalx(s);
- if (!s) s = "";
- if (!*s) {
- evalerr(fn);
- goto fnend;
- }
- places = atoi(s);
- }
- errno = 0;
- failed = 0;
- switch (y) { /* Now do the requested function */
- case FN_FPABS: /* Floating-point absolute value */
- #ifndef COMMENT
- fpresult = fabs(farg[0]);
- #else
- if (farg[0] < 0.0)
- fpresult = 0.0 - farg[0];
- #endif /* COMMENT */
- break;
- case FN_FPADD: /* FP add */
- fpresult = farg[0] + farg[1];
- break;
- case FN_FPDIV: /* FP divide */
- case FN_FPMOD: /* FP modulus */
- if (!farg[1]) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:DIVIDE_BY_ZERO:\\f",fn,"()>",NULL);
- } else
- fpresult = (cx == FN_FPDIV) ?
- (farg[0] / farg[1]) :
- fmod(farg[0],farg[1]);
- break;
- case FN_FPEXP: /* FP e to the x */
- fpresult = (CKFLOAT) exp(farg[0]);
- break;
- case FN_FPLOG: /* FP base-10 logarithm */
- case FN_FPLN: /* FP natural logarithm */
- if (farg[0] < 0.0) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
- } else
- fpresult = (cx == FN_FPLOG) ? log10(farg[0]) : log(farg[0]);
- break;
- case FN_FPMUL: /* FP multiply */
- fpresult = farg[0] * farg[1];
- break;
- case FN_FPPOW: /* FP raise to a power */
- fpresult = modf(farg[1],&dummy);
- if ((!farg[0] && farg[1] <= 0.0) ||
- (farg[0] < 0.0 && fpresult)) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
- } else
- fpresult = pow(farg[0],farg[1]);
- break;
- case FN_FPSQR: /* FP square root */
- if (farg[0] < 0.0) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
- } else
- fpresult = sqrt(farg[0]);
- break;
- case FN_FPSUB: /* FP subtract */
- fpresult = farg[0] - farg[1];
- break;
- case FN_FPROU: /* FP round */
- fpresult = farg[0];
- break;
- case FN_FPSIN: /* FP sine */
- fpresult = (CKFLOAT) sin(farg[0]);
- break;
- case FN_FPCOS: /* FP cosine */
- fpresult = (CKFLOAT) cos(farg[0]);
- break;
- case FN_FPTAN: /* FP tangent */
- fpresult = (CKFLOAT) tan(farg[0]);
- break;
- case FN_FPMAX:
- fpresult = (farg[0] > farg[1]) ? farg[0] : farg[1];
- break;
- case FN_FPMIN:
- fpresult = (farg[0] < farg[1]) ? farg[0] : farg[1];
- break;
- }
- /* Get here with fpresult = function result */
- if (errno) { /* If range or domain error */
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:FLOATING-POINT-OP:\\f",fn,"()>",NULL);
- }
- if (failed) /* and/or any other kind of error, */
- goto fnend; /* fail. */
- #ifndef COMMENT
- /* Call routine containing code that was formerly inline */
- ckstrncpy(fnval,fpformat(fpresult,places,cx == FN_FPROU),FNVALL);
- #else
- {
- char fbuf[16]; /* For creating printf format */
- if (!fp_rounding && /* If printf doesn't round, */
- (places > 0 || /* round result to decimal places. */
- (places == 0 && cx == FN_FPROU)))
- fpresult += (0.5 / pow(10.0,(CKFLOAT)places));
- if (places > 0) { /* If places specified */
- /* use specified places to write given number of digits */
- sprintf(fbuf,"%%0.%df",places); /* SAFE */
- sprintf(fnval,fbuf,fpresult); /* SAFE */
- } else { /* Otherwise... */
- #ifdef COMMENT
- /*
- Here we want to print exactly fp_digits significant digits, no matter which
- side of the decimal point they are on. That is, we want want the default
- format to show the maximum number of non-garbage digits, AND we want the last
- such digit to be rounded. Of course there is no way to do that, since the
- digit after the last non-garbage digit is, well, garbage. So the following
- clever ruse does no good.
- */
- int sign = 0, m = 0;
- sprintf(fnval,"%f",fpresult);
- if (fnval[0] == '-') sign = 1;
- for (i = sign; i < FNVALL; i++) {
- if (isdigit(fnval[i]))
- m++;
- else
- break;
- }
- if (m > 1) {
- int d = fp_digits - m;
- if (d < 1) d = 1;
- sprintf(fbuf,"%%%d.%df",fp_digits+sign+1,d);
- } else {
- sprintf(fbuf,"%%0.%df",fp_digits);
- }
- sprintf(fnval,fbuf,fpresult);
- #else
- /* Go for max precision */
- sprintf(fbuf,"%%0.%df",fp_digits); /* SAFE */
- sprintf(fnval,fbuf,fpresult); /* SAFE */
- #endif /* COMMENT */
- }
- if (fnval[0] == '-') sign = 1;
- }
- debug(F111,"fpresult 1",fnval,errno); /* Check for over/underflow */
- for (i = sign; fnval[i]; i++) { /* Give requested decimal places */
- if (fnval[i] == '.') /* First find the decimal point */
- break;
- else if (i > fp_digits + sign - 1) /* replacing garbage */
- fnval[i] = '0'; /* digits with 0... */
- }
- if (fnval[i] == '.') { /* Have decimal point */
- int gotend = 0;
- /* d < 0 so truncate fraction */
- if (places < 0 || (places == 0 && cx == FN_FPROU)) {
- fnval[i] = NUL;
- } else if (places > 0) { /* d > 0 so this many decimal places */
- i++; /* First digit after decimal */
- for (j = 0; j < places; j++) { /* Truncate after d decimal */
- if (!fnval[j+i]) /* places or extend to d */
- gotend = 1; /* decimal places. */
- if (gotend || j+i+sign > fp_digits)
- fnval[j+i] = '0';
- }
- fnval[j+i] = NUL;
- } else { /* d == 0 so Do The Right Thing */
- for (j = (int)strlen(fnval) - 1; j > i+1; j--) {
- if ((j - sign) > fp_digits)
- fnval[j] = '0';
- if (fnval[j] == '0')
- fnval[j] = NUL; /* Strip useless trailing 0's. */
- else
- break;
- }
- }
- }
- #endif /* COMMENT */
- debug(F111,"fpresult 2",fnval,errno);
- goto fnend;
- }
- #endif /* FNFLOAT */
- #ifdef CKCHANNELIO
- if (cx == FN_FSTAT || /* File functions */
- cx == FN_FPOS ||
- cx == FN_FEOF ||
- cx == FN_FGCHAR ||
- cx == FN_FGLINE ||
- cx == FN_FGBLK ||
- cx == FN_FPCHAR ||
- cx == FN_FPLINE ||
- cx == FN_FPBLK ||
- cx == FN_NLINE ||
- cx == FN_FERMSG ||
- cx == FN_FILNO) {
- int x = 0, t = 0, channel;
- long z;
- extern int z_maxchan;
- failed = 1; /* Assume failure */
- p = fnval; /* until we validate args */
- if (cx == FN_FERMSG) {
- extern int z_error;
- if (argn < 1) {
- x = z_error;
- } else if (chknum(bp[0])) {
- x = atoi(bp[0]);
- } else if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- failed = 0;
- ckstrncpy(fnval,ckferror(x),FNVALL);
- goto fnend;
- }
- if (argn < 1) { /* All file functions need channel */
- if (cx == FN_FSTAT) { /* Except f_status(), e.g. when */
- fnval[0] = '0'; /* called with a variable that */
- fnval[1] = NUL; /* hasn't been defined yet. */
- failed = 0;
- } else {
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
- }
- goto fnend;
- }
- if (rdigits(bp[0])) { /* Channel must be numeric */
- channel = atoi(bp[0]);
- } else { /* Fail if it isn't */
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- if (channel < 0 || channel > z_maxchan) { /* Check channel range */
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- x = z_getmode(channel); /* Find out about the channel */
- failed = 0; /* Assume success from here down */
- if (cx == FN_FSTAT) { /* Status / modes of channel */
- if (x > -1)
- x &= FM_RWB; /* Mask out irrelevant bits */
- else /* In this case not open is OK */
- x = 0; /* 0 if not open, 1-7 if open */
- sprintf(fnval,"%d",x); /* SAFE */
- goto fnend;
- } else if (x < 1) { /* Not \f_status() so must be open */
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:FILE_NOT_OPEN:\\f",fn,"()>",NULL);
- goto fnend;
- }
- switch (y) { /* Do the requested function */
- case FN_FPOS: /* Get position */
- z = z_getpos(channel); /* FIX THIS */
- sprintf(fnval,"%ld",z); /* SAFE */
- goto fnend;
- case FN_NLINE: /* Get line number */
- z = z_getline(channel); /* FIX THIS */
- sprintf(fnval,"%ld",z); /* SAFE */
- goto fnend;
- case FN_FEOF: /* Check EOF */
- t = 0;
- if (x & FM_EOF) t = 1;
- sprintf(fnval,"%d",t); /* SAFE */
- goto fnend;
- case FN_FILNO: /* Get file handle */
- x = z_getfnum(channel);
- sprintf(fnval,"%d",x); /* SAFE */
- goto fnend;
- case FN_FPBLK: /* Read or write block */
- case FN_FGBLK:
- if (argn < 2) {
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
- goto fnend;
- }
- if (rdigits(bp[1])) {
- t = atoi(bp[1]);
- } else {
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- case FN_FGCHAR: /* Read or write character or line */
- case FN_FPCHAR:
- case FN_FGLINE:
- case FN_FPLINE:
- fnval[0] = NUL;
- switch (y) {
- case FN_FGCHAR: t = z_in(channel,fnval,FNVALL,1,1); break;
- case FN_FGLINE: t = z_in(channel,fnval,FNVALL,FNVALL-1,0); break;
- case FN_FGBLK:
- if (t >= FNVALL) t = FNVALL - 1;
- t = z_in(channel,fnval,FNVALL,t,1);
- break;
- case FN_FPCHAR: t = z_out(channel,bp[1],1,1); break;
- case FN_FPLINE: t = z_out(channel,bp[1],-1,0); break;
- case FN_FPBLK: t = z_out(channel,bp[1],-1,1); break;
- }
- if (t < 0) { /* Handle read/write error */
- failed = 1;
- if (fndiags && t != FX_EOF)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:FILE_ERROR_%d:\\f",fn,"()>",NULL);
- goto fnend;
- }
- if (cx == FN_FGCHAR) /* Null terminate char */
- fnval[1] = NUL;
- /* Write (put) functions return numeric status code */
- if (cx == FN_FPCHAR || cx == FN_FPLINE || cx == FN_FPBLK)
- sprintf(fnval,"%d",t); /* SAFE */
- goto fnend;
- }
- }
- #endif /* CKCHANNELIO */
- if (cx == FN_SQUEEZE) { /* String function \fsqueeze() */
- /* Squeeze out whitespace */
- /* Add options later for whether to trim leading and trailing blanks */
- /* and what to do about control characters, 8-bit whitespace, etc */
- int started = 0; /* Flag for first non-whitespace */
- int n = 0; /* Blank/Tab counter */
- s = bp[0] ? bp[0] : "";
- p = fnval; /* Result buffer */
- while (*s) { /* While there is input */
- if (!started && (*s == ' ' || *s == '\011')) {
- s++; /* Skip past leading whitespace */
- continue;
- }
- started++; /* Leading whitespace was skipped */
- if (*s != ' ' && *s != '\011') { /* Have a nonspace char */
- n = 0; /* reset space counter */
- *p++ = *s++; /* copy char to destination */
- continue;
- }
- if (n++ > 0) { /* Have blank or tab */
- s++; /* don't copy more than one */
- continue;
- }
- *p++ = ' '; /* Deposit one space */
- s++; /* and go to next source char */
- }
- if (*(p-1) == ' ') p--; /* Remove trailing space */
- *p = NUL; /* Terminate string */
- p = fnval; /* point to beginning */
- goto fnend; /* Done. */
- }
- if (cx == FN_PATTERN) { /* \fpattern() for INPUT */
- itsapattern = 1;
- if (argn > 0) {
- p = fnval;
- ckstrncpy(fnval,bp[0],FNVALL);
- } else p = "";
- goto fnend;
- }
- if (cx == FN_HEX2N || cx == FN_OCT2N) { /* \fhex2n(), \foct2n() */
- p = "0";
- if (argn < 1)
- goto fnend;
- p = ckradix(bp[0], ((cx == FN_HEX2N) ? 16 : 8), 10);
- if (!p) {
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- failed = 0;
- ckstrncpy(fnval,p,FNVALL);
- p = fnval;
- goto fnend;
- }
- if (cx == FN_HEX2IP) {
- int c[2], ip[4], i, k;
- p = "0";
- if (argn < 1)
- goto fnend;
- s = bp[0];
- if ((int)strlen(s) != 8) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- p = fnval;
- for (k = 0; k < 8; k += 2) {
- for (i = 0; i < 2; i++) {
- c[i] = *s++;
- if (islower(c[i])) c[i] = toupper(c[i]);
- if (c[i] >= '0' && c[i] <= '9') {
- c[i] -= 0x30;
- } else if (c[i] >= 'A' && c[i] <= 'F') {
- c[i] -= 0x37;
- } else {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- ip[k/2] = c[0] << 4 | c[1];
- }
- sprintf(p,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]); /* SAFE */
- }
- goto fnend;
- }
- if (cx == FN_IP2HEX) {
- int ip[4], i;
- char * q;
- p = "00000000";
- if (argn < 1)
- goto fnend;
- s = bp[0];
- p = fnval;
- for (i = 0; i < 3; i++) {
- q = ckstrchr(s,'.');
- if (q) {
- *q++ = NUL;
- ip[i] = atoi(s);
- s = q;
- } else {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- }
- ip[3] = atoi(s);
- sprintf(p,"%02x%02x%02x%02x",ip[0],ip[1],ip[2],ip[3]); /* SAFE */
- goto fnend;
- }
- if (cx == FN_RADIX) {
- failed = 1;
- p = fnval;
- if (argn < 3) {
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:MISSING_ARG:\\f",fn,"()>",NULL);
- goto fnend;
- }
- if (!rdigits(bp[1]) || !rdigits(bp[2])) {
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- p = ckradix(bp[0],atoi(bp[1]),atoi(bp[2]));
- if (!p) {
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- failed = 0;
- ckstrncpy(fnval,p,FNVALL);
- p = fnval;
- goto fnend;
- }
- if (cx == FN_JOIN) {
- int i, x, y, z, flag, flag2, hi, lo, max, seplen, grouping = 0;
- char abuf[16], c, *s, *q, *sep = NULL;
- char * gr_opn = "\"{'([<"; /* Group open brackets */
- char * gr_cls = "\"}')]>"; /* Group close brackets */
- char lb[2], rb[2]; /* Selected left and right brackets */
- int csv = 0, tsv = 0; /* Function flags */
- char specialchar = 0; /* Field char that triggers grouping */
- char *s2 = NULL; /* Address of malloc'd storage */
- failed = 1; /* Assume failure */
- fnval[0] = NUL;
- debug(F101,"FNJOIN ARGN","",argn);
- ckstrncpy(abuf,bp[0],16); /* Get array reference */
- s = abuf;
- if ((x = arraybounds(s,&lo,&hi)) < 0) { /* Get index and bounds */
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
- goto fnend;
- }
- p = fnval; /* Point to result */
- max = a_dim[x]; /* Size of array */
- if (lo < 0) lo = 1; /* Use given range if any */
- if (lo > max) lo = max;
- #ifdef COMMENT
- hi = max;
- #else
- /*
- This is a workaround for the problem in which the dimension of the \&_[]
- array (but not its contents) grows upon entry to a SWITCH block. But this
- code prevents the dimension from growing. Go figure.
- */
- if (hi < 0) { /* Bounds not given */
- if (x) /* Regular array */
- hi = max;
- else /* Argument vector array */
- for (hi = max; hi >= lo; hi--) { /* ignore any trailing */
- if (!a_ptr[x][hi]) continue; /* empty elements */
- if (!*(a_ptr[x][hi])) continue;
- break;
- }
- }
- #endif /* COMMENT */
- if (hi > max) hi = max;
- failed = 0; /* Unset failure flag */
- if (max < 1)
- goto fnend;
- sep = " "; /* Separator */
- lb[0] = NUL; /* Group start char (as string) */
- rb[0] = NUL;
- lb[1] = NUL; /* Group end char as string */
- rb[1] = NUL;
- if (argn > 1) {
- if (bp[1]) if (*bp[1]) { /* If arg1 given and not empty */
- if (!strcmp(bp[1],"CSV")) { /* Special "CSV" symbolic arg */
- csv++; /* Make a comma separated list */
- sep = ","; /* Comma */
- specialchar = *sep; /* Separator is special character */
- grouping = 1; /* Group with doublequotes */
- lb[0] = '"'; /* and here */
- rb[0] = '"'; /* they are */
- } else if (!strcmp(bp[1],"TSV")) { /* "TSV" symbolic arg */
- tsv++; /* Make a Tab separated list */
- sep = "\011"; /* Tab */
- specialchar = *sep;
- grouping = 0; /* No grouping */
- } else /* Normal case */
- sep = bp[1]; /* use the separator char specified */
- }
- }
- if (argn > 2 && !csv && !tsv) { /* Grouping? */
- char * bp2 = bp[2];
- if (!bp2) bp2 = "0";
- if (!*bp2) bp2 = "0";
- if (chknum(bp2)) {
- grouping = atoi(bp2);
- if (grouping < 0 || grouping > 63)
- grouping = 1;
- } else {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- if (grouping) { /* Take lowest-order one */
- int j, k; /* and set the others to 0 */
- for (k = 0; k < 6; k++) {
- j = 1 << k;
- if (grouping & j) {
- lb[0] = gr_opn[k];
- rb[0] = gr_cls[k];
- break;
- }
- }
- }
- }
- if (!csv && !tsv) { /* Normal case, not CSV or TSV */
- specialchar = SP; /* Special character is space */
- if (argn > 3) /* Nonzero 4th arg for no separator */
- if (chknum(bp[3]))
- if (atoi(bp[3]) > 0)
- sep = NULL;
- if (!sep) {
- sep = "";
- seplen = 0;
- } else
- seplen = strlen(sep);
- }
- for (i = lo; i <= hi; i++) { /* Loop thru selected array elements */
- s = a_ptr[x][i]; /* Get next element */
- if (!s)
- s = "";
- flag = 0; /* Flag to indicate grouping needed */
- flag2 = 0; /* Flag for internal doublequotes */
- if (grouping) { /* Does this element need quoting? */
- q = s; /* Look for special character */
- while ((c = *q++)) { /* If found */
- if (c == specialchar) /* grouping is required */
- flag++;
- if (csv && (c == '"')) /* Character that needs doubling */
- flag2++; /* in comma-separated list */
- if (flag && !csv) /* Exit early if no more to do */
- break;
- }
- }
- y = strlen(s); /* Get length of this element */
- if ((y > 0) && csv && !flag) { /* CSV item needs grouping */
- if (s[0] == SP || s[y-1] == SP || /* if it has leading */
- s[0] == HT || s[y-1] == HT) /* or trailing whitespace */
- flag++; /* then it needs grouping */
- }
- if (flag || flag2) { /* String needs grouping or quoting */
- char *ss = s;
- q = (char *)malloc(y + flag2 + 3); /* Make new buffer */
- if (q) {
- s2 = q; /* and this is what to free */
- if (flag) /* If grouping */
- *q++ = lb[0]; /* put opening group quote */
- while (*ss) { /* Loop through string */
- if (flag2 && (*ss == '"')) /* If CSV and this a '"' */
- *q++ = *ss; /* double it. */
- *q++ = *ss++; /* Copy the character */
- }
- if (flag) /* If grouping */
- *q++ = rb[0]; /* add closing group quote */
- *q = NUL; /* terminate the result. */
- s = s2;
- y = strlen(s);
- }
- }
- z = 0; /* Number of chars copied */
- flag = 0; /* flag is now buffer-overrun flag */
- if (y > 0) /* If this string is not empty */
- z = ckstrncat(fnval,s,FNVALL); /* copy it. */
- if (s2) free(s2); /* Free temp storage */
- if (z < y) /* Now check for buffer overrun. */
- flag++;
- if (!flag && *sep && i < hi) { /* If buffer still has room */
- z = ckstrncat(fnval,sep,FNVALL); /* copy delimiter */
- if (z < seplen)
- flag++;
- }
- if (flag) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:RESULT_TOO_LONG:\\f",fn,"()>",NULL);
- goto fnend;
- }
- }
- isjoin = 1;
- goto fnend;
- }
- if (cx == FN_SUBST) { /* \fsubstitute() */
- CHAR c, * s, * r, * tp[2], buf1[256], buf2[256], buf3[256];
- int len, i, j, state = 0, lo = 0, hi = 0;
- failed = 0;
- p = fnval; /* Result pointer */
- *p = NUL;
- if (!bp[0]) /* No target, no result*/
- goto fnend;
- len = strlen(bp[0]); /* Length of source */
- if (len == 0)
- goto fnend;
- if (len > FNVALL) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:RESULT_TOO_LONG:\\f",fn,"()>",NULL);
- goto fnend;
- }
- if (!bp[1]) {
- ckstrncpy(bp[0],fnval,FNVALL);
- goto fnend;
- }
- tp[0] = buf1; /* For s2-s3 interpretation loop */
- tp[1] = buf2;
- for (i = 0; i < 256; i++) { /* Initialize working buffers */
- buf1[i] = 0; /* s2 expansion buffer */
- buf2[i] = 0; /* s3 expansion buffer */
- buf3[i] = i; /* Translation table */
- }
- for (i = 0; i < 2; i++) { /* Interpret s2 and s3 */
- s = (CHAR *)bp[i+1]; /* Arg pointer */
- if (!s) s = (CHAR *)"";
- r = tp[i]; /* To construct interpreted arg */
- j = 0; /* Output buf pointer */
- state = 0; /* Initial state */
- while (c = *s++) { /* Loop thru arg chars */
- if (j > 255) /* Output buf full */
- break;
- switch (state) {
- case 0: /* Normal state */
- switch (c) {
- case '\\': /* Have quote */
- state = 1;
- break;
- case '[': /* Have range starter */
- state = 2;
- break;
- default: /* Anything else */
- r[j++] = c;
- break;
- }
- continue;
- case 1: /* Quoted char */
- r[j++] = c;
- state = 0;
- continue;
- case 2: /* Range bottom */
- lo = c;
- state++;
- continue;
- case 3: /* Range separater */
- if (c != '-') {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:BAD_RANGE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- state++;
- continue;
- case 4: /* Range top */
- hi = c;
- state++;
- continue;
- case 5: /* Range end */
- if (c != ']') {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:BAD_RANGE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- for (k = lo; k <= hi && j < 255; k++) /* Fill in */
- r[j++] = k;
- lo = 0; hi = 0; /* Reset */
- state = 0;
- continue;
- }
- }
- }
- for (i = 0; i < 256 && buf1[i]; i++) { /* Create translation table */
- k = (unsigned)buf1[i];
- buf3[k] = buf2[i];
- }
- s = (CHAR *)bp[0]; /* Point to source string */
- for (i = 0; i < len; i++) { /* Translation loop */
- k = (unsigned)s[i]; /* Get next char */
- if (!buf3[k]) /* Remove this char */
- continue;
- *p++ = buf3[k]; /* Substitute this char */
- }
- *p = NUL;
- p = fnval;
- goto fnend;
- }
- #ifndef NOSEXP
- if (cx == FN_SEXP) { /* \fsexpression(arg1) */
- char * p2;
- fsexpflag++;
- p = (argn > 0) ? dosexp(bp[0]) : "";
- fsexpflag--;
- p2 = fnval;
- while ((*p2++ = *p++)) ;
- p = fnval;
- goto fnend;
- }
- #endif /* NOSEXP */
- if (cx == FN_CMDSTK) { /* \fcmdstack(n1,n2) */
- int i, j, k;
- char * s;
- if (bp[0])
- val1 = *(bp[0]) ? evalx(bp[0]) : ckitoa(cmdlvl);
- else
- val1 = ckitoa(cmdlvl);
- #ifdef COMMENT
- free(bp[0]); /* (evalx() always uses same buffer) */
- bp[0] = NULL; /* (not any more!) */
- #endif /* COMMENT */
- failed = 1;
- if (argn > 1) {
- #ifdef COMMENT
- makestr(&(bp[0]),val1);
- val1 = bp[0];
- #endif /* COMMENT */
- val2 = *(bp[1]) ? evalx(bp[1]) : "0";
- if (!(chknum(val1) && chknum(val2))) {
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- goto fnend;
- }
- } else {
- val1 = ckitoa(cmdlvl);
- val2 = "0";
- }
- i = atoi(val1); /* Level */
- j = atoi(val2); /* Flags */
- if (i < 0 || i > cmdlvl) {
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_OUT_OF_RANGE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- failed = 0;
- p = fnval;
- k = cmdstk[i].src; /* What (prompt, file, macro) */
- if (j) {
- ckstrncpy(fnval,ckitoa(k),FNVALL);
- goto fnend;
- }
- switch (k) {
- case CMD_KB:
- ckstrncpy(fnval,"(prompt)",FNVALL);
- break;
- case CMD_TF:
- s = tfnam[cmdstk[i].lvl];
- if (!zfnqfp(s,FNVALL,fnval))
- ckstrncpy(fnval,s,FNVALL);
- break;
- case CMD_MD:
- ckstrncpy(fnval,m_arg[cmdstk[i].lvl][0],FNVALL);
- break;
- }
- goto fnend;
- }
- #ifdef CKFLOAT
- if (cx == FN_DIFDATE) { /* \fdiffdates(d1,d2) */
- char * d1, * d2;
- d1 = bp[0] ? bp[0] : ckdate();
- d2 = bp[1] ? bp[1] : ckdate();
- p = (char *)cmdiffdate(d1,d2);
- if (!p) {
- failed = 1;
- if (fndiags) {
- ckmakmsg(fnval,FNVALL,"<ERROR:BAD_DATE:\\f",fn,"()>",NULL);
- p = fnval;
- }
- }
- goto fnend;
- }
- #endif /* CKFLOAT */
- if (cx == FN_CMPDATE) { /* \fcmddates(d1,d2) */
- int x = 0;
- char d1[18], d2[18], * dp;
- failed = 0;
- d1[0] = NUL;
- d2[0] = NUL;
- p = fnval;
- dp = cmcvtdate(bp[0],1);
- if (dp) {
- ckstrncpy(d1,dp,18);
- if ((dp = cmcvtdate(bp[1],1))) {
- ckstrncpy(d2,dp,18);
- x = 1;
- }
- }
- if (x == 0) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:BAD_DATE:\\f",fn,"()>",NULL);
- } else {
- x = strcmp(d1,d2);
- if (x > 0)
- x = 1;
- else if (x < 0)
- x = -1;
- sprintf(fnval,"%d",x);
- }
- goto fnend;
- }
- if (cx == FN_TOGMT) { /* \futcdate(d1) */
- char * d1, * dp;
- char datebuf[32];
- char d2[32];
- p = fnval;
- failed = 1;
- if ((dp = cmcvtdate(bp[0],1))) { /* The given date */
- ckstrncpy(datebuf,dp,18);
- ckstrncpy(d2,dp,18); /* local time */
- ckstrncat(datebuf,"Z",19); /* Same time GMT */
- if ((dp = cmcvtdate(datebuf,1))) /* converted to local time */
- ckstrncpy(datebuf,dp,18);
- if ((p = (char *)cmdiffdate(d2,datebuf))) { /* Get offset */
- ckstrncat(d2,p,32); /* Append offset to local time */
- if ((dp = cmcvtdate(d2,1))) {
- failed = 0;
- ckstrncpy(fnval,dp,FNVALL);
- p = fnval;
- }
- }
- }
- if (failed && fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:BAD_DATE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- if (cx == FN_DELSEC) { /* \fdelta2secs(delta-time) */
- long secs;
- p = fnval;
- if ((x = delta2sec(bp[0],&secs)) < 0) {
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,
- (x == -1) ?
- "<ERROR:BAD_DELTA_TIME:\\f" :
- "<ERROR:OVERFLOW:\\f",
- fn,
- "()>",
- NULL
- );
- goto fnend;
- }
- sprintf(p,"%ld",secs);
- goto fnend;
- }
- if (cx == FN_PC_DU) {
- char c, * s = bp[0];
- if (!s) s = "";
- p = fnval;
- while ((c = *s++)) {
- if (c == ':') {
- if (*s != '\\')
- *p++ = '/';
- } else if (c == '\\') {
- *p++ = '/';
- } else {
- *p++ = c;
- }
- }
- *p = NUL;
- p = fnval;
- goto fnend;
- }
- if (cx == FN_PC_UD) { /* Unix to DOS path */
- char c, * s = bp[0];
- if (!s) s = "";
- if (*s == '~') { /* Skip leading tilde */
- s++;
- if (*s == '/')
- s++;
- }
- p = fnval;
- while ((c = *s++))
- *p ++ = (c == '/') ? '\\' : c;
- *p = NUL;
- p = fnval;
- goto fnend;
- }
- if (cx == FN_KWVAL) { /* Keyword=Value */
- p = dokwval(bp[0],bp[1]?bp[1]:"=");
- goto fnend;
- }
- #ifdef COMMENT
- /* Cute idea but doesn't work */
- if (cx == FN_SLEEP || cx == FN_MSLEEP) {
- p = "";
- if (chknum(bp[0])) {
- x = atoi(bp[0]);
- } else {
- failed = 1;
- if (fndiags) {
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_NOT_NUMERIC:\\f",fn,"()>",NULL);
- p = fnval;
- }
- goto fnend;
- }
- if (cx == FN_SLEEP)
- x *= 1000;
- msleep(x);
- goto fnend;
- }
- #endif /* COMMENT */
- #ifdef NT
- if (cx == FN_SNAME) {
- GetShortPathName(bp[0],fnval,FNVALL);
- goto fnend;
- }
- if (cx == FN_LNAME) {
- ckGetLongPathName(bp[0],fnval,FNVALL);
- goto fnend;
- }
- #endif /* NT */
- /*
- \femailaddress():
- Picks the email address out of an RFC 2822 From: or Sender: header.
- Added 26 Nov 2005. Handles all common, and some uncommon, cases but
- doesn't totally bother about nested comments. Needed this for fetching
- email from a POP server and then constructing the BSD "From " line.
- Works with or without the "From: " or "Sender: " tag.
- */
- if (cx == FN_EMAIL) {
- char c, * s = bp[0], * s2, * s3, * ap = "";
- int k, state = 0, quote = 0, infield = 0;
- int pc = 0; /* For nested comments */
- if (!s) s = "";
- if (!*s) goto xemail;
- if (ckindex("From: ",s,0,0,0) == 1) s += 5;
- if (ckindex("Sender: ",s,0,0,0) == 1) s += 7;
- k = strlen(s); /* Strip junk from end */
- if (k < 1) goto xemail;
- k--;
- while (k >= 0 && s[k] == CR || s[k] == LF)
- s[k--] = NUL;
- while (k >= 0 && s[k] == SP || s[k] == HT)
- s[k--] = NUL;
- if (k == 0)
- goto xemail;
- #ifndef COMMENT /* Simple method if not 100% foolproof */
- k = 0;
- for (s2 = s; *s2; s2++) { /* Find at-sign */
- if (*s2 == '@') {
- k++; /* If more than one use rightmost */
- s3 = s2;
- }
- }
- if (k < 1) /* No at-sign */
- goto xemail;
- for (ap = s3-1; ap >= s; ap--) { /* Back up to beginning of address */
- if (isspace(*ap) || *ap == '<') {
- ap++;
- break;
- }
- if (ap == s)
- break;
- }
- for (s2 = s3+1; *s2; s2++) { /* Find end of address */
- if (isspace(*s2) || *s2 == '>')
- break;
- }
- *s2-- = NUL;
- if (*ap == '[' && *s2 == ']') { /* Handle [blah@blah.blah] */
- ap++;
- *s2 = NUL;
- }
- if (!ckstrcmp(ap,"mailto:",7,0)) /* Handle mailto: URLs */
- ap += 7;
- #else /* Too complicated and error-prone */
- k = 0;
- for (s2 = s; *s2; s2++) { /* Strip leading whitespace */
- if (*s2 == SP || *s2 == HT) {
- k = 1;
- break;
- }
- }
- if (!k) { /* Simple address */
- ap = s;
- goto xemail;
- }
- do { /* Not simple, have to extract it */
- if (quote) {
- quote = 0;
- continue;
- } else if (*s == '\\') {
- quote = 1;
- continue;
- }
- switch (state) {
- case 0:
- if (!infield && *s == '"') { /* Quoted string */
- infield = 1;
- c = '"';
- state = 1;
- } else if (!infield && *s == '(') { /* Comment in parens */
- pc++;
- infield = 1;
- c = ')';
- if (*ap) *s = NUL;
- state = 1;
- } else if (!infield && *s == '<') { /* Address */
- infield = 1;
- c = '>';
- ap = s+1;
- state = 2;
- } else if (infield && (*s == SP || *s == HT)) {
- infield = 0;
- } else { /* One or more bare words */
- infield = 1; /* Could be an address */
- if (!*ap) ap = s; /* Could be comments */
- }
- continue;
- case 1: /* In Quoted string or Comment */
- if (infield && *s == c) { /* Look for end */
- infield = 0;
- *s++ = NUL;
- while (*s == SP || *s == HT) s++;
- if (!*ap)
- ap = s;
- state = 0;
- }
- continue;
- case 2: /* In address */
- if (infield && *s == c) { /* Looking for end */
- infield = 0;
- *s = NUL;
- break;
- }
- }
- } while (*s++);
- xemail:
- if (*ap) {
- while (*ap == SP || *ap == HT) ap++;
- }
- k = strlen(ap) - 1;
- while (k >= 0 && (ap[k] == SP || ap[k] == HT))
- ap[k--] = NUL;
- if (*ap) {
- failed = 0;
- if (*ap == '<') {
- k = strlen(ap);
- if (*(ap+k-1) == '>') {
- ap[k-1] = NUL;
- ap++;
- }
- }
- } else
- failed = 1;
- /* Here we might also want check against "*@*.*" */
- #endif /* COMMENt */
- xemail:
- ckstrncpy(fnval,ap,FNVALL);
- goto fnend;
- }
- #ifdef SEEK_CUR
- /*
- \fpictureinfo(): Get dimensions of GIF or JPG image - fdc June 2006.
- NOTE: The height and width of a JPG image do not necessarily indicate
- an image's actual orientation. This is given by the Exif Orientation
- tag (0x0122). But locating it in a JPG file without having a full-blown
- Exif parser is probably not possible.
- */
- if (cx == FN_PICTURE) {
- FILE *fp = NULL;
- int c, x, w = 0, h = 0, eof = 0;
- unsigned int i, j, k;
- unsigned char buf[1024];
- char abuf[16], * p, * s;
- char ** ap = NULL;
- #ifdef UNIX
- char * tx;
- #endif /* UNIX */
- p = fnval; /* Point to result */
- failed = 1; /* Assume failure */
- s = bp[0];
- #ifdef UNIX
- if (*s == '~') {
- tx = tilde_expand(bp[0]);
- if (tx) if (*tx) {
- free(bp[0]);
- bp[0] = NULL;
- makestr(&(bp[0]),tx);
- }
- s = bp[0];
- }
- #endif /* UNIX */
- if (argn > 1) {
- int xi;
- ckstrncpy(abuf,bp[1],16); /* Get array reference */
- s = abuf;
- if (*s == CMDQ) s++;
- if (fndiags) /* Default is this error message */
- ckmakmsg(fnval,FNVALL,
- "<ERROR:ARG_BAD_ARRAY:\\f",fn,"()>",NULL);
- if (s[0] != '&') /* "Address" of array */
- goto fnend;
- if (s[2])
- if (s[2] != '[' || s[3] != ']')
- goto fnend;
- if (s[1] >= 64 && s[1] < 91) /* Convert upper to lower */
- s[1] += 32;
- if ((xi = dclarray(s[1],3)) < 0) /* three elements */
- goto fnend;
- ap = a_ptr[xi]; /* Point to array we just declared */
- }
- s = bp[0]; /* Filename */
- failed = 0; /* From here on we don't fail */
- p[0] = '0'; /* Default return value */
- p[1] = NUL;
- /* Tail anchor removed 2013-10-15 -fdc */
- if (!ckmatch("*.{jpg,jpeg,gif}",s,0,1)) /* Appropriate name? */
- goto fnend; /* No, fail */
- fp = fopen(s, "r"); /* Open it */
- if (fp == NULL) { /* Can't, fail */
- p[0] = '-';
- p[1] = '1';
- p[2] = NUL; /* Return -1 */
- goto fnend;
- }
- k = strlen(s);
- if (!ckstrcmp(&s[k-4],".gif",4,0)) { /* GIF file */
- if (fread(buf,1,10,fp) != 10) {
- fclose(fp);
- goto fnend;
- }
- /* Check signature */
- if (ckstrcmp((char *)buf,"GIF87a",6,0) &&
- ckstrcmp((char *)buf,"GIF89a",6,0)) {
- fclose(fp);
- goto fnend;
- }
- w = buf[6] + 256 * buf[7];
- h = buf[8] + 256 * buf[9];
- goto picend;
- } else if (!ckstrcmp(&s[k-4],".jpg",4,0) || /* JPEG file */
- !ckstrcmp(&s[k-5],".jpeg",5,0)) { /* (according to name) */
- if (fread(buf,1,2,fp) != 2) { /* Read 1st bytes */
- fclose(fp);
- goto fnend;
- }
- if (buf[0] != 0xff || buf[1] != 0xd8) { /* Check signature */
- fclose(fp); /* Should be FFD8 */
- goto fnend;
- }
- eof = 0;
- while (!eof) { /* Loop for each marker */
- while (!eof) { /* Find next marker */
- c = getc(fp);
- if (c == (unsigned int)EOF) {
- eof++;
- break;
- }
- if (c == 0xff) {
- buf[0] = c;
- c = getc(fp);
- if (c == (unsigned int)EOF) {
- eof++;
- break;
- }
- buf[1] = c;
- if (c == 0xd9) /* FFD9 means End of Image */
- eof++;
- if (c >= 0xc0 && c <= 0xfe)
- break;
- }
- }
- if (eof) break;
- x = buf[1];
- if (x == 0xc0 || x == 0xc1 || x == 0xc2 || x == 0xc3 ||
- x == 0xc9 || x == 0xca || x == 0xcb) {
- if (fread(buf,1,7,fp) != 7) {
- fclose(fp);
- goto fnend;
- }
- h = buf[3] * 256 + buf[4];
- w = buf[5] * 256 + buf[6];
- goto picend;
- } else { /* Not a desired field */
- if (feof(fp)) {
- eof++;
- break;
- }
- if (fread(buf,1,2,fp) != 2) { /* Length of this field */
- fclose(fp);
- goto fnend;
- }
- j = 256 * buf[0] + buf[1] - 2; /* Skip next field */
- if (CKFSEEK(fp,(CK_OFF_T)j,SEEK_CUR) != 0) {
- fclose(fp);
- goto fnend;
- }
- }
- }
- }
- picend:
- if (ap) {
- char * s;
- makestr(&(ap[0]),"2");
- makestr(&(ap[1]),ckitoa(w));
- makestr(&(ap[2]),ckitoa(h));
- s = jpgdate(fp);
- debug(F110,"jpgdate",s,0);
- if (s) if (*s) makestr(&(ap[3]),s);
- }
- fclose(fp);
- if (w > 0 && h > 0) {
- if (w > h) p[0] = '1'; /* Landscape */
- else if (h > w) p[0] = '2'; /* Portrait */
- else p[0] = '3'; /* Square - 2013-10-05 */
- }
- goto fnend;
- }
- #endif /* SEEK_CUR */
- if (cx == FN_PID) {
- int x = -1;
- if (chknum(bp[0])) { /* Need numeric argument */
- int pid;
- pid = atoi(bp[0]); /* Convert to int */
- #ifdef UNIX
- if (kill(pid,0) < 0) { /* Test it */
- if (errno ==
- #ifdef ESRCH
- ESRCH /* No such process */
- #else
- 3
- #endif /* ESRCH */
- )
- x = 0;
- } else /* Process exists */
- x = 1;
- #endif /* UNIX */
- }
- sprintf(fnval,"%d",x); /* SAFE */
- goto fnend;
- }
- if (cx == FN_FUNC) {
- char * s = bp[0];
- p = "0";
- debug(F111,"ffunc",s,argn);
- if (argn > 0) {
- int x, y;
- for (p = s; *p; p++) { /* Chop off trailing parens if any */
- if (*p == '(') {
- *p = NUL;
- break;
- }
- }
- /* Chop off leading "\\f" or "\f" or "f" */
- p = s;
- if (*p == CMDQ) /* Allow for \\f... */
- p++;
- if (*p == CMDQ && (*(p+1) == 'f' || *(p+1) == 'F')) { /* or \f */
- p += 2;
- } else if (*p == 'f' || *p == 'F') { /* or just f */
- p++;
- }
- y = lookup(fnctab,p,nfuncs,&x); /* Look up the result */
- debug(F111,"ffunc",p,y);
- p = (y > -1) ? "1" : "0";
- }
- goto fnend;
- }
- if (cx == FN_RECURSE) {
- int t, n;
- char * s;
- fnval[0] = NUL; /* Default result is empty string */
- s = bp[0]; /* Check for null argument */
- if (!s) s = ""; /* or empty argument */
- if (!*s) goto fnend; /* in which case return empty string */
- n = FNVALL; /* Not empty, max size for result */
- s = fnval; /* Location of result */
- {
- /* Force VARIABLE-EVALUATION SIMPLE RECURSIVE */
- /* NOTE: This is vulnerable to SIGINT and whatnot... */
- int tmp = vareval; /* Save VARIABLE-EVALUATION setting */
- vareval = 1; /* Force it to RECURSIVE */
- zzstring(bp[0],&s,&n); /* Expand arg into result space */
- vareval = tmp; /* Restore VARIABLE-EVALUATION */
- }
- goto fnend;
- }
- if (cx == FN_XLATE) { /* f_cvtcset() */
- #ifdef NOFRILLS
- ckstrncpy(fnval,bp[0],FNVALL);
- #else
- #ifndef NOUNICODE
- _PROTOTYP( char * cvtstring, (char *, int, int) );
- char * string, * cset1, * cset2;
- int id1, id2;
- #endif /* NOUNICODE */
- fnval[0] = NUL;
- #ifdef NOUNICODE
- ckstrncpy(fnval,bp[0],FNVALL);
- #else
- string = bp[0] ? bp[0] : ""; /* String to convert */
- if (!*string) goto fnend; /* It's empty */
- cset1 = bp[1] ? bp[1] : "ascii"; /* Current charset of string */
- cset2 = bp[2] ? bp[2] : "ascii"; /* Charset to convert to */
- id1 = lookup(fcstab,cset1,nfilc,NULL); /* Lookup 'from' set */
- if (id1 < 0) {
- failed = 1;
- ckmakmsg(fnval,FNVALL,"<ERROR:UNKNOWN_CHARSET:\\f",fn,"()>",NULL);
- goto fnend;
- }
- id2 = lookup(fcstab,cset2,nfilc,NULL); /* Lookup 'to' set */
- if (id2 < 0) {
- failed = 1;
- ckmakmsg(fnval,FNVALL,"<ERROR:UNKNOWN_CHARSET:\\f",fn,"()>",NULL);
- goto fnend;
- }
- string = cvtstring(string,id1,id2);
- ckstrncpy(fnval,string,FNVALL);
- #endif /* NOUNICODE */
- #endif /* NOFRILLS */
- goto fnend;
- }
- /* Decode strings containing hex escapes */
- if (cx == FN_UNPCT) { /* \fdecodehex() */
- char *s1, *s2;
- char *prefix; /* Can be 1 or 2 chars */
- char buf[3];
- int n = 0, k;
- p = fnval;
- *p = NUL;
- if (argn < 1) goto fnend; /* Empty string */
- s1 = bp[0] ? bp[0] : ""; /* Original string */
- prefix = bp[1] ? bp[1] : "%%"; /* Hex byte prefix */
- n = (int)strlen(prefix); /* Length of prefix */
- if (n < 1 || n > 2) { /* must be 1 or 2 */
- ckmakmsg(fnval,FNVALL,
- "<ERROR:INVALID_HEX_PREFIX:\\f",fn,"()>",NULL);
- goto xunpct;
- }
- while (*s1) {
- if (!ckstrcmp(s1,prefix,n,0)) { /* Case-independent */
- if (!*(s1+n)) {
- ckmakmsg(fnval,FNVALL,
- "<ERROR:INCOMPLETE_SEQUENCE:\\f",fn,"()>",NULL);
- goto xunpct;
- }
- buf[0] = *(s1+n); /* First hex character */
- buf[1] = *(s1+n+1); /* Second hex character */
- buf[2] = NUL;
- if ((k = ckhexbytetoint((char *)buf)) > -1) {
- *p++ = (char) k; /* Deposit decoded result */
- s1 += 2+n; /* and advance the source pointer */
- } else { /* Fail on conversion error */
- ckmakmsg(fnval,FNVALL,
- "<ERROR:NON_HEX_CHARS:\\f",fn,"()>",NULL);
- goto xunpct;
- }
- } else { /* Not a hex escape sequence */
- *p++ = *s1++; /* Just copy the character */
- }
- }
- *p = NUL; /* Terminate the result string */
- failed = 0; /* Say we didn't fail */
- p = fnval; /* Set up result pointer */
- goto fnend; /* and finish */
- xunpct: /* Error exit */
- p = fnval;
- failed = 1;
- goto fnend;
- }
- /* Check a string for encoding family */
- if (cx == FN_STRINGT) { /* \fstringtype() */
- p = "UNK";
- switch (scanstring(bp[0])) {
- case FT_7BIT: p = "7BIT"; break;
- case FT_8BIT: p = "8BIT"; break;
- case FT_UTF8: p = "UTF8"; break;
- case FT_UCS2: p = "UCS2"; break;
- case FT_TEXT: p = "TEXT"; break;
- case FT_BIN: p = "BINARY"; break;
- }
- ckstrncpy(fnval,p,FNVALL);
- p = fnval;
- goto fnend;
- }
- /* String compare s1, s2, [ case ], [ start ] , [ len ] */
- if (cx == FN_STRCMP) {
- int docase = 0; /* Case matters or not */
- int start = 0; /* Start of substring */
- int len = -1; /* Length of substring to compare */
- int x; char * s1, * s2; /* workers */
- p = "0"; /* Return value */
- if (argn == 0) { /* Two null strings are equal */
- ckstrncpy(fnval,p,FNVALL);
- p = fnval;
- goto fnend;
- }
- if (argn == 1) { /* Non-null string > null string */
- p = "1";
- ckstrncpy(fnval,p,FNVALL);
- p = fnval;
- goto fnend;
- }
- if (argn > 2) {
- s = *(bp[2]) ? evalx(bp[2]) : "0"; /* 0 = caseless */
- if (chknum(s)) docase = atoi(s);
- if (argn > 3) {
- s = *(bp[3]) ? evalx(bp[3]) : "1"; /* start is 1-based */
- if (chknum(s)) start = atoi(s);
- if (argn > 4) {
- s = *(bp[4]) ? evalx(bp[4]) : "-1"; /* -1 = whole thing */
- if (chknum(s)) len = atoi(s);
- }
- }
- }
- if (start > 0) start--; /* start is 0-based internally */
- s1 = bp[0]; /* Get length of first arg */
- x = (int)strlen(s1);
- if (x > start) /* Point to start position of s1 */
- s1 += start;
- else
- s1 = "";
- s2 = bp[1]; /* Get length of second arg */
- x = (int)strlen(s2);
- if (x > start) /* Point to start position of s2 */
- s2 += start;
- else
- s2 = "";
- x = ckstrcmp(s,s2,len,docase);
- p = ckitoa(x);
- ckstrncpy(fnval,p,FNVALL);
- p = fnval;
- goto fnend;
- }
- #ifdef HAVE_LOCALE
- /* \fdayname() - Returns locale-dependent day name string - 2013/07/23 */
- if (cx == FN_DAYNAME) {
- _PROTOTYP( char * locale_dayname, (int, int) );
- char *s1, *s2;
- char buf[3];
- int fc = 0, day = 999;
- s1 = bp[0];
- s2 = bp[1];
- p = fnval;
- *p = NUL;
- if (!s1) s1 = "";
- if (!*s1) {
- s1 = ckdate();
- } else if (rdigits(s1) && (int)strlen(s1) < 8) {
- day = atoi(s1);
- if (day == 0) day = 7; /* In case \v(nday) used as arg */
- if (day < 1 || day > 7) {
- ckmakmsg(fnval,FNVALL,"<ERROR:BAD_DAYNUM\\f",fn,"()>",NULL);
- goto fnend;
- }
- day--; /* Adjust to zero-based */
- } else if (!(s1 = cmcvtdate(s1,1))) {
- ckmakmsg(fnval,FNVALL,"<ERROR:BAD_DATE\\f",fn,"()>",NULL);
- goto fnend;
- }
- if (!s2) s2 = ""; /* Parse function code */
- if (!*s2) {
- fc = 0;
- } else if (rdigits(s2)) {
- fc = atoi(s2);
- } else {
- failed = 1;
- ckmakmsg(fnval,FNVALL,"<ERROR:FUNCTION_CODE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- if (day > 6) { /* Day number was not given */
- day = (mjd(s1) % 7) + 2; /* Get day number */
- if (day > 6) day -= 7; /* Adjust to 0=Sunday */
- }
- s1 = locale_dayname(day,fc); /* Get locale-based day name */
- if (!s1) {
- failed = 1;
- ckmakmsg(fnval,FNVALL,"<ERROR:NO_RESULT:\\f",fn,"()>",NULL);
- goto fnend;
- }
- ckstrncpy(fnval,s1,FNVALL);
- goto fnend;
- }
- /* \fmonthname() - Returns locale-dependent month name string 2013/07/24 */
- if (cx == FN_MONNAME) {
- _PROTOTYP( char * locale_monthname, (int, int) );
- char *s1, *s2;
- char buf[3];
- int fc = 0, month = 999;
- s1 = bp[0];
- s2 = bp[1];
- p = fnval;
- *p = NUL;
- if (!s1) s1 = "";
- if (!*s1) {
- s1 = ckdate();
- } else if (rdigits(s1) && (int)strlen(s1) < 8) {
- month = atoi(s1);
- if (month == 0) month = 12;
- if (month < 1 || month > 12) {
- ckmakmsg(fnval,FNVALL,"<ERROR:BAD_MONTHNUM:\\f",fn,"()>",NULL);
- goto fnend;
- }
- month--; /* Adjust to zero-based */
- } else if (!(s1 = cmcvtdate(s1,1))) {
- ckmakmsg(fnval,FNVALL,"<ERROR:BAD_DATE\\f",fn,"()>",NULL);
- goto fnend;
- }
- if (month > 12) {
- char mn[3];
- mn[0] = s1[4];
- mn[1] = s1[5];
- mn[2] = NUL;
- month = atoi((char *)mn) - 1;
- }
- if (!s2) s2 = ""; /* Parse function code */
- if (!*s2) {
- fc = 0;
- } else if (rdigits(s2)) {
- fc = atoi(s2);
- } else {
- failed = 1;
- ckmakmsg(fnval,FNVALL,"<ERROR:FUNCTION_CODE:\\f",fn,"()>",NULL);
- goto fnend;
- }
- s1 = locale_monthname(month,fc); /* Get locale-based month name */
- if (!s1) {
- failed = 1;
- ckmakmsg(fnval,FNVALL,"<ERROR:NO_RESULT:\\f",fn,"()>",NULL);
- goto fnend;
- }
- ckstrncpy(fnval,s1,FNVALL);
- goto fnend;
- }
- #endif /* HAVE_LOCALE */
- /* Note: when adding new functions remember to update dohfunc in ckuus2.c. */
- failed = 1;
- if (fndiags)
- ckmakmsg(fnval,FNVALL,"<ERROR:UNKNOWN_FUNCTION:\\f",fn,"()>",NULL);
- fnend:
- /* Free temporary storage for aguments */
- for (k = 0; k < argn; k++) if (bp[k]) free(bp[k]);
- fndepth--;
- if (failed) { /* Handle failure */
- debug(F111,"fnend",fnval,errno);
- if (!p) p = "";
- if (p[0]) {
- /* In case this wasn't caught above... */
- k = strlen(p);
- if (p[0] != '<' && p[k-1] != '>') {
- ckmakmsg(fnval,FNVALL,"<ERROR:BAD_ARG:\\f",fn,"()>",NULL);
- p = fnval;
- }
- } else {
- ckmakmsg(fnval,FNVALL,"<ERROR:UNKNOWN:\\f",fn,"()>",NULL);
- p = fnval;
- }
- if (fnerror) /* SET FUNCTION ERROR ON */
- fnsuccess = 0; /* Make command fail (see ckuus5.c) */
- debug(F111,"fneval failed",p,fnsuccess);
- if (fndiags) /* SET FUNCTION DIAGNOSTICS ON */
- printf("?%s\n",p); /* Print error message now. */
- else
- return(""); /* Return nothing. */
- }
- return(p);
- }
- #endif /* NOSPL */
- static char ckpidbuf[32] = "????";
- #ifdef VMS
- _PROTOTYP(long zgpid,(void));
- #endif /* VMS */
- char *
- ckgetpid() { /* Return pid as string */
- #ifdef CK_PID
- #ifdef OS2
- #define getpid _getpid
- unsigned long zz;
- #else
- long zz;
- #endif /* OS2 */
- #ifdef VMS
- zz = zgpid();
- #else
- zz = getpid();
- #endif /* VMS */
- sprintf(ckpidbuf,"%ld",zz); /* SAFE */
- #endif /* CK_PID */
- return((char *)ckpidbuf);
- }
- #ifndef NOSPL
- #define EMBUFLEN 128 /* Error message buffer length */
- static char embuf[EMBUFLEN+1];
- char * /* Evaluate builtin variable */
- nvlook(s) char *s; {
- int x, y, cx;
- long z;
- char *p;
- #ifndef NODIAL
- MDMINF * m;
- #endif /* NODIAL */
- #ifndef NOKVERBS /* Keyboard macro material */
- extern int keymac, keymacx;
- #endif /* NOKVERBS */
- #ifdef CK_LOGIN
- extern int isguest;
- #endif /* CK_LOGIN */
- if (!s) s = "";
- x = strlen(s);
- if (fndiags) { /* FUNCTION DIAGNOSTIC ON */
- if (x + 32 < EMBUFLEN)
- sprintf(embuf,"<ERROR:NO_SUCH_VARIABLE:\\v(%s)>",s); /* SAFE */
- else
- sprintf(embuf,"<ERROR:NO_SUCH_VARIABLE>"); /* SAFE */
- } else /* FUNCTION DIAGNOSTIC OFF */
- embuf[0] = NUL;
- x = VVBUFL;
- p = vvbuf;
- if (zzstring(s,&p,&x) < 0) { /* e.g. for \v(\%a) */
- y = -1;
- } else {
- s = vvbuf;
- y = lookup(vartab,s,nvars,&x);
- }
- cx = y; /* y is too generic */
- #ifndef NODIAL
- m = (mdmtyp > 0) ? modemp[mdmtyp] : NULL; /* For \v(m_xxx) variables */
- #endif /* NODIAL */
- debug(F101,"nvlook y","",y);
- switch (y) {
- case VN_ARGC: /* ARGC */
- sprintf(vvbuf,"%d",maclvl < 0 ? topargc : macargc[maclvl]); /* SAFE */
- return(vvbuf);
- case VN_ARGS: /* ARGS */
- sprintf(vvbuf,"%d",xargs); /* SAFE */
- return(vvbuf);
- case VN_COUN: /* COUNT */
- sprintf(vvbuf,"%d",count[cmdlvl]); /* SAFE */
- return(vvbuf);
- case VN_DATE: /* DATE */
- ztime(&p); /* Get "asctime" string */
- if (p == NULL || *p == NUL) return(NULL);
- vvbuf[0] = p[8]; /* dd */
- vvbuf[1] = p[9];
- vvbuf[2] = SP;
- vvbuf[3] = p[4]; /* mmm */
- vvbuf[4] = p[5];
- vvbuf[5] = p[6];
- vvbuf[6] = SP;
- for (x = 20; x < 24; x++) /* yyyy */
- vvbuf[x - 13] = p[x];
- vvbuf[11] = NUL;
- return(vvbuf);
- case VN_NDAT: /* Numeric date */
- ckstrncpy(vvbuf,zzndate(),VVBUFL);
- return(vvbuf);
- case VN_DIRE: /* DIRECTORY */
- s = zgtdir(); /* Get current directory */
- if (!s)
- #ifdef UNIXOROSK
- s = "./";
- #else
- #ifdef VMS
- s = "[]";
- #else
- s = "";
- #endif /* VMS */
- #endif /* UNIXOROSK */
- ckstrncpy(vvbuf,s,VVBUFL);
- s = vvbuf;
- #ifdef UNIXOROSK
- x = strlen(s);
- if (x < VVBUFL - 1) {
- if (s[x-1] != '/') {
- s[x] = '/';
- s[x+1] = NUL;
- }
- }
- #endif /* UNIXOROSK */
- return(s);
- case VN_FILE: /* filespec */
- return(fspec);
- case VN_HOST: /* host name */
- if (*myhost) { /* If known */
- return(myhost); /* return it. */
- } else { /* Otherwise */
- ckstrncpy(vvbuf,"unknown",VVBUFL); /* just say "unknown" */
- return(vvbuf);
- }
- case VN_SYST: /* System type */
- #ifdef UNIX
- ckstrncpy(vvbuf,"UNIX",VVBUFL);
- #else
- #ifdef VMS
- ckstrncpy(vvbuf,"VMS",VVBUFL);
- #else
- #ifdef OSK
- ckstrncpy(vvbuf,"OS9/68K",VVBUFL);
- #else
- #ifdef AMIGA
- ckstrncpy(vvbuf,"Amiga",VVBUFL);
- #else
- #ifdef MAC
- ckstrncpy(vvbuf,"Macintosh",VVBUFL);
- #else
- #ifdef OS2
- #ifdef NT
- ckstrncpy(vvbuf,"WIN32",VVBUFL) ;
- #else /* NT */
- ckstrncpy(vvbuf,"OS/2",VVBUFL);
- #endif /* NT */
- #else
- #ifdef datageneral
- ckstrncpy(vvbuf,"AOS/VS",VVBUFL);
- #else
- #ifdef GEMDOS
- ckstrncpy(vvbuf,"Atari_ST",VVBUFL);
- #else
- #ifdef STRATUS
- ckstrncpy(vvbuf,"Stratus_VOS",VVBUFL);
- #else
- ckstrncpy(vvbuf,"unknown",VVBUFL);
- #endif /* STRATUS */
- #endif /* GEMDOS */
- #endif /* datageneral */
- #endif /* OS2 */
- #endif /* MAC */
- #endif /* AMIGA */
- #endif /* OSK */
- #endif /* VMS */
- #endif /* UNIX */
- return(vvbuf);
- case VN_SYSV: /* System herald */
- #ifdef IKSD
- #ifdef CK_LOGIN
- if (inserver && isguest)
- return("");
- #endif /* CK_LOGIN */
- #endif /* IKSD */
- for (x = y = 0; x < VVBUFL; x++) {
- if (ckxsys[x] == SP && y == 0) continue;
- vvbuf[y++] = (char) ((ckxsys[x] == SP) ? '_' : ckxsys[x]);
- }
- vvbuf[y] = NUL;
- return(vvbuf);
- } /* Break up long switch statements... */
- switch(y) {
- case VN_TIME: /* TIME. Assumes that ztime returns */
- ztime(&p); /* "Thu Feb 8 12:00:00 1990" */
- if (p == NULL || *p == NUL) /* like asctime()! */
- return("");
- for (x = 11; x < 19; x++) /* copy hh:mm:ss */
- vvbuf[x - 11] = p[x]; /* to vvbuf */
- vvbuf[8] = NUL; /* terminate */
- return(vvbuf); /* and return it */
- case VN_NTIM: /* Numeric time */
- ztime(&p); /* "Thu Feb 8 12:00:00 1990" */
- if (p == NULL || *p == NUL) /* like asctime()! */
- return(NULL);
- z = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
- sprintf(vvbuf,"%ld",z); /* SAFE */
- return(vvbuf);
- #ifdef CK_TTYFD
- case VN_TTYF: /* TTY file descriptor */
- sprintf(vvbuf,"%d", /* SAFE */
- #ifdef VMS
- vmsttyfd()
- #else
- ttyfd
- #endif /* VMS */
- );
- return(vvbuf);
- #endif /* CK_TTYFD */
- case VN_VERS: /* Numeric Kermit version number */
- sprintf(vvbuf,"%ld",vernum); /* SAFE */
- return(vvbuf);
- case VN_XVNUM: /* Product-specific version number */
- sprintf(vvbuf,"%ld",xvernum); /* SAFE */
- return(vvbuf);
- case VN_HOME: /* Home directory */
- return(homepath());
- case VN_IBUF: /* INPUT buffer */
- return((char *)inpbuf);
- case VN_ICHR: /* INPUT character */
- inchar[1] = NUL;
- return((char *)inchar);
- case VN_ICNT: /* INPUT character count */
- sprintf(vvbuf,"%d",incount); /* SAFE */
- return(vvbuf);
- case VN_SPEE: { /* Transmission SPEED */
- long t;
- t = ttgspd();
- if (t < 0L)
- sprintf(vvbuf,"unknown"); /* SAFE */
- else
- sprintf(vvbuf,"%ld",t); /* SAFE */
- return(vvbuf);
- }
- case VN_SUCC: /* SUCCESS flag */
- /* Note inverted sense */
- sprintf(vvbuf,"%d",(success == 0) ? 1 : 0); /* SAFE */
- return(vvbuf);
- case VN_LINE: { /* LINE */
- #ifdef DEBUG
- if (deblog) {
- debug(F111,"\\v(line) local",ttname,local);
- debug(F111,"\\v(line) inserver","",inserver);
- #ifdef TNCODE
- debug(F111,"\\v(line) tcp_incoming","",tcp_incoming);
- #endif /* TNCODE */
- #ifdef CK_TAPI
- debug(F111,"\\v(line) tttapi","",tttapi);
- #endif /* CK_TAPI */
- }
- #endif /* DEBUG */
- #ifdef CK_TAPI
- if (tttapi) { /* If I have made a TAPI connection */
- int i; /* return the TAPI device name */
- for (i = 0; i < ntapiline; i++) {
- if (!strcmp(ttname,tapilinetab[i].kwd)) {
- p = _tapilinetab[i].kwd;
- return(p);
- }
- }
- }
- #endif /* CK_TAPI */
- #ifndef NOXFER
- if (inserver /* If I am a TCP server */
- #ifdef TNCODE
- || tcp_incoming
- #endif /* TNCODE */
- )
- #ifdef TCPSOCKET
- p = ckgetpeer(); /* return peer name */
- else
- #endif /* TCPSOCKET */
- #endif /* NOXFER */
- if (local) /* Otherwise if in local mode */
- p = (char *) ttname; /* return SET LINE / SET HOST name */
- else /* Otherwise */
- p = ""; /* return empty string */
- if (!p) /* In case ckgetpeer() returns */
- p = ""; /* null pointer... */
- debug(F110,"\\v(line) p",p,0);
- if (!*p)
- p = (char *) ttname;
- return(p);
- }
- case VN_PROG: /* Program name */
- return("C-Kermit");
- } /* Break up long switch statements... */
- switch(y) {
- case VN_RET: /* Value of most recent RETURN */
- debug(F111,"\\v(return)",mrval[maclvl+1],maclvl+1);
- p = mrval[maclvl+1];
- if (p == NULL) p = "";
- return(p);
- case VN_FFC: /* Size of most recent file */
- sprintf(vvbuf, "%s", ckfstoa(ffc)); /* SAFE */
- return(vvbuf);
- case VN_TFC: /* Size of most recent file group */
- sprintf(vvbuf, "%s", ckfstoa(tfc)); /* SAFE */
- return(vvbuf);
- case VN_CPU: /* CPU type */
- #ifdef IKSD
- #ifdef CK_LOGIN
- if (inserver && isguest)
- return("");
- #endif /* CK_LOGIN */
- #endif /* IKSD */
- #ifdef OS2
- {
- char * getcpu(void) ;
- return getcpu();
- }
- #else /* OS2 */
- #ifdef CKCPU
- return(CKCPU); /* Traditionally, compile-time value */
- #else
- #ifdef CK_UTSNAME
- { /* But if none, try runtime value */
- extern char unm_mch[];
- return((char *)unm_mch);
- }
- #else
- p = getenv("HOSTTYPE"); /* 20091116 */
- if (p) if (*p) return(p);
- return("unknown");
- #endif /* CK_UTSNAME */
- #endif /* CKCPU */
- #endif /* OS2 */
- case VN_CMDL: /* Command level */
- sprintf(vvbuf, "%d", cmdlvl); /* SAFE */
- return(vvbuf);
- case VN_DAY: /* Current day of the week */
- ztime(&p); /* three-letter abbreviation */
- if (p != NULL && *p != NUL) /* ztime() succeeded. */
- ckstrncpy(vvbuf,p,4);
- else
- vvbuf[0] = NUL; /* ztime() failed. */
- return(vvbuf); /* Return what we got. */
- case VN_NDAY: { /* Numeric day of week */
- long k;
- z = mjd(zzndate()); /* Get modified Julian date */
- k = (((int)(z % 7L)) + 3) % 7; /* Get day number */
- sprintf(vvbuf,"%ld",k); /* SAFE */
- return(vvbuf);
- case VN_MONTH:
- ztime(&p); /* three-letter abbreviation */
- if (p != NULL && *p != NUL) /* ztime() succeeded. */
- ckstrncpy(vvbuf,p+4,5);
- else
- vvbuf[0] = NUL; /* ztime() failed. */
- return(vvbuf); /* Return what we got. */
- case VN_NMONTH: { /* Numeric month (1-12) */
- int x;
- ztime(&p); /* asctime three-letter abbreviation */
- for (x = 0; x < 12; x++)
- if (!strncmp(p+4,months[x],3)) break;
- if (x == 12) {
- vvbuf[0] = '?';
- vvbuf[1] = '?';
- } else {
- x++;
- vvbuf[0] = (char) ((x < 10) ? '0' : '1');
- vvbuf[1] = (char) ((x % 10) + 48);
- }
- vvbuf[2] = NUL;
- return(vvbuf); /* Return what we got. */
- }
- case VN_YEAR: /* Current year */
- ztime(&p);
- if (p != NULL && *p != NUL) /* ztime() succeeded. */
- ckstrncpy(vvbuf,p+20,5);
- else
- vvbuf[0] = NUL; /* ztime() failed. */
- return(vvbuf); /* Return what we got. */
- }
- case VN_LCL: /* Local (vs remote) mode */
- ckstrncpy(vvbuf, local ? "1" : "0",VVBUFL);
- return(vvbuf);
- case VN_CMDS: /* Command source */
- if (cmdstk[cmdlvl].src == CMD_KB)
- ckstrncpy(vvbuf,"prompt",VVBUFL);
- else if (cmdstk[cmdlvl].src == CMD_MD)
- ckstrncpy(vvbuf,"macro",VVBUFL);
- else if (cmdstk[cmdlvl].src == CMD_TF)
- ckstrncpy(vvbuf,"file",VVBUFL);
- else
- ckstrncpy(vvbuf,"unknown",VVBUFL);
- return(vvbuf);
- case VN_CMDF: /* Current command file name */
- #ifdef COMMENT /* (see comments above) */
- if (tfnam[tlevel]) { /* (near dblbs declaration) */
- dblbs(tfnam[tlevel],vvbuf,VVBUFL);
- return(vvbuf);
- } else return("");
- #else
- if (tlevel < 0)
- return("");
- else
- return(tfnam[tlevel] ? tfnam[tlevel] : "");
- #endif /* COMMENT */
- case VN_MAC: /* Current macro name */
- return((maclvl > -1) ? m_arg[maclvl][0] : "");
- case VN_EXIT:
- sprintf(vvbuf,"%d",xitsta); /* SAFE */
- return(vvbuf);
- } /* Break up long switch statements... */
- switch(y) {
- case VN_PRTY: { /* Parity */
- char *ss;
- switch (parity) {
- case 0: ss = "none"; break;
- case 'e': ss = "even"; break;
- case 'm': ss = "mark"; break;
- case 'o': ss = "odd"; break;
- case 's': ss = "space"; break;
- default: ss = "unknown"; break;
- }
- ckstrncpy(vvbuf,ss,VVBUFL);
- return(vvbuf);
- }
- case VN_DIAL:
- sprintf(vvbuf,"%d", /* SAFE */
- #ifndef NODIAL
- dialsta
- #else
- -1
- #endif /* NODIAL */
- );
- return(vvbuf);
- #ifndef NODIAL
- case VN_DMSG:
- #ifdef BIGBUFOK
- ckstrncpy(vvbuf,
- ((dialsta < 0) ? "(none)" : dialmsg[dialsta]),
- VVBUFL); /* Safe if src == NULL.. mdw 20140213 */
- #endif /* BIGBUFOK */
- return((char *)vvbuf);
- #endif /* NODIAL */
- #ifdef OS2
- case VN_KEYB:
- ckstrncpy(vvbuf,conkbg(),VVBUFL);
- return(vvbuf);
- case VN_SELCT: {
- #ifndef NOLOCAL
- const char * selection = GetSelection();
- return( (char *) (selection ? selection : "" )) ;
- #else
- return("");
- #endif /* NOLOCAL */
- }
- #endif /* OS2 */
- #ifndef NOXFER
- case VN_CPS:
- sprintf(vvbuf,"%ld",tfcps); /* SAFE */
- return(vvbuf);
- #endif /* NOXFER */
- case VN_MODE: /* File transfer mode */
- switch (binary) {
- case XYFT_T: ckstrncpy(vvbuf,"text",VVBUFL); break;
- case XYFT_B:
- case XYFT_U: ckstrncpy(vvbuf,"binary",VVBUFL); break;
- case XYFT_I: ckstrncpy(vvbuf,"image",VVBUFL); break;
- case XYFT_L: ckstrncpy(vvbuf,"labeled",VVBUFL); break;
- case XYFT_M: ckstrncpy(vvbuf,"macbinary",VVBUFL); break;
- default: ckstrncpy(vvbuf,"unknown",VVBUFL);
- }
- return(vvbuf);
- #ifdef CK_REXX
- case VN_REXX:
- return(rexxbuf);
- #endif /* CK_REXX */
- case VN_NEWL: /* System newline char or sequence */
- #ifdef UNIX
- ckstrncpy(vvbuf,"\n",VVBUFL);
- #else
- #ifdef datageneral
- ckstrncpy(vvbuf,"\n",VVBUFL);
- #else
- #ifdef OSK
- ckstrncpy(vvbuf,"\15",VVBUFL); /* Remember, these are octal... */
- #else
- #ifdef MAC
- ckstrncpy(vvbuf,"\15",VVBUFL);
- #else
- #ifdef OS2
- ckstrncpy(vvbuf,"\15\12",VVBUFL);
- #else
- #ifdef STRATUS
- ckstrncpy(vvbuf,"\n",VVBUFL);
- #else
- #ifdef VMS
- ckstrncpy(vvbuf,"\15\12",VVBUFL);
- #else
- #ifdef AMIGA
- ckstrncpy(vvbuf,"\n",VVBUFL);
- #else
- #ifdef GEMDOS
- ckstrncpy(vvbuf,"\n",VVBUFL);
- #else
- ckstrncpy(vvbuf,"\n",VVBUFL);
- #endif /* GEMDOS */
- #endif /* AMIGA */
- #endif /* VMS */
- #endif /* STRATUS */
- #endif /* OS2 */
- #endif /* MAC */
- #endif /* OSK */
- #endif /* datageneral */
- #endif /* UNIX */
- return(vvbuf);
- case VN_ROWS: /* ROWS */
- case VN_COLS: /* COLS */
- ckstrncpy(vvbuf,(cx == VN_ROWS) ? "24" : "80",VVBUFL); /* Default */
- #ifdef CK_TTGWSIZ
- #ifdef OS2
- if (tt_cols[VTERM] < 0 || tt_rows[VTERM] < 0)
- ttgwsiz();
- sprintf(vvbuf,"%d", /* SAFE */
- (cx == VN_ROWS) ? tt_rows[VTERM] : tt_cols[VTERM]);
- #else /* OS2 */
- if (ttgwsiz() > 0) /* Get window size */
- if (tt_cols > 0 && tt_rows > 0) /* sets tt_rows, tt_cols */
- sprintf(vvbuf,"%d", /* SAFE */
- (cx == VN_ROWS) ? tt_rows : tt_cols);
- #endif /* OS2 */
- #endif /* CK_TTGWSIZ */
- return(vvbuf);
- case VN_TTYP:
- #ifdef NOTERM
- ckstrncpy(vvbuf,"unknown",VVBUFL);
- #else
- #ifdef OS2
- sprintf(vvbuf, "%s", /* SAFE */
- (tt_type >= 0 && tt_type <= max_tt) ?
- tt_info[tt_type].x_name :
- "unknown"
- );
- #else
- #ifdef MAC
- ckstrncpy(vvbuf,"vt320",VVBUFL);
- #else
- p = getenv("TERM");
- ckstrncpy(vvbuf,p ? p : "unknown",VVBUFL+1);
- #endif /* MAC */
- #endif /* OS2 */
- #endif /* NOTERM */
- return(vvbuf);
- case VN_MINP: /* MINPUT */
- sprintf(vvbuf, "%d", m_found); /* SAFE */
- return(vvbuf);
- } /* Break up long switch statements... */
- switch(y) {
- case VN_CONN: /* CONNECTION */
- if (!local) {
- ckstrncpy(vvbuf,"remote",VVBUFL);
- } else {
- if (!network)
- ckstrncpy(vvbuf,"serial",VVBUFL);
- #ifdef TCPSOCKET
- else if (nettype == NET_TCPB || nettype == NET_TCPA) {
- if (ttnproto == NP_TELNET)
- ckstrncpy(vvbuf,"tcp/ip_telnet",VVBUFL);
- #ifdef CK_SSL
- else if (ttnproto == NP_SSL || ttnproto == NP_SSL_RAW)
- ckstrncpy(vvbuf,"tcp/ip_ssl",VVBUFL);
- else if (ttnproto == NP_TLS || ttnproto == NP_SSL_RAW)
- ckstrncpy(vvbuf,"tcp/ip_tls",VVBUFL);
- #endif /* CK_SSL */
- else
- ckstrncpy(vvbuf,"tcp/ip",VVBUFL);
- }
- #endif /* TCPSOCKET */
- #ifdef SSHBUILTIN
- else if (nettype == NET_SSH)
- ckstrncpy(vvbuf,"tcp/ip_ssh",VVBUFL);
- #endif /* SSHBUILTIN */
- #ifdef ANYX25
- else if (nettype == NET_SX25 ||
- nettype == NET_VX25 ||
- nettype == NET_IX25
- )
- ckstrncpy(vvbuf,"x.25",VVBUFL);
- #endif /* ANYX25 */
- #ifdef DECNET
- else if (nettype == NET_DEC) {
- if (ttnproto == NP_LAT)
- ckstrncpy(vvbuf,"decnet_lat",VVBUFL);
- else if ( ttnproto == NP_CTERM )
- ckstrncpy(vvbuf,"decnet_cterm",VVBUFL);
- else
- ckstrncpy(vvbuf,"decnet",VVBUFL);
- }
- #endif /* DECNET */
- #ifdef SUPERLAT
- else if (nettype == NET_SLAT)
- ckstrncpy(vvbuf,"superlat",VVBUFL);
- #endif /* SUPERLAT */
- #ifdef NETFILE
- else if (nettype == NET_FILE)
- ckstrncpy(vvbuf,"local_file",VVBUFL);
- #endif /* NETFILE */
- #ifdef NETCMD
- else if (nettype == NET_CMD)
- ckstrncpy(vvbuf,"pipe",VVBUFL);
- #endif /* NETCMD */
- #ifdef NETPTY
- else if (nettype == NET_PTY)
- ckstrncpy(vvbuf,"pseudoterminal",VVBUFL);
- #endif /* NETPTY */
- #ifdef NETDLL
- else if (nettype == NET_DLL)
- ckstrncpy(vvbuf,"dynamic_link_library",VVBUFL);
- #endif /* NETDLL */
- #ifdef NPIPE
- else if (nettype == NET_PIPE)
- ckstrncpy(vvbuf,"named_pipe",VVBUFL);
- #endif /* NPIPE */
- #ifdef CK_NETBIOS
- else if (nettype == NET_BIOS)
- ckstrncpy(vvbuf,"netbios",VVBUFL);
- #endif /* CK_NETBIOS */
- else
- ckstrncpy(vvbuf,"unknown",VVBUFL);
- }
- return(vvbuf);
- #ifndef NOXFER
- case VN_SYSI: /* System ID, Kermit code */
- return((char *)cksysid);
- #endif /* NOXFER */
- #ifdef OS2
- case VN_SPA: {
- unsigned long space = zdskspace(0);
- if (space > 0 && space < 1024)
- sprintf(vvbuf,"-1");
- else
- sprintf(vvbuf,"%lu",space); /* SAFE */
- return(vvbuf);
- }
- #endif /* OS2 */
- #ifndef NOXFER
- case VN_QUE: {
- extern char querybuf[];
- return(querybuf);
- }
- #endif /* NOXFER */
- #ifndef NOCSETS
- case VN_CSET:
- #ifdef OS2
- sprintf(vvbuf,"cp%d",os2getcp()); /* SAFE */
- #else
- ckstrncpy(vvbuf,fcsinfo[fcharset].keyword,VVBUFL+1);
- #endif /* OS2 */
- return(vvbuf);
- #endif /* NOCSETS */
- #ifdef OS2
- case VN_EXEDIR:
- return(exedir);
- case VN_STAR:
- return(startupdir);
- #else
- case VN_EXEDIR:
- return(exedir ? exedir : "");
- #ifdef VMSORUNIX
- case VN_STAR:
- return(startupdir);
- #endif /* VMSORUNIX */
- #endif /* OS2 */
- case VN_INI:
- return(inidir);
- case VN_MDM:
- return(gmdmtyp());
- case VN_EVAL:
- return(evalbuf);
- #ifndef NODIAL
- case VN_D_CC: /* DIAL COUNTRY-CODE */
- return(diallcc ? diallcc : "");
- case VN_D_AC: /* DIAL AREA-CODE */
- return(diallac ? diallac : "");
- case VN_D_IP: /* DIAL INTERNATIONAL-PREFIX */
- return(dialixp ? dialixp : "");
- case VN_D_LP: /* DIAL LD-PREFIX */
- return(dialldp ? dialldp : "");
- case VN_D_LCP: /* DIAL LOCAL-PREFIX */
- return(diallcp ? diallcp : "");
- case VN_D_PXX: /* DIAL PBX-EXCHANGE that matched */
- return(matchpxx ? matchpxx : "");
- #else
- case VN_D_CC: /* DIAL COUNTRY-CODE */
- case VN_D_AC: /* DIAL AREA-CODE */
- case VN_D_IP: /* DIAL INTERNATIONAL-PREFIX */
- case VN_D_LP: /* DIAL LD-PREFIX */
- case VN_D_LCP: /* DIAL LOCAL-PREFIX */
- case VN_D_PXX: /* DIAL PBX-EXCHANGE */
- return("");
- #endif /* NODIAL */
- case VN_UID:
- #ifdef UNIX
- {
- #ifdef IKSD
- if (inserver)
- return((char *)uidbuf);
- else
- #endif /* IKSD */
- if (uidbuf[0])
- return((char *)uidbuf);
- else
- return(whoami());
- }
- #else
- return((char *)uidbuf);
- #endif /* UNIX */
- } /* Break up long switch statements... */
- switch(y) {
- case VN_PWD:
- #ifdef OS2
- if (activecmd == XXOUT || activecmd == XXLNOUT) {
- ckstrncpy(vvbuf,pwbuf,VVBUFL);
- ck_encrypt((char *)vvbuf);
- return((char *)vvbuf);
- } else
- #endif /* OS2 */
- return((char *)pwbuf);
- case VN_PRM:
- return((char *)prmbuf);
- case VN_PROTO:
- #ifdef NOXFER
- return("none");
- #else
- #ifdef CK_XYZ
- return(ptab[protocol].p_name);
- #else
- return("kermit");
- #endif /* CK_XYZ */
- #endif /* NOXFER */
- #ifndef NOXFER
- #ifdef CK_TMPDIR
- case VN_DLDIR:
- return(dldir ? dldir : "");
- #endif /* CK_TMPDIR */
- #endif /* NOXFER */
- #ifndef NODIAL
- case VN_M_INI: /* Modem init string */
- return(dialini ? dialini : (m ? m->wake_str : ""));
- case VN_M_DCM: /* Modem dial command */
- return(dialcmd ? dialcmd : (m ? m->dial_str : ""));
- case VN_M_DCO: /* Modem data compression on */
- return(dialdcon ? dialdcon : (m ? m->dc_on_str : ""));
- case VN_M_DCX: /* Modem data compression off */
- return(dialdcoff ? dialdcoff : (m ? m->dc_off_str : ""));
- case VN_M_ECO: /* Modem error correction on */
- return(dialecon ? dialecon : (m ? m->ec_on_str : ""));
- case VN_M_ECX: /* Modem error correction off */
- return(dialecoff ? dialecoff : (m ? m->ec_off_str : ""));
- case VN_M_AAO: /* Modem autoanswer on */
- return(dialaaon ? dialaaon : (m ? m->aa_on_str : ""));
- case VN_M_AAX: /* Modem autoanswer off */
- return(dialaaoff ? dialaaoff : (m ? m->aa_off_str : ""));
- case VN_M_HUP: /* Modem hangup command */
- return(dialhcmd ? dialhcmd : (m ? m->hup_str : ""));
- case VN_M_HWF: /* Modem hardware flow command */
- return(dialhwfc ? dialhwfc : (m ? m->hwfc_str : ""));
- case VN_M_SWF: /* Modem software flow command */
- return(dialswfc ? dialswfc : (m ? m->swfc_str : ""));
- case VN_M_NFC: /* Modem no flow-control command */
- return(dialnofc ? dialnofc : (m ? m->nofc_str : ""));
- case VN_M_PDM: /* Modem pulse dialing mode */
- return(dialpulse ? dialpulse : (m ? m->pulse : ""));
- case VN_M_TDM: /* Modem tone dialing mode */
- return(dialtone ? dialtone : (m ? m->tone : ""));
- case VN_M_NAM: /* Modem full name */
- return(dialname ? dialname : (m ? m->name : ""));
- #else
- case VN_M_INI: /* Modem init string */
- case VN_M_DCM: /* Modem dial command */
- case VN_M_DCO: /* Modem data compression on */
- case VN_M_DCX: /* Modem data compression off */
- case VN_M_ECO: /* Modem error correction on */
- case VN_M_ECX: /* Modem error correction off */
- case VN_M_AAO: /* Modem autoanswer on */
- case VN_M_AAX: /* Modem autoanswer off */
- case VN_M_HUP: /* Modem hangup command */
- case VN_M_HWF: /* Modem hardware flow command */
- case VN_M_SWF: /* Modem software flow command */
- case VN_M_NFC: /* Modem no flow-control command */
- case VN_M_PDM: /* Modem pulse dialing mode */
- case VN_M_TDM: /* Modem tone dialing mode */
- case VN_M_NAM:
- return("");
- #endif /* NODIAL */
- case VN_ISTAT: /* INPUT status */
- sprintf(vvbuf, "%d", instatus); /* SAFE */
- return(vvbuf);
- case VN_TEMP: /* Temporary directory */
- if (tempdir) { /* This is where SET TEMP-DIRECTORY */
- p = tempdir; /* puts it -- just use what's here */
- ckstrncpy(vvbuf,tempdir,VVBUFL);
- } else {
- char c;
- /*
- If tempdir was empty, we have to figure out what the temp directory should
- be here and then put the result where we should have found it in the first
- place. This is done by checking environment variables (or logical names
- in VMS, same thing from the API point of view), and if that fails using
- platform-specific conventions, like the /tmp directory in Unix.
- */
- #ifdef OS2
- #ifdef NT
- p = getenv("K95TMP");
- #else
- p = getenv("K2TMP");
- #endif /* NT */
- if ( !p )
- #endif /* OS2 */
- p = getenv("CK_TMP");
- if (!p) p = getenv("TMPDIR");
- if (!p) p = getenv("TEMP");
- if (!p) p = getenv("TMP");
- #ifdef OS2ORUNIX
- if (p) {
- int len = strlen(p);
- if (p[len-1] != '/'
- #ifdef OS2
- && p[len-1] != '\\'
- #endif /* OS2 */
- ) {
- ckstrncpy(vvbuf,p,VVBUFL);
- if (vvbuf[0]) ckstrncat(vvbuf,"/",CKMAXPATH);
- p = vvbuf;
- }
- }
- #endif /* OS2ORUNIX */
- if (!p) {
- #ifdef UNIX /* Systems that have a standard */
- p = "/tmp/"; /* temporary directory... */
- #else
- #ifdef datageneral
- p = ":TMP:";
- #else
- p = "";
- #endif /* datageneral */
- #endif /* UNIX */
- ckstrncpy(vvbuf,p,VVBUFL);
- p = vvbuf;
- }
- /*
- If the result does not end with a directory separator, tack on the
- appropriate one. This way scripts can be written in a platform-independent
- way, without having to hardwire a particlar OS's directory separator;
- e.g. \v(tmpfile)foo.bar instead of \v(tmpfile)/foo.bar, which would not be
- portable to (say) VMS. In a better world the following code would be in the
- platform-specific modules, ck?fio.c, but it's too late to go back and redo
- them all. Note: Windows and OS/2 use backslash (\) as the directory
- separate in the user interface, but accept slash(/) in their APIs.
- */
- while (*p) { /* For Windows and OS/2 */
- #ifdef OS2 /* flip the backslash */
- if (*p == '\\') *p = '/';
- #endif /* OS2 */
- p++;
- }
- p = vvbuf;
- #ifndef VMS
- if (p > vvbuf) { /* Directory termination character */
- c =
- #ifdef MAC
- ':'
- #else
- #ifdef datageneral
- ':'
- #else
- #ifdef STRATUS
- '>'
- #else
- '/'
- #endif /* STRATUS */
- #endif /* datageneral */
- #endif /* MAC */
- ;
- if (*(p-1) != c) { /* Add it to the end of the */
- *p++ = c; /* string if it was not already */
- *p = NUL; /* there */
- }
- }
- #endif /* Not VMS */
- /*
- But if the result is just the one character, e.g. '/' in Unix, erase it
- because that's the root directory and obviously can't be used for temporary
- files.
- */
- if (vvbuf[0] == c && vvbuf[1] == NUL) {
- vvbuf[0] = NUL;
- }
- }
- makestr(&tempdir,p); /* Save result where we can find it next time */
- return(vvbuf);
- }
- /* Break up long switch statements... */
- switch(y) {
- case VN_ERRNO: /* Error number */
- #ifdef VMS
- {
- extern int vms_lasterr;
- sprintf(vvbuf, "%d", vms_lasterr); /* SAFE */
- }
- #else
- sprintf(vvbuf, "%d", errno); /* SAFE */
- #endif /* VMS */
- return(vvbuf);
- case VN_ERSTR: /* Error string */
- ckstrncpy(vvbuf,ck_errstr(),VVBUFL);
- return(vvbuf);
- #ifndef NOXFER
- case VN_RPSIZ: /* RECEIVE packet-length */
- sprintf(vvbuf,"%d",urpsiz); /* SAFE */
- return(vvbuf);
- case VN_WINDO: /* WINDOW slots */
- sprintf(vvbuf,"%d",wslotr); /* SAFE */
- return(vvbuf);
- #endif /* NOXFER */
- case VN_TFLN: /* TAKE-file line number */
- if (tlevel > -1) {
- sprintf(vvbuf, "%d", tfline[tlevel]); /* SAFE */
- return(vvbuf);
- } else
- return("0");
- case VN_MDMSG: /* DIALRESULT */
- #ifndef NODIAL
- return((char *)modemmsg);
- #else
- return("");
- #endif /* NODIAL */
- case VN_DNUM: /* DIALNUMBER */
- #ifndef NODIAL
- return(dialnum ? (char *) dialnum : "");
- #else
- return("");
- #endif /* NODIAL */
- case VN_APC:
- sprintf(vvbuf, "%d", /* SAFE */
- #ifdef CK_APC
- apcactive
- #else
- 0
- #endif /* CK_APC */
- );
- return((char *)vvbuf);
- #ifdef OS2
- #ifndef NOKVERBS
- case VN_TRMK:
- sprintf(vvbuf, "%d", keymac); /* SAFE */
- return((char *)vvbuf);
- #endif /* NOKVERBS */
- #endif /* OS2 */
- case VN_IPADDR:
- #ifdef TCPSOCKET
- #ifndef OSK
- /* This dumps core on OS-9 for some reason, but only if executed */
- /* before we have made a TCP connection. This is obviously not */
- /* the ideal fix. */
- if (!myipaddr[0])
- getlocalipaddr();
- #endif /* OSK */
- #endif /* TCPSOCKET */
- ckstrncpy(vvbuf,
- #ifdef TCPSOCKET
- (char *)myipaddr,
- #else
- "",
- #endif /* TCPSOCKET */
- VVBUFL);
- return((char *)vvbuf);
- #ifndef NOXFER
- case VN_CRC16: /* CRC-16 of most recent transfer */
- sprintf(vvbuf,"%d",crc16); /* SAFE */
- return(vvbuf);
- #endif /* NOXFER */
- #ifdef CK_PID
- case VN_PID:
- #ifdef IKSD
- #ifdef CK_LOGIN
- if (inserver && isguest)
- return("");
- #endif /* CK_LOGIN */
- #endif /* IKSD */
- return(ckgetpid());
- #endif /* CK_PID */
- #ifndef NOXFER
- case VN_FNAM: { /* \v(filename) */
- extern char filnam[], ofn1[], *sfspec, *rrfspec;
- char * tmp;
- switch (what) { /* File transfer is in progress */
- #ifdef NEWFTP
- case (W_FTP|W_RECV):
- case (W_FTP|W_SEND):
- return((char *)filnam);
- #endif /* NEWFTP */
- case W_RECV:
- case W_REMO:
- return((char *)ofn1);
- default: /* Most recent file transferred */
- if (filnam[0]) { /* (if any) */
- return((char *)filnam);
- } else if (lastxfer & W_SEND && sfspec) {
- if (fnspath == PATH_OFF)
- zstrip(sfspec,&tmp);
- else
- tmp = sfspec;
- return(tmp);
- } else if (lastxfer & W_RECV && rrfspec) {
- if (fnrpath == PATH_OFF)
- zstrip(rrfspec,&tmp);
- else
- tmp = rrfspec;
- return(tmp);
- } else
- return("");
- }
- }
- case VN_FNUM: /* \v(filenum) */
- sprintf(vvbuf,"%ld",filcnt); /* SAFE */
- return((char *)vvbuf);
- #endif /* NOXFER */
- #ifdef PEXITSTAT
- case VN_PEXIT: {
- extern int pexitstat;
- sprintf(vvbuf,"%d",pexitstat); /* SAFE */
- return((char *)vvbuf);
- }
- #endif /* PEXITSTAT */
- #ifndef NOXFER
- case VN_P_8BIT:
- vvbuf[0] = parity ? ebq : NUL;
- vvbuf[1] = NUL;
- return((char *)vvbuf);
- case VN_P_CTL: {
- extern CHAR myctlq;
- vvbuf[0] = myctlq;
- vvbuf[1] = NUL;
- return((char *)vvbuf);
- }
- case VN_P_RPT: {
- extern int rptena;
- vvbuf[0] = rptena ? rptq : NUL;
- vvbuf[1] = NUL;
- return((char *)vvbuf);
- }
- #endif /* NOXFER */
- } /* Break up long switch statements... */
- switch(y) {
- case VN_XPROG:
- #ifndef COMMENT
- /* C-Kermit 9.0 and later for Windows and OS/2 is just C-Kermit */
- return("C-Kermit");
- #else
- #ifdef OS2
- #ifdef NT
- #ifdef KUI
- return("K-95G");
- #else
- return("K-95");
- #endif /* KUI */
- #else
- return("K/2");
- #endif /* NT */
- #else
- return("C-Kermit");
- #endif /* OS2 */
- #endif /* COMMENT */
- case VN_EDITOR:
- #ifdef NOFRILLS
- return("");
- #else
- #ifdef NOPUSH
- return("");
- #else
- {
- extern char editor[];
- char *ss;
- if (!editor[0]) {
- ss = getenv("EDITOR");
- if (ss) {
- ckstrncpy(editor,ss,CKMAXPATH);
- }
- }
- debug(F110,"\\v(editor)",editor,0);
- return(editor[0] ? (char *)editor : "");
- }
- #endif /* NOPUSH */
- #endif /* NOFRILLS */
- case VN_EDOPT:
- #ifdef NOFRILLS
- return("");
- #else
- #ifdef NOPUSH
- return("");
- #else
- {
- extern char editopts[];
- return(editopts[0] ? (char *)editopts : "");
- }
- #endif /* NOPUSH */
- #endif /* NOFRILLS */
- case VN_EDFILE:
- #ifdef NOFRILLS
- return("");
- #else
- #ifdef NOPUSH
- return("");
- #else
- {
- extern char editfile[];
- return(editfile[0] ? (char *)editfile : "");
- }
- #endif /* NOPUSH */
- #endif /* NOFRILLS */
- #ifdef BROWSER
- case VN_BROWSR: {
- extern char browser[];
- if (!browser[0]) {
- s = getenv("BROWSER");
- if (s) ckstrncpy(browser,s,CKMAXPATH);
- }
- return(browser[0] ? (char *)browser : "");
- }
- case VN_BROPT: {
- extern char browsopts[];
- return(browsopts[0] ? (char *)browsopts : "");
- }
- case VN_URL: {
- extern char browsurl[];
- return(browsurl[0] ? (char *)browsurl : "");
- }
- #endif /* BROWSER */
- case VN_HERALD:
- return((char *)versio);
- case VN_TEST: { /* test */
- extern char * ck_s_test, * ck_s_tver;
- if (!ck_s_test) ck_s_test = "";
- if (!ck_s_tver) ck_s_tver = "";
- if (*ck_s_test) {
- ckstrncpy(vvbuf,ck_s_test,VVBUFL);
- if (*ck_s_tver) {
- ckstrncat(vvbuf,".",VVBUFL);
- ckstrncat(vvbuf,ck_s_tver,VVBUFL);
- }
- } else
- ckstrncpy(vvbuf,"0",VVBUFL);
- return((char *)vvbuf);
- }
- #ifndef NOXFER
- case VN_XFSTAT: /* xferstatus */
- x = xferstat; /* Like success */
- if (x > -1) x = (x == 0) ? 1 : 0; /* External value is reversed */
- sprintf(vvbuf,"%d",x); /* SAFE */
- return((char *)vvbuf);
- case VN_XFMSG: /* xfermsg */
- return((char *)epktmsg);
- #ifndef NOMSEND
- case VN_SNDL: { /* sendlist */
- extern int filesinlist;
- sprintf(vvbuf,"%d",filesinlist); /* SAFE */
- return((char *)vvbuf);
- }
- #endif /* NOMSEND */
- #endif /* NOXFER */
- #ifdef CK_TRIGGER
- case VN_TRIG: {
- extern char * triggerval;
- return(triggerval ? triggerval : "");
- }
- #endif /* CK_TRIGGER */
- #ifdef OS2MOUSE
- #ifdef OS2
- case VN_MOU_X: {
- extern int MouseCurX;
- sprintf(vvbuf,"%d",MouseCurX); /* SAFE */
- return((char *)vvbuf);
- }
- case VN_MOU_Y: {
- extern int MouseCurY;
- sprintf(vvbuf,"%d",MouseCurY); /* SAFE */
- return((char *)vvbuf);
- }
- #endif /* OS2 */
- #endif /* OS2MOUSE */
- case VN_PRINT: {
- extern int printpipe;
- extern char * printername;
- #ifdef PRINTSWI
- extern int noprinter;
- if (noprinter) return("");
- #endif /* PRINTSWI */
- ckmakmsg(vvbuf,VVBUFL,
- printpipe ? "|" : "",
- printername ? printername :
- #ifdef OS2
- "PRN",
- #else
- "(default)",
- #endif /* OS2 */
- NULL,
- NULL
- );
- return((char *)vvbuf);
- }
- } /* Break up long switch statements... */
- switch(y) {
- case VN_ESC: /* Escape character */
- sprintf(vvbuf,"%d",escape); /* SAFE */
- return((char *)vvbuf);
- case VN_INTIME:
- sprintf(vvbuf,"%ld",inetime); /* SAFE */
- return((char *)vvbuf);
- case VN_INTMO:
- sprintf(vvbuf,"%d",inwait); /* SAFE */
- return((char *)vvbuf);
- case VN_SECURE:
- if (0
- #ifdef SSHBUILTIN
- || IS_SSH()
- #endif /* SSHBUILTIN */
- #ifdef CK_ENCRYPTION
- || ck_tn_encrypting() && ck_tn_decrypting()
- #endif /* CK_ENCRYPTION */
- #ifdef CK_SSL
- || tls_active_flag || ssl_active_flag
- #endif /* CK_SSL */
- )
- return("1");
- else
- return("0");
- case VN_AUTHN:
- #ifdef CK_AUTHENTICATION
- {
- extern char szUserNameAuthenticated[];
- return((char *)szUserNameAuthenticated);
- }
- #else /* CK_AUTHENTICATION */
- return((char *)"");
- #endif /* CK_AUTHENTICATION */
- case VN_AUTHS:
- #ifdef CK_AUTHENTICATION
- switch (ck_tn_auth_valid()) {
- case AUTH_UNKNOWN:
- return((char *)"unknown");
- case AUTH_OTHER:
- return((char *)"other");
- case AUTH_USER:
- return((char *)"user");
- case AUTH_VALID:
- return((char *)"valid");
- case AUTH_REJECT:
- default:
- return((char *)"rejected");
- }
- #else /* CK_AUTHENTICATION */
- return((char *)"rejected");
- #endif /* CK_AUTHENTICATION */
- case VN_AUTHT:
- #ifdef CK_AUTHENTICATION
- #ifdef CK_SSL
- if ((ssl_active_flag || tls_active_flag) &&
- ck_tn_auth_valid() == AUTH_VALID &&
- (sstelnet ? (!TELOPT_U(TELOPT_AUTHENTICATION)) :
- (!TELOPT_ME(TELOPT_AUTHENTICATION))) ||
- ck_tn_authenticated() == AUTHTYPE_NULL ||
- ck_tn_authenticated() == AUTHTYPE_AUTO)
- return("X_509_CERTIFICATE");
- else
- #endif /* CK_SSL */
- return(AUTHTYPE_NAME(ck_tn_authenticated()));
- #else /* CK_AUTHENTICATION */
- return((char *)"NULL");
- #endif /* CK_AUTHENTICATION */
- #ifdef CK_KERBEROS
- case VN_K4PRN: {
- extern char * krb4_d_principal;
- if (krb4_d_principal)
- ckstrncpy(vvbuf,krb4_d_principal,VVBUFL+1);
- else
- *vvbuf = NUL;
- return((char *)vvbuf);
- }
- case VN_K5PRN: {
- extern char * krb5_d_principal;
- if (krb5_d_principal)
- ckstrncpy(vvbuf,krb5_d_principal,VVBUFL+1);
- else
- *vvbuf = NUL;
- return((char *)vvbuf);
- }
- case VN_K4RLM: {
- extern char * krb4_d_realm;
- if (krb4_d_realm) {
- ckstrncpy(vvbuf,krb4_d_realm,VVBUFL+1);
- } else {
- char * s = ck_krb4_getrealm();
- ckstrncpy(vvbuf,s ? s : "",VVBUFL+1);
- }
- return((char *)vvbuf);
- }
- case VN_K4SRV: {
- extern char * krb4_d_srv;
- if (krb4_d_srv)
- ckstrncpy(vvbuf,krb4_d_srv,VVBUFL+1);
- else
- ckstrncpy(vvbuf,"rcmd",VVBUFL);
- return((char *)vvbuf);
- }
- case VN_K5RLM: {
- extern char * krb5_d_realm;
- extern char * krb5_d_cc;
- if (krb5_d_realm) {
- ckstrncpy(vvbuf,krb5_d_realm,VVBUFL+1);
- } else {
- char * s = ck_krb5_getrealm(krb5_d_cc);
- ckstrncpy(vvbuf,s,VVBUFL+1);
- }
- return((char *)vvbuf);
- }
- case VN_K5CC: {
- extern char * krb5_d_cc;
- if (krb5_d_cc)
- ckstrncpy(vvbuf,krb5_d_cc,VVBUFL+1);
- else
- ckstrncpy(vvbuf,ck_krb5_get_cc_name(),VVBUFL+1);
- return((char *)vvbuf);
- }
- case VN_K5SRV: {
- extern char * krb5_d_srv;
- if (krb5_d_srv)
- ckstrncpy(vvbuf,krb5_d_srv,VVBUFL+1);
- else
- ckstrncpy(vvbuf,"host",VVBUFL);
- return((char *)vvbuf);
- }
- case VN_K4ENO: {
- extern int krb4_errno;
- sprintf(vvbuf,"%d",krb4_errno); /* SAFE */
- return((char *)vvbuf);
- }
- case VN_K5ENO: {
- extern int krb5_errno;
- sprintf(vvbuf,"%d",krb5_errno); /* SAFE */
- return((char *)vvbuf);
- }
- case VN_K4EMSG: {
- extern char * krb4_errmsg;
- ckstrncpy(vvbuf,krb4_errmsg?krb4_errmsg:"",VVBUFL+1);
- return((char *)vvbuf);
- }
- case VN_K5EMSG: {
- extern char * krb5_errmsg;
- ckstrncpy(vvbuf,krb5_errmsg,VVBUFL+1);
- return((char *)vvbuf);
- }
- #endif /* CK_KERBEROS */
- #ifdef CK_SSL
- case VN_X509_S:
- if (ssl_active_flag)
- ckstrncpy(vvbuf,ssl_get_subject_name(ssl_con),VVBUFL+1);
- else if (tls_active_flag)
- ckstrncpy(vvbuf,ssl_get_subject_name(tls_con),VVBUFL+1);
- else
- ckstrncpy(vvbuf,"",VVBUFL+1);
- return((char *)vvbuf);
- case VN_X509_I:
- if (ssl_active_flag)
- ckstrncpy(vvbuf,ssl_get_issuer_name(ssl_con),VVBUFL+1);
- else if (tls_active_flag)
- ckstrncpy(vvbuf,ssl_get_issuer_name(tls_con),VVBUFL+1);
- else
- ckstrncpy(vvbuf,"",VVBUFL+1);
- return((char *)vvbuf);
- #endif /* CK_SSL */
- case VN_OSNAM:
- #ifdef IKSD
- #ifdef CK_LOGIN
- if (inserver && isguest)
- return("");
- #endif /* CK_LOGIN */
- #endif /* IKSD */
- #ifdef CK_UTSNAME
- {
- extern char unm_nam[];
- return((char *)unm_nam);
- }
- #else
- for (x = y = 0; x < VVBUFL; x++) {
- if (ckxsys[x] == SP && cx == 0) continue;
- vvbuf[y++] = (char) ((ckxsys[x] == SP) ? '_' : ckxsys[x]);
- }
- vvbuf[y] = NUL;
- return(vvbuf);
- #endif /* CK_UTSNAME */
- case VN_OSVER: {
- #ifdef CK_UTSNAME
- extern char unm_ver[];
- #ifdef IKSD
- #ifdef CK_LOGIN
- if (inserver && isguest)
- return("");
- #endif /* CK_LOGIN */
- #endif /* IKSD */
- return((char *)unm_ver);
- #else
- return("");
- #endif /* CK_UTSNAME */
- }
- case VN_OSREL: {
- #ifdef CK_UTSNAME
- extern char unm_rel[];
- #ifdef IKSD
- #ifdef CK_LOGIN
- if (inserver && isguest)
- return("");
- #endif /* CK_LOGIN */
- #endif /* IKSD */
- return((char *)unm_rel);
- #else
- return("");
- #endif /* CK_UTSNAME */
- }
- } /* Break up long switch statements... */
- switch(y) {
- case VN_NAME: {
- extern char * myname;
- return(myname);
- }
- case VN_MODL: {
- #ifdef CK_UTSNAME
- extern char unm_mod[], unm_mch[];
- int y = VVBUFL - 1;
- char * s = unm_mod;
- #endif /* CK_UTSNAME */
- #ifdef IKSD
- #ifdef CK_LOGIN
- if (inserver && isguest)
- return("");
- #endif /* CK_LOGIN */
- #endif /* IKSD */
- #ifdef COMMENT /* was HPUX */
- if (!unm_mod[0] && !nopush)
- zzstring("\\fcommand(model)",&s,&y);
- /*
- Another possibility would be:
- "\\fcommand(ksh -c 'whence model 1>&- && model || uname -m')"
- But that would depend on having ksh.
- */
- #else
- #ifdef OSF32 /* Digital UNIX 3.2 and higher... */
- /* Note: Ultrix has /etc/sizer, but it is not publicly executable. */
- /* sizer -c outputs 'cpu:<tab><tab>"DECxxxx"' */
- if (!unm_mod[0]) {
- char * p;
- int flag = 0;
- zzstring("\\fcommand(/usr/sbin/sizer -c)",&s,&y);
- debug(F110,"DU model",unm_mod,0);
- s = unm_mod;
- p = unm_mod;
- while (*p) { /* Extract the part in quotes */
- if (*p == '"') {
- if (flag)
- break;
- flag = 1;
- p++;
- continue;
- }
- if (flag)
- *s++ = *p;
- p++;
- }
- *s = NUL;
- }
- #endif /* OSF32 */
- #endif /* COMMENT */
- #ifdef CK_UTSNAME
- if (unm_mod[0])
- return((char *)unm_mod);
- else
- return((char *)unm_mch);
- #else
- return("");
- #endif /* CK_UTSNAME */
- }
- #ifdef IBMX25
- /* X.25 variables (local and remote address) */
- case VN_X25LA:
- if (!local_nua[0] && !x25local_nua(local_nua))
- *vvbuf = NULL;
- else
- ckstrncpy(vvbuf,local_nua,VVBUFL+1);
- return((char *)vvbuf);
- case VN_X25RA:
- if (!remote_nua[0])
- *vvbuf = NULL;
- else
- ckstrncpy(vvbuf,remote_nua,VVBUFL+1);
- return((char *)vvbuf);
- #endif /* IBMX25 */
- #ifndef NODIAL
- case VN_PDSFX: {
- extern char pdsfx[];
- return((char *)pdsfx);
- }
- case VN_DTYPE: {
- extern int dialtype;
- sprintf(vvbuf,"%d",dialtype); /* SAFE */
- return((char *)vvbuf);
- }
- #endif /* NODIAL */
- #ifdef UNIX
- case VN_LCKPID: {
- extern char lockpid[];
- return((char *)lockpid);
- }
- #endif /* UNIX */
- #ifndef NOXFER
- case VN_BLK:
- sprintf(vvbuf,"%d",bctr); /* SAFE */
- return((char *)vvbuf);
- case VN_TFTIM:
- sprintf(vvbuf, /* SAFE */
- #ifdef GFTIMER
- "%ld", (long)(fptsecs + 0.5)
- #else
- "%d", tsecs
- #endif /* GFTIMER */
- );
- return((char *)vvbuf);
- #endif /* NOXFER */
- case VN_HWPAR:
- case VN_SERIAL: {
- int sb;
- char c, * ss;
- extern int stopbits;
- vvbuf[0] = NUL;
- if (hwparity && local && !network)
- ss = parnam((char)hwparity);
- else
- ss = parnam((char)parity);
- if (cx == VN_HWPAR) {
- ckstrncpy(vvbuf,ss,VVBUFL);
- return((char *)vvbuf);
- }
- c = ss[0];
- if (islower(c)) c = toupper(c);
- sb = stopbits;
- if (sb < 1)
- sb = (speed > 0 && speed <= 110L) ? 2 : 1;
- if (hwparity)
- sprintf(vvbuf," 8%c%d",c,sb); /* SAFE */
- else if (parity)
- sprintf(vvbuf," 7%c%d",c,sb); /* SAFE */
- else
- sprintf(vvbuf," 8N%d",sb); /* SAFE */
- return((char *)vvbuf);
- }
- #ifdef UNIX
- case VN_LCKDIR: {
- #ifndef NOUUCP
- extern char * uucplockdir;
- ckstrncpy(vvbuf,uucplockdir,VVBUFL);
- x = strlen(vvbuf);
- if (x > 0) {
- if (vvbuf[x-1] != '/') {
- vvbuf[x] = '/';
- vvbuf[x+1] = NUL;
- }
- }
- #else
- vvbuf[0] = NUL;
- #endif /* NOUUCP */
- return((char *)vvbuf);
- }
- #endif /* UNIX */
- } /* Break up long switch statements... */
- switch(y) {
- #ifndef NODIAL
- case VN_DM_LP:
- case VN_DM_SP:
- case VN_DM_PD:
- case VN_DM_TD:
- case VN_DM_WA:
- case VN_DM_WD:
- case VN_DM_HF:
- case VN_DM_WB:
- case VN_DM_RC: {
- extern char * getdm();
- ckstrncpy(vvbuf,getdm(y),VVBUFL);
- return((char *)vvbuf);
- }
- #endif /* NODIAL */
- case VN_TY_LN:
- case VN_TY_LC: {
- extern int typ_lines;
- sprintf(vvbuf,"%d",typ_lines); /* SAFE */
- return((char *)vvbuf);
- }
- case VN_TY_LM: {
- extern int typ_mtchs;
- sprintf(vvbuf,"%d",typ_mtchs); /* SAFE */
- return((char *)vvbuf);
- }
- case VN_MACLVL:
- sprintf(vvbuf,"%d",maclvl); /* SAFE */
- return((char *)vvbuf);
- } /* Break up long switch statements... */
- switch(y) {
- #ifndef NOLASTFILE
- case VN_LASTFIL: {
- extern char * lastfile;
- return(lastfile ? lastfile : "");
- }
- #endif /* NOLASTFILE */
- #ifndef NOXFER
- case VN_XF_BC:
- sprintf(vvbuf,"%d",crunched); /* SAFE */
- return((char *)vvbuf);
- case VN_XF_TM:
- sprintf(vvbuf,"%d",timeouts); /* SAFE */
- return((char *)vvbuf);
- case VN_XF_RX:
- sprintf(vvbuf,"%d",retrans); /* SAFE */
- return((char *)vvbuf);
- #endif /* NOXFER */
- case VN_MS_CD: /* Modem signals */
- case VN_MS_CTS:
- case VN_MS_DSR:
- case VN_MS_DTR:
- case VN_MS_RI:
- case VN_MS_RTS: {
- int x, z = -1;
- x = ttgmdm(); /* Try to get them */
- if (x > -1) {
- switch (y) {
- case VN_MS_CD: z = (x & BM_DCD) ? 1 : 0; break;
- case VN_MS_DSR: z = (x & BM_DSR) ? 1 : 0; break;
- case VN_MS_CTS: z = (x & BM_CTS) ? 1 : 0; break;
- #ifdef MAC
- case VN_MS_DTR: z = (x & BM_DTR) ? 1 : 0; break;
- #else
- #ifndef STRATUS
- case VN_MS_RI: z = (x & BM_RNG) ? 1 : 0; break;
- #ifndef NT
- case VN_MS_DTR: z = (x & BM_DTR) ? 1 : 0; break;
- case VN_MS_RTS: z = (x & BM_RTS) ? 1 : 0; break;
- #endif /* NT */
- #endif /* STRATUS */
- #endif /* MAC */
- }
- }
- sprintf(vvbuf,"%d",z); /* SAFE */
- return((char *)vvbuf);
- }
- case VN_MATCH: /* INPUT MATCH */
- return(inpmatch ? inpmatch : "");
- #ifdef CKFLOAT
- case VN_ISCALE: /* INPUT SCALE-FACTOR */
- return(inpscale ? inpscale : "1.0");
- #endif /* CKFLOAT */
- case VN_SLMSG: { /* SET LINE / HOST message */
- extern char * slmsg;
- vvbuf[0] = NUL;
- if (slmsg)
- ckstrncpy(vvbuf,slmsg,VVBUFL);
- return(vvbuf);
- }
- case VN_TXTDIR: /* TEXTDIR */
- return(k_info_dir ? k_info_dir : "");
- #ifdef FNFLOAT
- case VN_MA_PI:
- return(math_pi);
- case VN_MA_E:
- return(math_e);
- case VN_MA_PR:
- sprintf(vvbuf,"%d",fp_digits); /* SAFE */
- return(vvbuf);
- #endif /* FNFLOAT */
- case VN_CMDBL:
- sprintf(vvbuf,"%d",CMDBL); /* SAFE */
- return(vvbuf);
- #ifdef CKCHANNELIO
- case VN_FERR: {
- extern int z_error;
- sprintf(vvbuf,"%d",z_error); /* SAFE */
- return(vvbuf);
- }
- case VN_FMAX: {
- extern int z_maxchan;
- sprintf(vvbuf,"%d",z_maxchan); /* SAFE */
- return(vvbuf);
- }
- case VN_FCOU: {
- extern int z_filcount;
- sprintf(vvbuf,"%d",z_filcount); /* SAFE */
- return(vvbuf);
- }
- #endif /* CKCHANNELIO */
- #ifndef NODIAL
- case VN_DRTR: {
- extern int dialcount;
- sprintf(vvbuf,"%d",dialcount); /* SAFE */
- return(vvbuf);
- }
- #endif /* NODIAL */
- #ifndef NOLOGDIAL
- #ifndef NOLOCAL
- case VN_CXTIME:
- sprintf(vvbuf,"%ld",dologshow(0)); /* SAFE */
- return(vvbuf);
- #endif /* NOLOCAL */
- #endif /* NOLOGDIAL */
- case VN_BYTE:
- sprintf(vvbuf,"%d",byteorder); /* SAFE */
- return(vvbuf);
- case VN_KBCHAR:
- vvbuf[0] = NUL;
- vvbuf[1] = NUL;
- if (kbchar > 0)
- vvbuf[0] = (kbchar & 0xff);
- return(vvbuf);
- case VN_TTYNAM: {
- #ifdef HAVECTTNAM
- extern char cttnam[];
- return((char *)cttnam);
- #else
- return(CTTNAM);
- #endif /* HAVECTTNAM */
- }
- case VN_PROMPT:
- return(cmgetp());
- case VN_BUILD: {
- extern char * buildid;
- return(buildid);
- }
- #ifndef NOSEXP
- case VN_SEXP: {
- extern char * lastsexp;
- return(lastsexp ? lastsexp : "");
- }
- case VN_VSEXP: {
- extern char * sexpval;
- return(sexpval ? sexpval : "");
- }
- case VN_LSEXP: {
- extern int sexpdep;
- ckstrncpy(vvbuf,ckitoa(sexpdep),VVBUFL);
- return(vvbuf);
- }
- #endif /* NOSEXP */
- #ifdef GFTIMER
- case VN_FTIME: {
- CKFLOAT f;
- ztime(&p);
- if (p == NULL || *p == NUL)
- return(NULL);
- z = atol(p+11) * 3600L + atol(p+14) * 60L + atol(p+17);
- f = (CKFLOAT)z + ((CKFLOAT)ztusec) / 1000000.0;
- sprintf(vvbuf,"%f",f); /* SAFE */
- return(vvbuf);
- }
- #endif /* GFTIMER */
- #ifndef NOHTTP
- case VN_HTTP_C: { /* HTTP Code */
- extern int http_code;
- return(ckitoa(http_code));
- }
- case VN_HTTP_N: /* HTTP Connected */
- return( http_isconnected() ? "1" : "0");
- case VN_HTTP_H: /* HTTP Host */
- return( (char *)http_host() );
- case VN_HTTP_M: { /* HTTP Message */
- extern char http_reply_str[];
- return((char *)http_reply_str);
- }
- case VN_HTTP_S: /* HTTP Security */
- return((char *)http_security());
- #endif /* NOHTTP */
- #ifdef NEWFTP
- case VN_FTP_B:
- return((char *)ftp_cpl_mode());
- case VN_FTP_D:
- return((char *)ftp_dpl_mode());
- case VN_FTP_Z:
- return((char *)ftp_authtype());
- case VN_FTP_C: {
- extern int ftpcode;
- return(ckitoa(ftpcode));
- }
- case VN_FTP_M: {
- extern char ftp_reply_str[];
- if (isdigit(ftp_reply_str[0]) &&
- isdigit(ftp_reply_str[1]) &&
- isdigit(ftp_reply_str[2]) &&
- ftp_reply_str[3] == ' ')
- return(&ftp_reply_str[4]);
- else
- return(ftp_reply_str);
- }
- case VN_FTP_S: {
- extern char ftp_srvtyp[];
- return((char *)ftp_srvtyp);
- }
- case VN_FTP_H: {
- extern char * ftp_host;
- return(ftp_host ? ftp_host : "");
- }
- case VN_FTP_X: { /* FTP Connected */
- return(ftpisconnected() ? "1" : "0");
- }
- case VN_FTP_L: { /* FTP Logged in */
- return(ftpisloggedin() ? "1" : "0");
- }
- case VN_FTP_G: { /* FTP GET-PUT-REMOTE */
- extern int ftpget;
- char * s = "";
- switch (ftpget) {
- case 0: s = "kermit"; break;
- case 1: s = "ftp"; break;
- case 2: s = "auto"; break;
- }
- return(s);
- }
- #endif /* NEWFTP */
- #ifndef NOLOCAL
- case VN_CX_STA: { /* CONNECT status */
- extern int cx_status;
- return(ckitoa(cx_status));
- }
- #endif /* NOLOCAL */
- case VN_NOW: /* Timestamp */
- return(ckcvtdate(p,0));
- case VN_HOUR: /* Hour of the day */
- ztime(&p); /* "Thu Feb 8 12:00:00 1990" */
- if (!p) p = "";
- if (!*p) return(p);
- vvbuf[0] = p[11];
- vvbuf[1] = p[12];
- vvbuf[2] = NUL;
- return(vvbuf); /* and return it */
- case VN_BITS: /* Bits (16, 32, 64) */
- if (sizeof(long) > 4)
- return(ckitoa(8*sizeof(long)));
- else
- return(ckitoa(8*sizeof(int)));
- case VN_LASTKWV: /* 212 */
- return(lastkwval ? lastkwval : "");
- case VN_HOSTIP: { /* 212 */
- #ifdef TCPSOCKET
- extern char hostipaddr[];
- return((char *)hostipaddr);
- #else
- return("");
- #endif /* TCPSOCKET */
- }
- case VN_INPMSG:
- switch (instatus) {
- case INP_OK: return("SUCCESS");
- case INP_TO: return("Timed out");
- case INP_UI: return("Keyboard interrupt");
- case INP_IE: return("Internal error");
- case INP_IO: return("I/O error or connection lost");
- case INP_IKS: return("INPUT disabled");
- case INP_BF: return("Buffer filled and /NOWRAP set");
- default: return("Unknown");
- }
- case VN_VAREVAL: /* 212 */
- return(vareval ? "recursive" : "simple");
- case VN_LOG_CON: /* \v(...) for log files */
- #ifdef CKLOGDIAL
- return(diafil);
- #else
- return("");
- #endif
- case VN_LOG_PKT:
- #ifndef NOXFER
- return(pktfil);
- #else
- return("");
- #endif
- case VN_LOG_SES:
- #ifndef NOLOCAL
- return(sesfil);
- #else
- return("");
- #endif
- case VN_LOG_TRA:
- #ifdef TLOG
- return(trafil);
- #else
- return("");
- #endif
- case VN_LOG_DEB:
- #ifdef DEBUG
- return(debfil);
- #else
- return("");
- #endif
- case VN_PREVCMD: {
- extern char * prevcmd;
- return(prevcmd ? prevcmd : "");
- }
- }
- #ifndef NODIAL
- switch (y) { /* Caller ID values */
- extern char
- * callid_date, * callid_time, * callid_name,
- * callid_nmbr, * callid_mesg;
- case VN_CI_DA:
- return(callid_date ? callid_date : "");
- case VN_CI_TI:
- return(callid_time ? callid_time : "");
- case VN_CI_NA:
- return(callid_name ? callid_name : "");
- case VN_CI_NU:
- return(callid_nmbr ? callid_nmbr : "");
- case VN_CI_ME:
- return(callid_mesg ? callid_mesg : "");
- } /* End of variable-name switches */
- #endif /* NODIAL */
- #ifdef NT
- switch (y) {
- case VN_PERSONAL:
- p = (char *)GetPersonal();
- if (p) {
- GetShortPathName(p,vvbuf,VVBUFL);
- return(vvbuf);
- }
- return("");
- case VN_DESKTOP:
- p = (char *)GetDesktop();
- if (p) {
- GetShortPathName(p,vvbuf,VVBUFL);
- return(vvbuf);
- }
- return("");
- case VN_COMMON:
- p = (char *)GetAppData(1);
- if (p) {
- ckmakmsg(vvbuf,VVBUFL,p,"Kermit 95/",NULL,NULL);
- GetShortPathName(vvbuf,vvbuf,VVBUFL);
- return(vvbuf);
- }
- return("");
- case VN_APPDATA:
- p = (char *)GetAppData(0);
- if (p) {
- ckmakmsg(vvbuf,VVBUFL,p,"Kermit 95/",NULL,NULL);
- GetShortPathName(vvbuf,vvbuf,VVBUFL);
- return(vvbuf);
- }
- return("");
- }
- #endif /* NT */
- #ifdef TN_COMPORT
- switch (y) {
- case VN_TNC_SIG: {
- p = (char *) tnc_get_signature();
- ckstrncpy(vvbuf,p ? p : "",VVBUFL);
- return(vvbuf);
- }
- }
- #endif /* TN_COMPORT */
- #ifdef KUI
- switch (y) {
- case VN_GUI_RUN: {
- extern HWND getHwndKUI();
- if ( IsIconic(getHwndKUI()) )
- return("minimized");
- if ( IsZoomed(getHwndKUI()) )
- return("maximized");
- return("restored");
- }
- case VN_GUI_XP:
- sprintf(vvbuf,"%d",get_gui_window_pos_x()); /* SAFE */
- return(vvbuf);
- case VN_GUI_YP:
- sprintf(vvbuf,"%d",get_gui_window_pos_y()); /* SAFE */
- return(vvbuf);
- case VN_GUI_XR:
- sprintf(vvbuf,"%d",GetSystemMetrics(SM_CXSCREEN)); /* SAFE */
- return(vvbuf);
- case VN_GUI_YR:
- sprintf(vvbuf,"%d",GetSystemMetrics(SM_CYSCREEN)); /* SAFE */
- return(vvbuf);
- case VN_GUI_FNM:
- if ( ntermfont > 0 ) {
- int i;
- for (i = 0; i < ntermfont; i++) {
- if (tt_font == term_font[i].kwval) {
- ckstrncpy(vvbuf,term_font[i].kwd,VVBUFL);
- return(vvbuf);
- }
- }
- }
- return("(unknown)");
- case VN_GUI_FSZ:
- ckstrncpy(vvbuf,ckitoa(tt_font_size/2),VVBUFL);
- if ( tt_font_size % 2 )
- ckstrncat(vvbuf,".5",VVBUFL);
- return(vvbuf);
- }
- #endif /* KUI */
- fnsuccess = 0;
- if (fnerror) {
- fnsuccess = 0;
- }
- if (fndiags) {
- if (!embuf[0])
- ckstrncpy(embuf,"<ERROR:NO_SUCH_VARIABLE>",EMBUFLEN);
- printf("?%s\n",embuf);
- return((char *)embuf);
- } else
- return("");
- }
- #endif /* NOSPL */
- /* warning, this won't work for VMS */
- char *
- getbasename(s) char *s; {
- int n, i;
- if (!s) s = "";
- if (!*s) return("");
- n = (int)strlen(s);
- for (i = n-2; i >= 0; i--) {
- if (ISDIRSEP(s[i]))
- return(s+i+1);
- }
- return(s);
- }
- /*
- X X S T R I N G -- Expand variables and backslash codes.
- int xxtstring(s,&s2,&n);
- Expands \ escapes via recursive descent.
- Argument s is a pointer to string to expand (source).
- Argument s2 is the address of where to put result (destination).
- Argument n is the length of the destination string (to prevent overruns).
- Returns -1 on failure, 0 on success,
- with destination string null-terminated and s2 pointing to the
- terminating null, so that subsequent characters can be added.
- Failure reasons include destination buffer is filled up.
- */
- #define XXDEPLIM 100 /* Recursion depth limit */
- /*
- In Windows the stack is limited to 256K so big character arrays like
- vnambuf can't be on the stack in recursive functions like zzstring().
- But that's no reason use malloc() in Unix or VMS, which don't have
- this kind of restriction.
- */
- #ifdef DVNAMBUF /* Dynamic vnambuf[] */
- #undef DVNAMBUF /* Clean slate */
- #endif /* DVNAMBUF */
- #ifndef NOSPL /* Only if SPL included */
- #ifdef OS2 /* Only for K95 */
- #define DVNAMBUF
- #endif /* OS2 */
- #endif /* NOSPL */
- int
- zzstring(s,s2,n) char *s; char **s2; int *n; {
- int x, /* Current character */
- xx, /* Worker */
- y, /* Worker */
- pp, /* Paren level */
- kp, /* Brace level */
- argn, /* Function argument counter */
- n2, /* Local copy of n */
- d, /* Array dimension */
- vbi, /* Variable id (integer form) */
- argl, /* String argument length */
- nx, /* Save original length */
- quoting = 0; /* 299 */
- char vb, /* Variable id (char form) */
- *vp, /* Pointer to variable definition */
- *new, /* Local pointer to target string */
- #ifdef COMMENT
- *old, /* Save original target pointer */
- #endif /* COMMENT */
- *p, /* Worker */
- *q, /* Worker */
- *s3; /* Worker */
- int x3; /* Worker */
- char *r = (char *)0; /* For holding function args */
- char *r2 = (char *)0;
- char *r3p;
- #ifndef NOSPL
- #ifdef DVNAMBUF
- char * vnambuf = NULL; /* Buffer for variable/function name */
- #else /* DVNAMBUF */
- char vnambuf[VNAML]; /* Buffer for variable/function name */
- #endif /* DVNAMBUF */
- char *argp[FNARGS]; /* Pointers to function args */
- #endif /* NOSPL */
- static int depth = 0; /* Call depth, avoid overflow */
- n2 = *n; /* Make local copies of args */
- nx = n2;
- #ifdef COMMENT
- /* This is always 32K in BIGBUFOK builds */
- if (depth == 0)
- debug(F101,"zzstring top-level n","",n2);
- #endif /* COMMENT */
- new = *s2; /* for one less level of indirection */
- #ifdef COMMENT
- old = new;
- #endif /* COMMENT */
- #ifndef NOSPL
- itsapattern = 0; /* For \fpattern() */
- isjoin = 0; /* For \fjoin() */
- #endif /* NOSPL */
- depth++; /* Sink to a new depth */
- if (depth > XXDEPLIM) { /* Too deep? */
- (VOID) newerrmsg("Definition is circular or too deep");
- debug(F111,"zzstring","Definition is circular or too deep",XXDEPLIM);
- depth = 0;
- *new = NUL;
- return(-1);
- }
- if (!s || !new) { /* Watch out for null pointers */
- debug(F101,"zzstring fail 2","",depth);
- if (new)
- *new = NUL;
- depth = 0;
- return(-1);
- }
- s3 = s;
- argl = 0;
- while (*s3++) argl++; /* Get length of source string */
- debug(F010,"zzstring entry",s,0);
- if (argl == 0) { /* Empty string */
- debug(F111,"zzstring empty arg",s,argl);
- depth = 0;
- *new = NUL;
- return(0);
- }
- if (argl < 0) { /* Watch out for garbage */
- debug(F101,"zzstring fail 3","",depth);
- *new = NUL;
- depth = 0;
- return(-1);
- }
- #ifdef DVNAMBUF
- debug(F100,"vnambuf malloc...","",0);
- vnambuf = malloc(VNAML);
- if (vnambuf == NULL) {
- printf("?Out of memory");
- return(-1);
- }
- debug(F100,"vnambuf malloc ok","",0);
- #endif /* DVNAMBUF */
- while ((x = *s)) { /* Loop for all characters */
- if (x != CMDQ) { /* Is it the command-quote char? */
- *new++ = *s++; /* No, normal char, just copy */
- if (--n2 < 0) { /* and count it, careful of overflow */
- debug(F101,"zzstring overflow 1","",depth);
- depth = 0;
- #ifdef DVNAMBUF
- if (vnambuf) free(vnambuf);
- #endif /* DVNAMBUF */
- return(-1);
- }
- continue;
- }
- /* We have the command-quote character. */
- x = *(s+1); /* Get the following character. */
- if (isupper(x)) x = tolower(x);
- switch (x) { /* Act according to variable type */
- #ifndef NOSPL
- case 0: /* It's a lone backslash */
- *new++ = *s++;
- if (--n2 < 0) {
- debug(F101,"zzstring overflow 2","",0);
- #ifdef DVNAMBUF
- if (vnambuf) free(vnambuf);
- #endif /* DVNAMBUF */
- return(-1);
- }
- break;
- case '%': /* Variable */
- s += 2; /* Get the letter or digit */
- vb = *s++; /* and move source pointer past it */
- vp = NULL; /* Assume definition is empty */
- if (vb >= '0' && vb <= '9') { /* Digit for macro arg */
- if (maclvl < 0) /* Digit variables are global */
- vp = g_var[vb]; /* if no macro is active */
- else /* otherwise */
- vp = m_arg[maclvl][vb - '0']; /* they're on the stack */
- } else if (vb == '*') { /* Macro args string */
- #ifdef COMMENT
- /* This doesn't take changes into account */
- vp = (maclvl >= 0) ? m_line[maclvl] : topline;
- if (!vp) vp = "";
- #else
- char * ss = new;
- if (zzstring("\\fjoin(&_[],,1)",&new,&n2) < 0) {
- #ifdef DVNAMBUF
- if (vnambuf) free(vnambuf);
- #endif /* DVNAMBUF */
- return(-1);
- }
- debug(F110,"zzstring \\%*",ss,0);
- break;
- #endif /* COMMENT */
- } else {
- if (isupper(vb)) vb += ('a'-'A');
- vp = g_var[vb]; /* Letter for global variable */
- }
- if (!vp) vp = "";
- #ifdef COMMENT
- if (vp) { /* If definition not empty */
- #endif /* COMMENT */
- if (vareval) {
- debug(F010,"zzstring %n vp",vp,0);
- /* call self to evaluate it */
- if (zzstring(vp,&new,&n2) < 0) {
- debug(F101,"zzstring fail 6","",depth);
- #ifdef DVNAMBUF
- if (vnambuf) free(vnambuf);
- #endif /* DVNAMBUF */
- return(-1); /* Pass along failure */
- }
- } else {
- while ((*new++ = *vp++)) /* copy it to output string. */
- if (--n2 < 0) {
- if (q) free(q);
- debug(F101,"zzstring overflow 4.5","",depth);
- #ifdef DVNAMBUF
- if (vnambuf) free(vnambuf);
- #endif /* DVNAMBUF */
- return(-1);
- }
- new--; /* Back up over terminating null */
- n2++; /* to allow for further deposits. */
- }
- #ifdef COMMENT
- } else {
- debug(F110,"zzstring %n vp","(NULL)",0);
- n2 = nx;
- new = old;
- *new = NUL;
- }
- #endif /* COMMENT */
- break;
- case '&': /* An array reference */
- x = arraynam(s,&vbi,&d); /* Get name and subscript */
- debug(F111,"zzstring arraynam",s,x);
- if (x < 0) {
- debug(F101,"zzstring fail 7","",depth);
- #ifdef DVNAMBUF
- if (vnambuf) free(vnambuf);
- #endif /* DVNAMBUF */
- return(-1);
- }
- pp = 0; /* Bracket counter */
- while (*s) { /* Advance source pointer... */
- if (*s == '[') pp++;
- if (*s == ']' && --pp == 0) break;
- s++;
- }
- if (*s == ']') s++; /* ...past the closing bracket. */
- xx = chkarray(vbi,d); /* Array is declared? */
- debug(F101,"zzstring chkarray","",x);
- if (xx > -1) {
- #ifdef COMMENT
- char * s1 = NULL;
- #endif /* COMMENT */
- vbi -= ARRAYBASE; /* Convert name to index */
- if (a_dim[vbi] >= d) { /* If subscript in range */
- char **ap;
- ap = a_ptr[vbi]; /* get data pointer */
- if (ap) { /* and if there is one */
- if (ap[d]) { /* If definition not empty */
- debug(F111,"zzstring ap[d]",ap[d],d);
- if (vareval) {
- if (zzstring(ap[d],&new,&n2) < 0) {
- debug(F101,"zzstring fail 8","",depth);
- #ifdef DVNAMBUF
- if (vnambuf) free(vnambuf);
- #endif /* DVNAMBUF */
- return(-1); /* Pass along failure */
- }
- } else {
- vp = ap[d];
- while ((*new++ = *vp++)) /* copy to result */
- if (--n2 < 0) {
- if (q) free(q);
- debug(F101,
- "zzstring overflow 8.5","",depth);
- #ifdef DVNAMBUF
- if (vnambuf) free(vnambuf);
- #endif /* DVNAMBUF */
- return(-1);
- }
- new--; /* Back up over terminating null */
- n2++; /* to allow for further deposits. */
- }
- }
- } else {
- /* old = new; */
- n2 = nx;
- }
- }
- }
- break;
- case 'f': /* A builtin function */
- q = vnambuf; /* Copy the name */
- y = 0; /* into a separate buffer */
- s += 2; /* point past 'F' */
- while (y++ < VNAML) {
- if (*s == '(') { s++; break; } /* Look for open paren */
- if ((*q = *s) == NUL) break; /* or end of string */
- s++; q++;
- }
- *q = NUL; /* Terminate function name */
- if (y >= VNAML) { /* Handle pathological case */
- while (*s && (*s != '(')) /* of very long string entered */
- s++; /* as function name. */
- if (*s == ')') s++; /* Skip past it. */
- }
- r = r2 = malloc(argl+2); /* And make a place to copy args */
- /* debug(F101,"zzstring r2","",r2); */
- if (!r2) { /* Watch out for malloc failure */
- debug(F101,"zzstring fail 9","",depth);
- *new = NUL;
- depth = 0;
- #ifdef DVNAMBUF
- if (vnambuf) free(vnambuf);
- #endif /* DVNAMBUF */
- return(-1);
- }
- if (r3) free(r3); /* And another to copy literal arg string */
- r3 = malloc(argl+2);
- /* debug(F101,"zzstring r3","",r3); */
- if (!r3) {
- debug(F101,"zzstring fail 10","",depth);
- depth = 0;
- *new = NUL;
- if (r2) free(r2);
- #ifdef DVNAMBUF
- if (vnambuf) free(vnambuf);
- #endif /* DVNAMBUF */
- return(-1);
- } else
- r3p = r3;
- argn = 0; /* Argument counter */
- argp[argn++] = r; /* Point to first argument */
- y = 0; /* Completion flag */
- pp = 1; /* Paren level (already have one). */
- kp = 0;
- while (1) { /* Copy each argument, char by char. */
- *r3p++ = *s; /* This is a literal copy for \flit */
- if (!*s) break;
- if (*s == '{') { /* Left brace */
- kp++;
- }
- if (*s == '}') { /* Right brace */
- kp--;
- }
- if (*s == '(' && kp <= 0) { /* Open paren not in brace */
- pp++; /* Count it */
- }
- *r = *s; /* Now copy resulting byte */
- if (!*r) /* If NUL, done. */
- break;
- if (*r == ')' && kp <= 0) { /* Closing paren, count it. */
- if (--pp == 0) { /* Final one? */
- *r = NUL; /* Make it a terminating null */
- *(r3p - 1) = NUL;
- s++; /* Point past it in source string */
- y = 1; /* Flag we've got all the args */
- break; /* Done with while loop */
- }
- }
- if (*r == ',' && kp <= 0) { /* Comma */
- if (pp == 1) { /* If not within ()'s, */
- if (argn >= FNARGS) { /* Too many args */
- s++; r++; /* Keep collecting flit() string */
- continue;
- }
- *r = NUL; /* New arg, skip past comma */
- argp[argn++] = r+1; /* In range, point to new arg */
- } /* Otherwise just skip past */
- }
- s++; r++; /* Advance pointers */
- }
- if (!y) /* If we didn't find closing paren */
- argn = -1;
- #ifdef DEBUG
- if (deblog) {
- char buf[24];
- debug(F111,"zzstring function name",vnambuf,y);
- debug(F010,"zzstring function r3",r3,0);
- for (y = 0; y < argn; y++) {
- sprintf(buf,"arg %2d ",y);
- debug(F010,buf,argp[y],0);
- }
- }
- #endif /* DEBUG */
- {
- /* In case the function name itself is constructed */
- char buf[64]; char * p = buf; int n = 64;
- if (zzstring(vnambuf,&p,&n) > -1)
- ckstrncpy(vnambuf,buf,64);
- }
- vp = fneval(vnambuf,argp,argn,r3); /* Evaluate the function. */
- if (vp) { /* If definition not empty */
- while ((*new++ = *vp++)) { /* copy it to output string */
- if (--n2 < 0) { /* watch out for overflow */
- debug(F101,"zzstring fail 12","",depth);
- if (r2) { free(r2); r2 = NULL; }
- if (r3) { free(r3); r3 = NULL; }
- #ifdef DVNAMBUF
- if (vnambuf) free(vnambuf);
- #endif /* DVNAMBUF */
- return(-1);
- }
- }
- new--; /* Back up over terminating null */
- n2++; /* to allow for further deposits. */
- }
- if (r2) { free(r2); r2 = NULL; }
- if (r3) { free(r3); r3 = NULL; }
- break;
- case 'q': /* 299 String to be take literally */
- quoting = 1; /* 299 */
- case '$': /* An environment variable */
- case 'v': /* Or a named builtin variable. */
- case 'm': /* Or a macro /long variable */
- case 's': /* 196 Macro substring */
- case ':': /* 196 \-variable substring */
- pp = 0;
- p = s+2; /* $/V/M must be followed by (name) */
- if (*p != '(') { /* as in \$(HOME) or \V(count) */
- *new++ = *s++; /* If not, just copy it */
- if (--n2 < 0) {
- debug(F101,"zzstring overflow 3","",depth);
- #ifdef DVNAMBUF
- if (vnambuf) free(vnambuf);
- #endif /* DVNAMBUF */
- return(-1);
- }
- break;
- }
- pp++;
- p++; /* Point to 1st char of name */
- q = vnambuf; /* Copy the name */
- y = 0; /* into a separate buffer */
- debug(F110,">>>> \\q(ARG)",p,0);
- while (y++ < VNAML) { /* Watch out for name too long */
- if (*p == '(') { /* Parens can be nested... */
- if (*(p-1) != CMDQ) /* 299 */
- pp++;
- } else if (*p == ')') { /* Name properly terminated with ')' */
- if (*(p-1) != CMDQ) /* 299 */
- pp--;
- if (pp == 0) {
- p++; /* Move source pointer past ')' */
- break;
- }
- }
- if ((*q = *p) == NUL) /* String ends before ')' */
- break;
- p++; q++; /* Advance pointers */
- }
- *q = NUL; /* Terminate the variable name */
- if (y >= VNAML) { /* Handle pathological case */
- while (*p && (*p != ')')) /* of very long string entered */
- p++; /* as variable name. */
- if (*p == ')') p++; /* Skip ahead to the end of it. */
- }
- /* At this point vnambuf contains the macro name from inside the parens */
- s = p; /* Adjust global source pointer */
- s3 = vnambuf;
- x3 = 0;
- while (*s3++) x3++; /* Length needed */
- /* The following is in case the macro name itself contains variables */
- p = malloc(x3 + 1); /* Make temporary space */
- if (p && !quoting) { /* If we got the space */
- vp = vnambuf; /* Point to original */
- strcpy(p,vp); /* (safe) Make a copy of it */
- y = VNAML; /* Length of name buffer */
- zzstring(p,&vp,&y); /* Evaluate the copy */
- free(p); /* Free the temporary space */
- p = NULL;
- }
- /* At this point vnambuf contains the fully evaluated macro name */
- debug(F110,"zzstring macro name",vnambuf,0);
- q = NULL;
- if (x == 'q') { /* 299 Quoting this string */
- vp = vnambuf; /* 299 */
- debug(F110,">>> VP",vp,0);
- } else if (x == '$') { /* Look up its value */
- vp = getenv(vnambuf); /* This way for environment variable */
- } else if (x == 'm' || x == 's' || x == ':') { /* Macro / substr */
- int k, x1 = -1, x2 = -1;
- char c = NUL;
- k = strlen(vnambuf);
- /* \s(name[n:m]) -- Compact substring notation */
- if ((x == 's' || x == ':') && (k > 1)) { /* Substring wanted */
- int bprc;
- if (vnambuf[k-1] == ']') {
- int i;
- for (i = 0; i < k-1; i++) {
- if (vnambuf[i] == '[') {
- bprc = boundspair(vnambuf,":_.",&x1,&x2,&c);
- debug(F111,"zzstring boundspair",vnambuf,bprc);
- debug(F000,"zzstring boundspair c","",c);
- if (bprc > -1) {
- vnambuf[i] = NUL;
- if (x1 < 1)
- x1 = 1;
- x1--; /* Adjust to 0-base */
- }
- break;
- }
- }
- }
- }
- if (x == ':') { /* Variable type (s or :) */
- vp = vnambuf;
- } else { /* Regular macro or associative array*/
- y = isaarray(vnambuf) ?
- mxxlook(mactab,vnambuf,nmac) : /* Assoc Array */
- mxlook(mactab,vnambuf,nmac); /* Macro */
- if (y > -1) { /* Got definition */
- vp = mactab[y].mval;
- } else {
- vp = NULL;
- }
- }
- debug(F111,"zzstring vp",vp,(vp==NULL)?0:strlen(vp));
- if (vp) {
- if ((x == 's' || x == ':') && (k > 1)) {
- /* Compact substring notation */
- if (x2 == 0) { /* Length */
- vp = NULL;
- } else if (x1 > -1) { /* Start */
- k = strlen(vp);
- debug(F101,">>> k","",k);
- /* If it's off the end, result is empty */
- if (x1 > k) {
- vp = NULL;
- } else if (k > 0) {
- /* Stay in bounds */
- if (c == '_' && x2 > k) /* startpos_endpos */
- x2 = k;
- if (c == ':' && x1 + x2 > k) /* start:length */
- x2 = -1;
- debug(F101,">>> x2","",x2);
- debug(F000,">>> c","",c);
- if ((q = malloc(k+1))) {
- strcpy(q,vp); /* safe */
- if (c == '.') {
- q[x1+1] = NUL;
- debug(F000,"XXX. q",q,c);
- }
- if (c == ':') { /* start:length */
- if ((x2 > -1) && ((x1 + x2) <= k)) {
- q[x1+x2] = NUL;
- }
- debug(F000,"XXX: q",q,c);
- } else if (c == '_') { /* start_endpos */
- if (x1 >= x2) {
- q[x1 = 0] = NUL;
- } else if (x2 < k && x2 > -1) {
- q[x2] = NUL;
- }
- debug(F000,"XXX_ q",q,c);
- }
- vp = q+x1;
- } else vp = NULL;
- } else vp = NULL;
- }
- debug(F110,"XXX vnambuf",vnambuf,0);
- debug(F000,"XXX c","",c);
- debug(F101,"XXX x1","",x1);
- debug(F101,"XXX x2","",x2);
- debug(F110,"XXX result",vp,0);
- #ifdef DEBUG
- if (deblog) {
- if (!vp) {
- } else {
- k = strlen(vp);
- }
- }
- #endif /* DEBUG */
- }
- }
- } else { /* or */
- vp = nvlook(vnambuf); /* this way for builtin variable */
- }
- if (vp) { /* If definition not empty */
- while ((*new++ = *vp++)) /* copy it to output string. */
- if (--n2 < 0) {
- if (q) free(q);
- debug(F101,"zzstring overflow 4","",depth);
- #ifdef DVNAMBUF
- if (vnambuf) free(vnambuf);
- #endif /* DVNAMBUF */
- return(-1);
- }
- new--; /* Back up over terminating null */
- n2++; /* to allow for further deposits. */
- }
- if (q) {
- free(q);
- q = NULL;
- }
- break;
- #endif /* NOSPL */ /* Handle \nnn even if NOSPL. */
- #ifndef NOKVERBS
- case 'K':
- case 'k': {
- extern struct keytab kverbs[];
- extern int nkverbs;
- #define K_BUFLEN 30
- char kbuf[K_BUFLEN + 1]; /* Key verb name buffer */
- int x, y, z, brace = 0;
- s += 2;
- /*
- We assume that the verb name is {braced}, or it extends to the end of the
- string, s, or it ends with a space, control character, or backslash.
- */
- p = kbuf; /* Copy verb name into local buffer */
- x = 0;
- if (*s == '{') {
- s++;
- brace++;
- }
- while ((x++ < K_BUFLEN) && (*s > SP) && (*s != CMDQ)) {
- if (brace && *s == '}') {
- s++;
- break;
- }
- *p++ = *s++;
- }
- brace = 0;
- *p = NUL; /* Terminate. */
- p = kbuf; /* Point back to beginning */
- debug(F110,"zzstring kverb",p,0);
- y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
- debug(F101,"zzstring lookup",0,y);
- if (y > -1) {
- dokverb(VCMD,y);
- #ifndef NOSPL
- } else { /* Is it a macro? */
- y = mxlook(mactab,p,nmac);
- if (y > -1) {
- debug(F111,"zzstring mxlook",p,y);
- if ((z = dodo(y,NULL,cmdstk[cmdlvl].ccflgs)) > 0) {
- if (cmpush() > -1) { /* Push command parser state */
- extern int ifc;
- int ifcsav = ifc; /* Push IF condition on stack */
- y = parser(1); /* New parser to execute macro */
- cmpop(); /* Pop command parser */
- ifc = ifcsav; /* Restore IF condition */
- if (y == 0) { /* No errors, ignore actions */
- p = mrval[maclvl+1]; /* If OK set return val */
- if (p == NULL) p = "";
- }
- } else { /* Can't push any more */
- debug(F101,"zzstring pushed too deep","",depth);
- printf(
- "\n?Internal error: zzstring stack overflow\n"
- );
- while (cmpop() > -1);
- p = "";
- }
- }
- }
- #endif /* NOSPL */
- }
- break;
- }
- #endif /* NOKVERBS */
- default: /* Maybe it's a backslash code */
- y = xxesc(&s); /* Go interpret it */
- if (y < 0) { /* Upon failure */
- *new++ = (char) x; /* Just quote the next character */
- s += 2; /* Move past the pair */
- n2 -= 2;
- if (n2 < 0) {
- debug(F101,"zzstring overflow 5","",depth);
- #ifdef DVNAMBUF
- if (vnambuf) free(vnambuf);
- #endif /* DVNAMBUF */
- return(-1);
- }
- continue; /* and go back for more */
- } else {
- *new++ = (char) y; /* else deposit interpreted value */
- if (--n2 < 0) {
- debug(F101,"zzstring overflow 6","",depth);
- #ifdef DVNAMBUF
- if (vnambuf) free(vnambuf);
- #endif /* DVNAMBUF */
- return(-1);
- }
- }
- }
- }
- *new = NUL; /* Terminate the new string */
- debug(F010,"zzstring while exit",*s2,0);
- depth--; /* Adjust stack depth gauge */
- *s2 = new; /* Copy results back into */
- *n = n2; /* the argument addresses */
- debug(F101,"zzstring ok","",depth);
- #ifdef DVNAMBUF
- if (vnambuf) free(vnambuf);
- #endif /* DVNAMBUF */
- return(0); /* and return. */
- }
- #endif /* NOICP */
|