cvs.patches.rse 148 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839
  1. Index: src/README.RSE
  2. ===================================================================
  3. RCS file: src/README.RSE
  4. diff -N src/README.RSE
  5. --- /dev/null 1 Jan 1970 00:00:00 -0000
  6. +++ src/README.RSE 28 Dec 2002 11:23:25 -0000
  7. @@ -0,0 +1,338 @@
  8. +
  9. + CVS RSE Patches
  10. + ===============
  11. +
  12. + This is the patched version of CVS from Ralf S. Engelschall
  13. + <rse@engelschall.com> - an enhanced version of the official CVS
  14. + version 1.11.4 (see http://www.cvshome.org/).
  15. +
  16. + The following changes against the vendor CVS version are provided:
  17. + - new `cvs pserverd' for running stand-alone pserver daemons
  18. + - support for an `admininfo' hook to ACL `cvs admin' commands.
  19. + - support for an `importinfo' hook to ACL `cvs import' commands.
  20. + - support for a `-h<handle>' option to `cvs diff' for compressed time spec.
  21. + - allow a hard-coded CVS super-user to override the CVS user via $CVSUSER
  22. + - support for .cvsrc files in both $HOME and working and its parent dirs
  23. + - support for $HOME/.cvsroot to alias CVSROOTs and to support root mirrors
  24. + - support global but command specific options in .cvsrc files
  25. + - support for stand-alone external custom commands `cvs <command>'
  26. + - support for prolog and epilog command line hooks
  27. + - support `$LocalId$, a local keyword variant of `$Id$'
  28. + - support `$CVSHeader$, a variant of `$Header$', but without root path
  29. + - new `cvs -u' option in addition to `cvs -n' for _REAL_ read-only access
  30. + - support for additional `%x' variables on `loginfo' hook command lines
  31. + - support a `UMask=<mask>' variable in `$CVSROOT/CVSROOT/config'
  32. + - speeded up `cvs update' by sending whole file if smaller than the diff
  33. + - disabled keyword expansions during branch merges
  34. + - adjusted `cvs diff -rHEAD' to be consistent with other commands
  35. + - set `$LOGNAME' to the real user and not the CVS user
  36. + - support for `HistoryFile=<rel-path-under-CVSROOT>' variable in config.
  37. + - use prefix 'T' ("touched/tagged") instead of 'U' ("updated") on `cvs import'
  38. + - allow `LockDir' configuration directive to use relative paths
  39. + - additional SetUID/SetGID support for `cvs server' situations.
  40. + - new global --map-root=/oldpath:/newpath option for mapping root paths
  41. + - support for wildcards in CVSROOT/passwd files to decrease admin efforts
  42. + - various cosmetic changes
  43. +
  44. + Some of my RSE functional patches are only useful for the server side,
  45. + others are also useful on the client side. All source patches to
  46. + *.[ch] files were entirely wrapped with ``#ifdef RSE_PATCH_<NAME> ...
  47. + #endif'' pairs. So, a particular patch is enabled by building CVS with
  48. + -DRSE_PATCH_<NAME>. All patches are enabled with -DRSE_PATCHES.
  49. +
  50. + Ralf S. Engelschall
  51. + rse@engelschall.com
  52. + www.engelschall.com
  53. + ________________________________________________________________________
  54. +
  55. + The following particular patches are available:
  56. +
  57. + RSE_PATCH_CVSRC:
  58. + In addition to processing `$HOME/.cvsrc', process also `.cvsrc'
  59. + files in the current working directory and the parent directories of
  60. + the current working directory. This allows one to use for instance a
  61. + `commit -m ""' locally (as used for GNU Pth development where CVS is
  62. + only used for plain revision control and not for bookkeeping changes
  63. + or group communication - instead a plain manually edited ChangeLog
  64. + exists) or `commit -d <master>' (if working with a local repository
  65. + copy). Additionally this adds support for quoted strings inside
  66. + .cvsrc files.
  67. + [Origin: Ralf S. Engelschall]
  68. +
  69. + RSE_PATCH_CVSROOT:
  70. + This adds support for a new dot-file ~/.cvsroot which is used
  71. + optionally by CVS. It can be used by the user to configure a
  72. + nickname for a CVS repository root (the master location) plus a
  73. + possibly existing local repository copy (the slave location). An
  74. + entry in ~/.cvsroot is of the format ``<nickname> <master-path>
  75. + [<slave-path> [<sync-prog>]]''. Those entries can be either created
  76. + manually in ~/.cvsroot or with the `cvs root -e' command.
  77. +
  78. + The idea is this: if a global `-d' option is used with <nickname> it is
  79. + automatically expanded to <master-path>. If no global `-d' option is used,
  80. + the CVS command is checked. If it is one of the commands which are known
  81. + to CVS to modify the repository, and the $CVSROOT or CVS/Root specify a
  82. + slave location, the repository is switched to the corresponding master
  83. + location (because modifications have to be performed there). If the
  84. + command is one of the commands which are known to CVS to NOT modify the
  85. + repository, and the $CVSROOT or CVS/Root specify a master location, the
  86. + repository is switched to the corresponding slave location (because the
  87. + slave location is faster than the master location per definition).
  88. +
  89. + After a modifying operation, CVS can either run a synchronization job
  90. + automatically to bring slave in sync with master again or the user can run
  91. + `cvs root -s <nickname>' manually to perform this task.
  92. + [Origin: Ralf S. Engelschall]
  93. +
  94. + RSE_PATCH_GLOBALOPTION:
  95. + RSE_PATCH_GLOBALOPTION_PARTLY:
  96. + By default, global options in `.cvsrc' files are specified with a
  97. + `cvs' prefix. These options then apply to _all_ cvs commands. If
  98. + RSE_PATCH_GLOBALOPTION is enabled, a second pass is done where all
  99. + global options are read with prefix `cvs/<command>' where <command>
  100. + is the official cvs command (for instance `commit' or `checkout',
  101. + even if `ci' or `co' are used on the command line). This is useful
  102. + for instance to override CVSROOT in commit commands if using a local
  103. + repository copy. The drawback of this feature is that it obviously
  104. + slows down cvs calls, because a second pass has to be done. But
  105. + usually this feature is intended only for use with `commit', `tag',
  106. + `rtag', `history', `admin', `import' and `rdiff' commands, so if
  107. + RSE_PATCH_GLOBALOPTION_PARTLY is additionally enabled, this second
  108. + pass is only done for those commands (which is the recommended use
  109. + of this feature).
  110. + [Origin: Ralf S. Engelschall]
  111. +
  112. + RSE_PATCH_CUSTOMCMD:
  113. + This provides an additional global option `-C
  114. + <cmd-name>:<cmd-program>' which defines an additional CVS command
  115. + <cmd-name>. It is intended for use on `cvs' lines inside .cvsrc
  116. + files. The effect of having `cvs -Csync:$CVSROOT/CVSROOT/sync' in a
  117. + .cvsrc file is (and assuming $CVSROOT is /e/ossp/cvs) that if you
  118. + run `cvs sync <arg1> <arg2>', CVS executes `/e/ossp/cvs/CVSROOT/sync
  119. + <arg1> <arg2>'. So this is a way to externally extend CVS with
  120. + additional commands.
  121. + [Origin: Ralf S. Engelschall]
  122. +
  123. + RSE_PATCH_PROLOGEPILOG:
  124. + Provides the two additional CVS options `-P <program>' and `-E
  125. + <program>' for running prolog and epilog programs before and
  126. + after the usual CVS processing. This is mainly intended as local
  127. + hooks for implicitly wrapping CVS commands (without having to
  128. + create slow wrapping shell scripts, etc.). Developers usually
  129. + use it to automatically start their RSYNC command to update the
  130. + local repository copy after a commit. The <program> is called
  131. + with four arguments: $1 is either `prolog' or `epilog' (useful
  132. + if one just wants to use a single hook program), $2 is the cvs
  133. + command (it is `commit' even `ci' is used, etc.), $3 is the current
  134. + working directory from which the cvs command was run and $4 is the
  135. + corresponding $CVSROOT variable.
  136. + [Origin: Ralf S. Engelschall]
  137. +
  138. + RSE_PATCH_LOCALID:
  139. + Support a local keyword variant of `$Id$'. By default this is
  140. + `$LocalId$', but if -DRSE_PATCH_LOCALID_NAME=\"<name>\" is
  141. + additionally defined, then the keyword is `$<name>$'. Alternatively
  142. + one can define the name also in the `$CVSROOT/CVSROOT/config' file
  143. + with `LocalIdName=<name>'.
  144. + [Origin: NetBSD, OpenBSD, Ralf S. Engelschall]
  145. +
  146. + RSE_PATCH_CVSHEADER:
  147. + Support the `$CVSHeader' variant of `$Header$' which has the
  148. + $CVSROOT prefix stripped of from the path. This is useful because
  149. + the prefix usually useless outside the server environment.
  150. + [Origin: FreeBSD]
  151. +
  152. + RSE_PATCH_NOLOCK:
  153. + Provide a `cvs -u' option in addition to `cvs -n' to force CVS to
  154. + not create any lock files in the repository. This is for supporting
  155. + read-only access to the repository. This is useful for working
  156. + with CVS repositories on CD-ROMs and for providing anonymous CVS
  157. + services.
  158. + [Origin: NetBSD]
  159. +
  160. + RSE_PATCH_EXTRAPERCENT:
  161. + This adds extra percent expansions to `loginfo' command lines:
  162. + `%o' to expand the operation (`A' = added, `M' = modified, `R' =
  163. + removed), `%t' to expand the tag, `%d' to expand the date.
  164. + [Origin: Ralf S. Engelschall]
  165. +
  166. + RSE_PATCH_READDNEW:
  167. + If a file was re-added to the repository, log the revision in the
  168. + `commitlog' as `NONE' instead of the previous dead revision.
  169. + [Origin: NetBSD]
  170. +
  171. + RSE_PATCH_CONFIGUMASK:
  172. + Provide a `UMask=<mask>' variable in `$CVSROOT/CVSROOT/config' which
  173. + overrides the umask of the CVS server process.
  174. + [Origin: OpenBSD]
  175. +
  176. + RSE_PATCH_FASTERUPDATE:
  177. + This speeds up `cvs update' by sending the whole file over the
  178. + network if it is smaller than the diff content. This is useful for
  179. + working remotely over slow Internet links.
  180. + [Origin: OpenBSD]
  181. +
  182. + RSE_PATCH_MERGENOKEYWORD:
  183. + This disables keyword expansions during branch merges which is
  184. + very useful in long-term branching. Without this the so-called
  185. + `spurious merging conflicts' occur because the keywords cause
  186. + spurious conflicts on every merge after the first (if those text
  187. + files have been modified on the trunk since the previous merge out
  188. + to the branch).
  189. + [Origin: Jay Sachs <jsachs@iclick.com>]
  190. +
  191. + RSE_PATCH_DIFFHEAD:
  192. + This patch changes the behavior of `cvs diff -rHEAD' on branches.
  193. + HEAD here now behaves with as it does with all other CVS commands,
  194. + as a name for the head of the trunk (the old behavior of `cvs diff
  195. + -rHEAD' was to treat HEAD to mean the head of the branch, while all
  196. + the other commands already treated HEAD as the head of the trunk).
  197. + [Origin: Stephen Cameron <steve.cameron@compaq.com>]
  198. +
  199. + RSE_PATCH_LOGNAME:
  200. + This is for SUID-based CVS servers and passes in `$LOGNAME' the real
  201. + user (first field in `$CVSROOT/CVSROOT/passwd') instead of the SUID
  202. + user (third field in `$CVSROOT/CVSROOT/passwd')
  203. + [Origin: Chris Cameron]
  204. +
  205. + RSE_PATCH_HISTORYFILE:
  206. + This provides an additional `HistoryFile=<rel-path-under-CVSROOT>'
  207. + config variable which allows one to store the history file under a
  208. + different path.
  209. + [Origin: Ralf S. Engelschall]
  210. +
  211. + RSE_PATCH_SMARTCONFIG:
  212. + This allows one to add custom configuration variables to
  213. + `$CVSROOT/CVSROOT/config' without having CVS complain about them and
  214. + fail with an error. This is useful to use the config file also for
  215. + storing config details for the various admin scripts.
  216. + [Origin: Ralf S. Engelschall]
  217. +
  218. + RSE_PATCH_ADMININFO:
  219. + This adds the feature of an extra `$CVSROOT/CVSROOT/admininfo'
  220. + configuration file which can be used for access controlling `cvs
  221. + admin' commands similar to `cvs tag' (which is already done
  222. + with `taginfo') and `cvs commit' (which is already done with
  223. + `commitinfo'). The specified filters in this info file receive the
  224. + absolute repository directory as the first argument, followed by all
  225. + names of files in this directory on which the `cvs admin' command
  226. + should be performed. If the filter returns 0, the operation is
  227. + allowed. If it returns not 0, the operation is denied.
  228. + [Origin: Ralf S. Engelschall]
  229. +
  230. + RSE_PATCH_IMPORTINFO:
  231. + This adds the feature of an extra `$CVSROOT/CVSROOT/importinfo'
  232. + configuration file which can be used for access controlling
  233. + `cvs import'. The specified filters in this info file receives
  234. + the following arguments: the vendor branch tag, the (absolute)
  235. + repository path which is the root of the import and then zero or
  236. + more relative file paths under this repository. If the filter
  237. + returns 0, the operation is allowed. If it returns not 0, the
  238. + operation is denied.
  239. + [Origin: Ralf S. Engelschall]
  240. +
  241. + RSE_PATCH_HANDLE:
  242. + This adds a convinient `-h<handle>' option to `cvs diff'. `<handle>'
  243. + is a string of the format `[!]YYMMDDhhmmssoo' (YY=year, MM=month,
  244. + DD=day, hh=hour, mm=minute, ss=second, oo=offset) which internally
  245. + is expanded into two `-D' options. The first date is the equivalent
  246. + of `YYMMDDhhmmss', the second is the first plus `oo' seconds. If the
  247. + exclamation mark is used, the two dates are reversed. The intention
  248. + is that such a handle is a short form for a time range and can be
  249. + easily computed in a commit log mail. So the `-h' option can be used
  250. + to easily get the corresponding change diff for branch merging or
  251. + backing out. The only restriction is that time-overlapping commits
  252. + break the solution, of course. But in practice this is no real
  253. + problem.
  254. + [Origin: Ralf S. Engelschall]
  255. +
  256. + RSE_PATCH_IMPORTTOUCH:
  257. + This prints the prefix 'T' (for "touched/tagged only") instead
  258. + of 'U' (for "updated") on `cvs import' if no modifications were
  259. + imported, i.e., no new revision is comitted. This way one can
  260. + distinguish those imports from the regular updated ones which also
  261. + print 'U' and which actually commit a new revision.
  262. + [Origin: Ralf S. Engelschall]
  263. +
  264. + RSE_PATCH_RELLOCKDIR:
  265. + This allows the `LockDir' configuration directive to use relative
  266. + paths to $CVSROOT, because without this patch a relative path would
  267. + be relative to the current working directory (which is useless).
  268. + [Origin: Stefan Monnier <foo@acm.com>]
  269. +
  270. + RSE_PATCH_CVSUSER:
  271. + This allows the Unix user RSE_PATCH_CVSUSER_CALLER (per default
  272. + "ossp-cvs") to use the environment variable CVSUSER to override the
  273. + login name CVS uses to identify the caller. This is intended for use
  274. + with a CVS setuid wrapper program or for use manually by the CVS
  275. + administrator.
  276. + [Origin: Ralf S. Engelschall]
  277. +
  278. + RSE_PATCH_SETXID:
  279. + This is a variant of CVS's SETXID_SUPPORT. It allows one to
  280. + setuid/setgid the CVS executable. Then CVS deletes these effective
  281. + uid/gid for all commands except for the "cvs server" command. For
  282. + this and only this it switches the real uid/gid to the effective
  283. + uid/gid. This way one can use the repository as a black-box. One
  284. + just has to be make sure that only :ext: (for remote) and :fork:
  285. + (for local) access is used.
  286. + [Origin: Ralf S. Engelschall]
  287. +
  288. + RSE_PATCH_PSERVERD:
  289. + This adds an additional `cvs pserverd' command which is like `cvs
  290. + pserver' except that it uses own builtin TCP/IP socket listening and
  291. + forking facility. The advantages over using inetd are: pserverd can
  292. + listen to particular host addresses/ports (inetd always binds to all
  293. + interfaces of a host), it can optionally chroot(2) for a particular
  294. + user only (usually "anonymous"), it can optionally force the global
  295. + options -l -u for a particular user only (usually "anonymous"), it
  296. + can detach into background and run as a real daemon, etc.
  297. + [Origin: Ralf S. Engelschall]
  298. +
  299. + RSE_PATCH_MAPROOT
  300. + This adds a global --map-root=/oldpath:/newpath option which
  301. + allows one to map virtual/incoming CVSROOT values to real ones.
  302. + For instance this can be used together with --allow-root and "cvs
  303. + pserverd" to map the intuitive virtual path to the physical path on
  304. + the host.
  305. + [Origin: Ralf S. Engelschall]
  306. +
  307. + RSE_PATCH_HASHFUNC:
  308. + This replaces the obscure hash function in src/hash.c with D.J.Berstein's
  309. + popular "times 33" function which is faster to compute and still
  310. + distributes very well.
  311. + [Origin: Ralf S. Engelschall]
  312. +
  313. + RSE_PATCH_ADDFILEATTR:
  314. + Let the default file attributes set on newly added files.
  315. + [Origin: Noel Yap]
  316. +
  317. + RSE_PATCH_WILDPASSWD:
  318. + This allows wildcards ("*") in CVSROOT/passwd. That allows one to
  319. + just do "*:ULtgRLXo7NRxs:cvsuser" which would let absolutely anyone
  320. + use CVS provided they know the password. It would also let you do
  321. + things like "*:*:cvsuser" to let only authorized system users use
  322. + CVS using their system passwords.
  323. + [Larry Jones <larry.jones@sdrc.com>]
  324. +
  325. + RSE_PATCH_CVSPID:
  326. + This provides an environment variable $CVSPID which contains the process
  327. + id of the parent CVS process. This is usually used inside scripts called
  328. + from *info files in order to have a unique session handle (for instance
  329. + for a common temporary directory "/tmp/cvs.foo.$CVSPID", etc).
  330. + [Origin: Rich Salz <rsalz@caveosystems.com>]
  331. +
  332. + RSE_PATCH_BUGFIX:
  333. + This enabled various bugfixes which are still not present in the
  334. + official CVS version.
  335. + [Origin: Ralf S. Engelschall]
  336. +
  337. + RSE_PATCH_COSMETICS:
  338. + This just enables some cosmetic changes to various output messages.
  339. + [Origin: Ralf S. Engelschall]
  340. +
  341. + RSE_PATCH_COSMETICS_HARD:
  342. + This just enables more cosmetic changes to various output messages.
  343. + The difference is that these break "make check".
  344. + [Origin: Ralf S. Engelschall]
  345. +
  346. Index: src/add.c
  347. ===================================================================
  348. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/add.c,v
  349. retrieving revision 1.1.1.5
  350. diff -u -d -r1.1.1.5 add.c
  351. --- src/add.c 24 Oct 2002 18:38:36 -0000 1.1.1.5
  352. +++ src/add.c 28 Dec 2002 10:48:11 -0000
  353. @@ -799,6 +799,9 @@
  354. li->type = T_TITLE;
  355. li->tag = xstrdup (tag);
  356. li->rev_old = li->rev_new = NULL;
  357. +#ifdef RSE_PATCH_EXTRAPERCENT
  358. + li->date = NULL;
  359. +#endif
  360. p->data = (char *) li;
  361. (void) addnode (ulist, p);
  362. Update_Logfile (rcsdir, message, (FILE *) NULL, ulist);
  363. Index: src/admin.c
  364. ===================================================================
  365. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/admin.c,v
  366. retrieving revision 1.1.1.7
  367. diff -u -d -r1.1.1.7 admin.c
  368. --- src/admin.c 28 Dec 2002 18:01:30 -0000 1.1.1.7
  369. +++ src/admin.c 28 Dec 2002 20:14:05 -0000
  370. @@ -139,6 +139,161 @@
  371. dat->av[dat->ac++] = newelt;
  372. }
  373. +#ifdef RSE_PATCH_ADMININFO
  374. +
  375. +static List *admininfo_dlist;
  376. +static List *admininfo_flist;
  377. +
  378. +static void admininfo_dlist_delproc(Node *);
  379. +static int admininfo_info_runproc(char *, char *);
  380. +static int admininfo_flist_runproc(Node *, void *);
  381. +
  382. +struct admininfo_dlist_st {
  383. + List *flist;
  384. +};
  385. +
  386. +/* file callback function for recursive processing */
  387. +static int
  388. +admininfo_fileproc (
  389. + void *callerdat,
  390. + struct file_info *finfo)
  391. +{
  392. + char *xdir;
  393. + Node *dnode;
  394. + Node *fnode;
  395. +
  396. + /* determine current directory */
  397. + if (finfo->update_dir[0] == '\0')
  398. + xdir = ".";
  399. + else
  400. + xdir = finfo->update_dir;
  401. +
  402. + /* find directory node in directory list */
  403. + if ((dnode = findnode(admininfo_dlist, xdir)) != NULL)
  404. + /* take already existing file list */
  405. + admininfo_flist = ((struct admininfo_dlist_st *)dnode->data)->flist;
  406. + else {
  407. + /* create a new file list */
  408. + struct admininfo_dlist_st *dlist;
  409. +
  410. + admininfo_flist = getlist();
  411. +
  412. + dlist = (struct admininfo_dlist_st *)xmalloc(sizeof(struct admininfo_dlist_st));
  413. + dlist->flist = admininfo_flist;
  414. +
  415. + dnode = getnode();
  416. + dnode->type = UPDATE;
  417. + dnode->key = xstrdup(xdir);
  418. + dnode->data = (char *)dlist;
  419. + dnode->delproc = admininfo_dlist_delproc;
  420. +
  421. + (void)addnode(admininfo_dlist, dnode);
  422. + }
  423. +
  424. + /* create new file node in file list */
  425. + fnode = getnode();
  426. + fnode->type = UPDATE;
  427. + fnode->key = xstrdup(finfo->file);
  428. + fnode->data = NULL;
  429. + fnode->delproc = NULL;
  430. + (void)addnode(admininfo_flist, fnode);
  431. +
  432. + return 0;
  433. +}
  434. +
  435. +/* delete a directory list node */
  436. +static void
  437. +admininfo_dlist_delproc(
  438. + Node *p)
  439. +{
  440. + struct admininfo_dlist_st *dlist;
  441. +
  442. + dlist = (struct admininfo_dlist_st *)p->data;
  443. + dellist(&dlist->flist);
  444. + free(dlist);
  445. + return;
  446. +}
  447. +
  448. +/* file callback function for recursive processing (when done) */
  449. +static int
  450. +admininfo_filesdoneproc(
  451. + void *callerdat,
  452. + int err,
  453. + char *repos,
  454. + char *update_dir,
  455. + List *entries)
  456. +{
  457. + Node *dnode;
  458. + int n;
  459. +
  460. + /* find file list for update directory */
  461. + if ((dnode = findnode(admininfo_dlist, update_dir)) != NULL)
  462. + admininfo_flist = ((struct admininfo_dlist_st *)dnode->data)->flist;
  463. + else
  464. + admininfo_flist = (List *)NULL;
  465. + if ( (admininfo_flist == NULL)
  466. + || (admininfo_flist->list->next == admininfo_flist->list))
  467. + return err;
  468. +
  469. + /* parse and execute the admininfo configuration */
  470. + if ((n = Parse_Info(CVSROOTADM_ADMININFO, repos, admininfo_info_runproc, 1)) > 0) {
  471. + error(0, 0, "Pre-admin check failed");
  472. + err += n;
  473. + }
  474. +
  475. + return err;
  476. +}
  477. +
  478. +/* admininfo configuration entry callback */
  479. +static int
  480. +admininfo_info_runproc(repository, filter)
  481. + char *repository;
  482. + char *filter;
  483. +{
  484. + char *s, *cp;
  485. + int rv;
  486. +
  487. + /* if possible, do an own check to make sure that filter really exists */
  488. + if (filter[0] == '/') {
  489. + s = xstrdup(filter);
  490. + for (cp = s; *cp; cp++) {
  491. + if (isspace((unsigned char)*cp)) {
  492. + *cp = '\0';
  493. + break;
  494. + }
  495. + }
  496. + if (!isfile(s)) {
  497. + error (0, errno, "cannot find pre-admin filter '%s'", s);
  498. + free(s);
  499. + return (1);
  500. + }
  501. + free(s);
  502. + }
  503. +
  504. + /* construct the filter command */
  505. + run_setup(filter);
  506. + run_arg(repository);
  507. + walklist(admininfo_flist, admininfo_flist_runproc, NULL);
  508. +
  509. + /* execute the filter command */
  510. + rv = run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
  511. +
  512. + return rv;
  513. +}
  514. +
  515. +/* file list callback for adding file as another program argument */
  516. +static int
  517. +admininfo_flist_runproc(
  518. + Node *p,
  519. + void *closure)
  520. +{
  521. + if (p->key != NULL)
  522. + run_arg(p->key);
  523. + return 0;
  524. +}
  525. +
  526. +#endif /* RSE_PATCH_ADMININFO */
  527. +
  528. int
  529. admin (argc, argv)
  530. int argc;
  531. @@ -516,6 +671,20 @@
  532. #endif /* CLIENT_SUPPORT */
  533. lock_tree_for_write (argc, argv, 0, W_LOCAL, 0);
  534. +
  535. +#ifdef RSE_PATCH_ADMININFO
  536. + /* allow `CVSROOT/CVSROOT/admininfo' filters to check whether the
  537. + `cvs admin' operation is authorized for all the specified files
  538. + in the repository */
  539. + admininfo_dlist = getlist();
  540. + err = start_recursion(admininfo_fileproc, admininfo_filesdoneproc,
  541. + (DIRENTPROC) NULL, (DIRLEAVEPROC) NULL, NULL,
  542. + argc, argv, 0, W_LOCAL, 0, 0, (char *)NULL, 1);
  543. + if (err) {
  544. + Lock_Cleanup();
  545. + error(1, 0, "correct above errors first!");
  546. + }
  547. +#endif
  548. err = start_recursion (admin_fileproc, (FILESDONEPROC) NULL, admin_dirproc,
  549. (DIRLEAVEPROC) NULL, (void *)&admin_data,
  550. Index: src/buffer.c
  551. ===================================================================
  552. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/buffer.c,v
  553. retrieving revision 1.1.1.3
  554. diff -u -d -r1.1.1.3 buffer.c
  555. --- src/buffer.c 6 Dec 2002 19:47:58 -0000 1.1.1.3
  556. +++ src/buffer.c 28 Dec 2002 10:48:12 -0000
  557. @@ -1381,7 +1381,7 @@
  558. int closefp = 1;
  559. /* Must be a pipe or a socket. What could go wrong? */
  560. - assert (fstat ( fileno (bc->fp), &s ) != -1);
  561. + assert (fstat ( fileno (bc->fp), &s ) != -1); /* RSE XXX */
  562. /* Flush the buffer if we can */
  563. if (buf->flush)
  564. Index: src/checkin.c
  565. ===================================================================
  566. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/checkin.c,v
  567. retrieving revision 1.1.1.1
  568. diff -u -d -r1.1.1.1 checkin.c
  569. --- src/checkin.c 22 Feb 1998 19:46:46 -0000 1.1.1.1
  570. +++ src/checkin.c 16 Feb 2002 12:36:09 -0000
  571. @@ -32,14 +32,27 @@
  572. Vers_TS *vers;
  573. int set_time;
  574. char *tocvsPath = NULL;
  575. +#ifdef RSE_PATCH_COSMETICS_HARD
  576. + int flags;
  577. +#endif
  578. /* Hmm. This message goes to stdout and the "foo,v <-- foo"
  579. message from "ci" goes to stderr. This doesn't make a whole
  580. lot of sense, but making everything go to stdout can only be
  581. gracefully achieved once RCS_checkin is librarified. */
  582. +#ifdef RSE_PATCH_COSMETICS_HARD
  583. + if (!really_quiet) {
  584. +#endif
  585. cvs_output ("Checking in ", 0);
  586. cvs_output (finfo->fullname, 0);
  587. +#ifdef RSE_PATCH_COSMETICS_HARD
  588. + cvs_output ("\n", 0);
  589. +#else
  590. cvs_output (";\n", 0);
  591. +#endif
  592. +#ifdef RSE_PATCH_COSMETICS_HARD
  593. + }
  594. +#endif
  595. tocvsPath = wrap_tocvs_process_file (finfo->file);
  596. if (!noexec)
  597. @@ -56,7 +69,14 @@
  598. if (finfo->rcs == NULL)
  599. finfo->rcs = RCS_parse (finfo->file, finfo->repository);
  600. +#ifdef RSE_PATCH_COSMETICS_HARD
  601. + flags = RCS_FLAGS_KEEPFILE;
  602. + if (really_quiet || quiet)
  603. + flags |= RCS_FLAGS_QUIET;
  604. + switch (RCS_checkin (finfo->rcs, NULL, message, rev, flags))
  605. +#else
  606. switch (RCS_checkin (finfo->rcs, NULL, message, rev, RCS_FLAGS_KEEPFILE))
  607. +#endif
  608. {
  609. case 0: /* everything normal */
  610. @@ -118,6 +138,16 @@
  611. vers->options, vers->tag, vers->date, (char *) 0);
  612. history_write (type, NULL, vers->vn_rcs,
  613. finfo->file, finfo->repository);
  614. +
  615. +#ifdef RSE_PATCH_ADDFILEATTR
  616. + if (type == 'A') {
  617. + char *attr;
  618. + if ((attr = fileattr_getall(NULL)) != NULL) {
  619. + fileattr_setall(finfo->file, attr);
  620. + free(attr);
  621. + }
  622. + }
  623. +#endif
  624. if (tocvsPath)
  625. if (unlink_file_dir (tocvsPath) < 0)
  626. Index: src/checkout.c
  627. ===================================================================
  628. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/checkout.c,v
  629. retrieving revision 1.1.1.6
  630. diff -u -d -r1.1.1.6 checkout.c
  631. --- src/checkout.c 4 Dec 2002 19:10:20 -0000 1.1.1.6
  632. +++ src/checkout.c 28 Dec 2002 10:48:12 -0000
  633. @@ -191,7 +191,11 @@
  634. case 'p':
  635. pipeout = 1;
  636. run_module_prog = 0; /* don't run module prog when piping */
  637. +#ifdef RSE_PATCH_NOLOCK
  638. + noexec = nolock = 1; /* so no locks will be created */
  639. +#else
  640. noexec = 1; /* so no locks will be created */
  641. +#endif
  642. break;
  643. case 'c':
  644. cat = 1;
  645. Index: src/client.c
  646. ===================================================================
  647. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/client.c,v
  648. retrieving revision 1.1.1.7
  649. diff -u -d -r1.1.1.7 client.c
  650. --- src/client.c 28 Dec 2002 18:01:30 -0000 1.1.1.7
  651. +++ src/client.c 28 Dec 2002 20:14:06 -0000
  652. @@ -104,6 +104,9 @@
  653. int status PROTO((int argc, char **argv));
  654. int tag PROTO((int argc, char **argv));
  655. int update PROTO((int argc, char **argv));
  656. +#ifdef RSE_PATCH_RLIST
  657. +int list PROTO((int argc, char **argv));
  658. +#endif
  659. /* All the response handling functions. */
  660. static void handle_ok PROTO((char *, int));
  661. @@ -251,14 +254,34 @@
  662. : Name_Root ((char *) NULL, (char *) NULL));
  663. }
  664. +#ifdef RSE_PATCH_CVSROOT
  665. + {
  666. + int cvsroot_alias;
  667. + cvsroot_type *e;
  668. +
  669. + cvsroot_alias = 0;
  670. + if ((e = cvsroot_lookup(NULL, current_parsed_root->original, NULL)) != NULL)
  671. + if (strcmp(e->slavepath, this_root) == 0)
  672. + cvsroot_alias = 1;
  673. + if ((e = cvsroot_lookup(NULL, NULL, this_root)) != NULL)
  674. + if (strcmp(e->masterpath, current_parsed_root->original) == 0)
  675. + cvsroot_alias = 1;
  676. +#endif
  677. +
  678. /* Now check the value for root. */
  679. if (this_root && current_parsed_root
  680. +#ifdef RSE_PATCH_CVSROOT
  681. + && !cvsroot_alias
  682. +#endif
  683. && (strcmp (this_root, current_parsed_root->original) != 0))
  684. {
  685. /* Don't send this, since the CVSROOTs don't match. */
  686. free (this_root);
  687. return 1;
  688. }
  689. +#ifdef RSE_PATCH_CVSROOT
  690. + }
  691. +#endif
  692. free (this_root);
  693. }
  694. @@ -2762,6 +2785,9 @@
  695. /* Add a directory name to the list of those sent to the
  696. server. */
  697. if (update_dir && (*update_dir != '\0')
  698. +#ifdef RSE_PATCH_CVSROOT
  699. + /* FIXME: alternative to RSE_PATCH_CVSROOT?! */
  700. +#endif
  701. && (strcmp (update_dir, ".") != 0)
  702. && (findnode (dirs_sent_to_server, update_dir) == NULL))
  703. {
  704. @@ -4559,6 +4585,18 @@
  705. error (1, 0,
  706. "This server does not support the global -n option.");
  707. }
  708. +#ifdef RSE_PATCH_NOLOCK
  709. + if (nolock && !noexec)
  710. + {
  711. + if (have_global)
  712. + {
  713. + send_to_server ("Global_option -u\012", 0);
  714. + }
  715. + else
  716. + error (1, 0,
  717. + "This server does not support the global -u option.");
  718. + }
  719. +#endif
  720. if (quiet)
  721. {
  722. if (have_global)
  723. Index: src/commit.c
  724. ===================================================================
  725. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/commit.c,v
  726. retrieving revision 1.1.1.7
  727. diff -u -d -r1.1.1.7 commit.c
  728. --- src/commit.c 28 Dec 2002 18:01:30 -0000 1.1.1.7
  729. +++ src/commit.c 28 Dec 2002 20:14:06 -0000
  730. @@ -308,6 +308,9 @@
  731. data->type = status;
  732. data->tag = xstrdup (vers->tag);
  733. data->rev_old = data->rev_new = NULL;
  734. +#ifdef RSE_PATCH_EXTRAPERCENT
  735. + data->date = xstrdup (vers->ts_user);
  736. +#endif
  737. node->type = UPDATE;
  738. node->delproc = update_delproc;
  739. @@ -996,7 +999,16 @@
  740. xmalloc (sizeof (struct logfile_info)));
  741. li->type = status;
  742. li->tag = xstrdup (vers->tag);
  743. +#ifdef RSE_PATCH_READDNEW
  744. + /* If the file was re-added, we want the revision in the commitlog
  745. + to be NONE, not the previous dead revision. */
  746. + li->rev_old = status == T_ADDED ? NULL : xstrdup (vers->vn_rcs);
  747. +#else
  748. li->rev_old = xstrdup (vers->vn_rcs);
  749. +#endif
  750. +#ifdef RSE_PATCH_EXTRAPERCENT
  751. + li->date = xstrdup (vers->ts_user);
  752. +#endif
  753. li->rev_new = NULL;
  754. p->data = (char *) li;
  755. (void) addnode (ulist, p);
  756. @@ -2314,6 +2326,10 @@
  757. free (li->rev_old);
  758. if (li->rev_new)
  759. free (li->rev_new);
  760. +#ifdef RSE_PATCH_EXTRAPERCENT
  761. + if (li->date)
  762. + free (li->date);
  763. +#endif
  764. free (li);
  765. }
  766. Index: src/create_adm.c
  767. ===================================================================
  768. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/create_adm.c,v
  769. retrieving revision 1.1.1.5
  770. diff -u -d -r1.1.1.5 create_adm.c
  771. --- src/create_adm.c 20 Sep 2002 02:48:59 -0000 1.1.1.5
  772. +++ src/create_adm.c 28 Dec 2002 10:48:13 -0000
  773. @@ -21,6 +21,41 @@
  774. or after which CVS might do something non-useful. If WARN is zero, then
  775. don't print warnings; all errors are fatal then. */
  776. +#ifdef RSE_PATCH_CVSROOT
  777. +static int local_template_cb(char *repository, char *template)
  778. +{
  779. + FILE *fpIN, *fpOUT;
  780. + char buf[1024];
  781. + size_t n;
  782. +
  783. + if ((fpOUT = CVS_FOPEN(CVSADM_TEMPLATE, "w+")) == NULL)
  784. + error(1, errno, "cannot open %s for writing", CVSADM_TEMPLATE);
  785. + if ((fpIN = CVS_FOPEN(template, "r")) == NULL)
  786. + error(1, errno, "cannot open %s for reading", template);
  787. + while (!feof(fpIN)) {
  788. + n = fread(buf, 1, sizeof buf, fpIN);
  789. + if (n == 0) {
  790. + if (ferror(fpIN))
  791. + error(0, errno, "cannot read template file %s", template);
  792. + break;
  793. + }
  794. + fwrite(buf, 1, n, fpOUT);
  795. + }
  796. + fclose(fpIN);
  797. + fclose(fpOUT);
  798. + return 0;
  799. +}
  800. +
  801. +static void local_template(char *update_dir, char *repository)
  802. +{
  803. + cvsroot_type *e;
  804. +
  805. + if ((e = cvsroot_lookup(NULL, NULL, current_parsed_root->original)) != NULL)
  806. + Parse_Info(CVSROOTADM_RCSINFO, repository, local_template_cb, 1);
  807. + return;
  808. +}
  809. +#endif
  810. +
  811. int
  812. Create_Admin (dir, update_dir, repository, tag, date, nonbranch, warn,
  813. dotemplate)
  814. @@ -174,6 +209,20 @@
  815. fprintf (stderr, "%c<- Create_Admin\n",
  816. (server_active) ? 'S' : ' ');
  817. }
  818. +#endif
  819. +#ifdef RSE_PATCH_CVSROOT
  820. + /* Under our "cvs root" feature, checkouts are performed
  821. + locally (from the repository copy and without C/S), but commits
  822. + are performed remotely (to the master repository with C/S).
  823. + Unfortunately, CVS "optimizes" processing and doesn't provide
  824. + CVS/Template files on non-C/S checkouts. This would mean that
  825. + if "cvs root" feature is used, the rcsinfo-configured templates
  826. + are never used. So, if and only if we do a non-C/S checkout (or
  827. + similar operation which creates CVS/Template) _and_ the current
  828. + CVSROOT is known to be a repository copy, we force the creation
  829. + of CVS/Template. */
  830. + if (!server_active && !(current_parsed_root->isremote) && dotemplate)
  831. + local_template(update_dir, repository);
  832. #endif
  833. free (reposcopy);
  834. Index: src/cvs.h
  835. ===================================================================
  836. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/cvs.h,v
  837. retrieving revision 1.1.1.7
  838. diff -u -d -r1.1.1.7 cvs.h
  839. --- src/cvs.h 28 Dec 2002 18:01:30 -0000 1.1.1.7
  840. +++ src/cvs.h 28 Dec 2002 20:14:06 -0000
  841. @@ -7,6 +7,48 @@
  842. */
  843. /*
  844. + * Support for compiling in various RSE extension
  845. + */
  846. +#ifdef RSE_PATCHES
  847. +#define RSE_PATCH_CVSRC
  848. +#define RSE_PATCH_CVSROOT
  849. +#define RSE_PATCH_GLOBALOPTION
  850. +#define RSE_PATCH_GLOBALOPTION_PARTLY
  851. +#define RSE_PATCH_CUSTOMCMD
  852. +#define RSE_PATCH_PROLOGEPILOG
  853. +#define RSE_PATCH_LOCALID
  854. +#define RSE_PATCH_CVSHEADER
  855. +#define RSE_PATCH_NOLOCK
  856. +#define RSE_PATCH_EXTRAPERCENT
  857. +#define RSE_PATCH_READDNEW
  858. +#define RSE_PATCH_CONFIGUMASK
  859. +#define RSE_PATCH_FASTERUPDATE
  860. +#define RSE_PATCH_LOGNAME
  861. +#define RSE_PATCH_HISTORYFILE
  862. +#define RSE_PATCH_IMPORTINFO
  863. +#define RSE_PATCH_ADMININFO
  864. +#define RSE_PATCH_HANDLE
  865. +#define RSE_PATCH_IMPORTTOUCH
  866. +#define RSE_PATCH_RELLOCKDIR
  867. +#define RSE_PATCH_CVSUSER
  868. +#define RSE_PATCH_SETXID
  869. +#define RSE_PATCH_PSERVERD
  870. +#define RSE_PATCH_MAPROOT
  871. +#define RSE_PATCH_RLIST
  872. +#define RSE_PATCH_COSMETICS
  873. +#define RSE_PATCH_HASHFUNC
  874. +#define RSE_PATCH_ADDFILEATTR
  875. +#define RSE_PATCH_WILDPASSWD
  876. +#define RSE_PATCH_CVSPID
  877. +#define RSE_PATCH_BUGFIX
  878. +/* problematic changes, because they break "make check" */
  879. +#undef RSE_PATCH_COSMETICS_HARD
  880. +#undef RSE_PATCH_MERGENOKEYWORD
  881. +#undef RSE_PATCH_DIFFHEAD
  882. +#undef RSE_PATCH_SMARTCONFIG
  883. +#endif
  884. +
  885. +/*
  886. * basic information used in all source files
  887. *
  888. */
  889. @@ -193,6 +235,33 @@
  890. #define CVSROOTADM_WRITERS "writers"
  891. #define CVSROOTADM_PASSWD "passwd"
  892. #define CVSROOTADM_CONFIG "config"
  893. +#ifdef RSE_PATCH_ADMININFO
  894. +#define CVSROOTADM_ADMININFO "admininfo"
  895. +#endif
  896. +#ifdef RSE_PATCH_IMPORTINFO
  897. +#define CVSROOTADM_IMPORTINFO "importinfo"
  898. +#endif
  899. +
  900. +#ifdef RSE_PATCH_ALTADMINFILES
  901. +#define CVSROOTADM_MODULES_ALT "conf_modules"
  902. +#define CVSROOTADM_LOGINFO_ALT "hook_logwrite"
  903. +#define CVSROOTADM_RCSINFO_ALT "hook_logtempl"
  904. +#define CVSROOTADM_COMMITINFO_ALT "hook_commit"
  905. +#define CVSROOTADM_TAGINFO_ALT "hook_tag"
  906. +#define CVSROOTADM_EDITINFO_ALT "hook_logedit"
  907. +#define CVSROOTADM_VERIFYMSG_ALT "hook_logverify"
  908. +#define CVSROOTADM_HISTORY_ALT "data_history"
  909. +#define CVSROOTADM_VALTAGS_ALT "data_valtags"
  910. +#define CVSROOTADM_IGNORE_ALT "conf_ignore"
  911. +#define CVSROOTADM_CHECKOUTLIST_ALT "conf_checkout"
  912. +#define CVSROOTADM_WRAPPER_ALT "hook_wrapper"
  913. +#define CVSROOTADM_NOTIFY_ALT "hook_notify"
  914. +#define CVSROOTADM_USERS_ALT "conf_users"
  915. +#define CVSROOTADM_READERS_ALT "conf_readers"
  916. +#define CVSROOTADM_WRITERS_ALT "conf_writers"
  917. +#define CVSROOTADM_PASSWD_ALT "conf_passwd"
  918. +#define CVSROOTADM_CONFIG_ALT "conf_global"
  919. +#endif
  920. #define CVSNULLREPOS "Emptydir" /* an empty directory */
  921. @@ -276,6 +345,10 @@
  922. #define CVSUMASK_ENV "CVSUMASK" /* Effective umask for repository */
  923. +#ifdef RSE_PATCH_NOLOCK
  924. +#define CVSNOLOCK_ENV "CVSNOLOCK" /* do not create lock files */
  925. +#endif
  926. +
  927. /*
  928. * If the beginning of the Repository matches the following string, strip it
  929. * so that the output to the logfile does not contain a full pathname.
  930. @@ -371,6 +444,9 @@
  931. extern int use_editor;
  932. extern int cvswrite;
  933. extern mode_t cvsumask;
  934. +#ifdef RSE_PATCH_LOCALID
  935. +extern char *RCS_citag;
  936. +#endif
  937. @@ -389,6 +465,9 @@
  938. extern int trace; /* Show all commands */
  939. extern int noexec; /* Don't modify disk anywhere */
  940. +#ifdef RSE_PATCH_NOLOCK
  941. +extern int nolock; /* Don't create locks */
  942. +#endif
  943. extern int logoff; /* Don't write history entry */
  944. extern int top_level_admin;
  945. @@ -458,6 +537,27 @@
  946. void root_allow_free PROTO ((void));
  947. int root_allow_ok PROTO ((char *));
  948. +#ifdef RSE_PATCH_MAPROOT
  949. +void root_map_add PROTO ((char *, char *));
  950. +void root_map_free PROTO ((void));
  951. +int root_map_it PROTO ((char *, char **, int));
  952. +#endif
  953. +
  954. +#ifdef RSE_PATCH_CVSROOT
  955. +typedef struct {
  956. + char *nickname;
  957. + char *masterpath;
  958. + char *slavepath;
  959. + char *syncprog;
  960. +} cvsroot_type;
  961. +char *cvsroot_filename(void);
  962. +void cvsroot_free(cvsroot_type *);
  963. +cvsroot_type *cvsroot_entry_read(FILE *);
  964. +void cvsroot_entry_write(FILE *, cvsroot_type *);
  965. +cvsroot_type *cvsroot_lookup(char *, char *, char *);
  966. +void cvsroot_synchronize(cvsroot_type *, int);
  967. +#endif
  968. +
  969. char *gca PROTO((const char *rev1, const char *rev2));
  970. extern void check_numeric PROTO ((const char *, int, char **));
  971. char *getcaller PROTO((void));
  972. @@ -562,6 +662,10 @@
  973. extern void expand_wild PROTO ((int argc, char **argv,
  974. int *pargc, char ***pargv));
  975. +#ifdef RSE_PATCH_HANDLE
  976. +int handle2dates(char *, time_t *, time_t *);
  977. +#endif
  978. +
  979. #ifdef SERVER_SUPPORT
  980. extern int cvs_casecmp PROTO ((char *, char *));
  981. extern int fopen_case PROTO ((char *, char *, FILE **, char **));
  982. @@ -804,6 +908,9 @@
  983. NULL for add or import */
  984. char *rev_new; /* rev number after a commit/modify,
  985. add, or import, NULL for remove */
  986. +#ifdef RSE_PATCH_EXTRAPERCENT
  987. + char *date;
  988. +#endif
  989. };
  990. /* Wrappers. */
  991. @@ -843,6 +950,13 @@
  992. int unedit PROTO ((int argc, char **argv));
  993. int editors PROTO ((int argc, char **argv));
  994. int watchers PROTO ((int argc, char **argv));
  995. +#ifdef RSE_PATCH_CVSROOT
  996. +int root PROTO ((int argc, char **argv));
  997. +#endif
  998. +#ifdef RSE_PATCH_PSERVERD
  999. +int pserverd PROTO ((int argc, char **argv));
  1000. +int pserver_daemon PROTO ((int argc, char **argv));
  1001. +#endif
  1002. extern int annotate PROTO ((int argc, char **argv));
  1003. extern int add PROTO ((int argc, char **argv));
  1004. extern int admin PROTO ((int argc, char **argv));
  1005. @@ -872,6 +986,9 @@
  1006. extern int cvsstatus PROTO((int argc, char **argv));
  1007. extern int cvstag PROTO((int argc, char **argv));
  1008. extern int version PROTO((int argc, char **argv));
  1009. +#ifdef RSE_PATCH_RLIST
  1010. +extern int cvslist PROTO((int argc, char **argv));
  1011. +#endif
  1012. extern unsigned long int lookup_command_attribute PROTO((char *));
  1013. Index: src/cvsrc.c
  1014. ===================================================================
  1015. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/cvsrc.c,v
  1016. retrieving revision 1.1.1.3
  1017. diff -u -d -r1.1.1.3 cvsrc.c
  1018. --- src/cvsrc.c 17 Jun 2002 23:39:00 -0000 1.1.1.3
  1019. +++ src/cvsrc.c 28 Dec 2002 10:48:13 -0000
  1020. @@ -12,6 +12,203 @@
  1021. #include "cvs.h"
  1022. #include "getline.h"
  1023. +#ifdef RSE_PATCH_CVSRC
  1024. +
  1025. +#include <ctype.h>
  1026. +#include <string.h>
  1027. +
  1028. +static char *strq_start = NULL;
  1029. +
  1030. +static char *
  1031. +strqtok_cchar(
  1032. + register char *s,
  1033. + register char *c,
  1034. + int *backslashed)
  1035. +{
  1036. + register char ch;
  1037. +
  1038. + if ((*backslashed = (*s == '\\'))) {
  1039. + switch (*++s) {
  1040. + case 'a':
  1041. + *c = '\a';
  1042. + break;
  1043. + case 'b':
  1044. + *c = '\b';
  1045. + break;
  1046. + case 'f':
  1047. + *c = '\f';
  1048. + break;
  1049. + case 'n':
  1050. + *c = '\n';
  1051. + break;
  1052. + case 'r':
  1053. + *c = '\r';
  1054. + break;
  1055. + case 't':
  1056. + *c = '\t';
  1057. + break;
  1058. + case 'v':
  1059. + *c = '\v';
  1060. + break;
  1061. + case '\\':
  1062. + *c = '\\';
  1063. + break;
  1064. + case '^':
  1065. + *c = '^';
  1066. + break;
  1067. + case '\'':
  1068. + *c = '\'';
  1069. + break;
  1070. + case '"':
  1071. + *c = '"';
  1072. + break;
  1073. + case '?':
  1074. + *c = '?';
  1075. + break;
  1076. + case '0':
  1077. + case '1':
  1078. + case '2':
  1079. + case '3':
  1080. + case '4':
  1081. + case '5':
  1082. + case '6':
  1083. + case '7':
  1084. + ch = 0;
  1085. + if (isdigit(*s) && *s != '8' && *s != '9') {
  1086. + ch = *s++ - '0';
  1087. + if (isdigit(*s) && *s != '8' && *s != '9') {
  1088. + ch <<= 3;
  1089. + ch |= *s++ - '0';
  1090. + if (isdigit(*s) && *s != '8' && *s != '9') {
  1091. + ch <<= 3;
  1092. + ch |= *s++ - '0';
  1093. + }
  1094. + }
  1095. + }
  1096. + s--;
  1097. + *c = ch;
  1098. + break;
  1099. + case 'x':
  1100. + s++;
  1101. + for (ch = 0; isxdigit(*s); s++) {
  1102. + ch <<= 4;
  1103. + ch |= isdigit(*s) ? *s - '0' :
  1104. + islower(*s) ? *s + 10 - 'a' : *s + 10 - 'A';
  1105. + }
  1106. + s--;
  1107. + *c = ch;
  1108. + break;
  1109. + default:
  1110. + *c = *s;
  1111. + break;
  1112. + }
  1113. + } else
  1114. + *c = *s;
  1115. + return (*s) ? s+1 : NULL;
  1116. +}
  1117. +
  1118. +static char *
  1119. +strqtok(
  1120. + char *s, /* String to tokenize. NULL to continue same str */
  1121. + char *delim, /* Token delimiters. Can be changed w/ each call. */
  1122. + char *quotemarks, /* Quotation marks. Can be changed w/ each call. */
  1123. + char *commentchars, /* Comment characters. Can be changed w/ each call. */
  1124. + unsigned int flags) /* flags&01 -> strip quotes;
  1125. + * flags&02 -> enable backslash escapes;
  1126. + * flags&04 -> skip all delims before return;
  1127. + */
  1128. +{
  1129. + register char *p, *q;
  1130. + char c;
  1131. + char leftquote = 0;
  1132. + char *token;
  1133. + int backslashed, inquote, intok;
  1134. +
  1135. + int stripquote = flags & 01; /* strip quotemarks from tokens */
  1136. + int backslash = flags & 02; /* backslash sequences */
  1137. + int skipdelim = flags & 04; /* skip seq of delims at end of token */
  1138. +
  1139. + /* New string? */
  1140. + if (s)
  1141. + strq_start = s;
  1142. + if (!strq_start)
  1143. + return NULL;
  1144. +
  1145. + /* Skip leading delimiters */
  1146. + for (p=strq_start; *p && strchr(delim, *p); p++)
  1147. + ;
  1148. + if (!(*p) || strchr(commentchars, *p))
  1149. + return NULL;
  1150. +
  1151. + /* Set `token' to point to returned string.
  1152. + * Use p and q to walk through the user's string:
  1153. + * p will follow input characters;
  1154. + * q will overwrite w/ outputted characters, minus possibly-stripped
  1155. + * quotes and including nulls after each token.
  1156. + */
  1157. + token = q = p;
  1158. + inquote = 0;
  1159. + intok = 1;
  1160. + if (backslash) {
  1161. + while (intok && (p = strqtok_cchar(p, &c, &backslashed))) {
  1162. + if (backslashed) {
  1163. + *q++ = c; /* treat as plain character */
  1164. + } else if (!inquote && *delim && strchr(delim, c)) {
  1165. + *q = '\0'; /* Reached end of token */
  1166. + intok = 0;
  1167. + } else if (!inquote && *commentchars && strchr(commentchars, c)) {
  1168. + *q = '\0'; /* Reached end of token */
  1169. + *p = '\0'; /* make it act like end of string */
  1170. + intok = 0;
  1171. + } else if (!inquote && *quotemarks && strchr(quotemarks, c)) {
  1172. + inquote = 1; /* Beginning a quoted segment */
  1173. + leftquote = c; /* Save quote char for matching with */
  1174. + if (!stripquote) *q++ = c;
  1175. + } else if (inquote && leftquote == c) {
  1176. + inquote = 0; /* Ending a quoted segment */
  1177. + if (!stripquote) *q++ = c;
  1178. + } else {
  1179. + *q++ = c; /* Ordinary character */
  1180. + }
  1181. + }
  1182. + strq_start = p; /* Where to start next search */
  1183. + *q = '\0';
  1184. + } else {
  1185. + while (intok && *p) {
  1186. + if (!inquote && *delim && strchr(delim, *p)) {
  1187. + *q = '\0'; /* Reached end of token */
  1188. + p++; /* advance p for next token */
  1189. + intok = 0;
  1190. + } else if (!inquote && *commentchars && strchr(commentchars, *p)) {
  1191. + *q = '\0'; /* Reached end of token */
  1192. + *p = '\0'; /* make it act like end of string */
  1193. + intok = 0;
  1194. + } else if (!inquote && *quotemarks && strchr(quotemarks, *p)) {
  1195. + inquote = 1; /* Beginning a quoted segment */
  1196. + leftquote = *p++; /* Save quote char for matching with */
  1197. + if (!stripquote) *q++ = leftquote;
  1198. + } else if (inquote && leftquote == *p) {
  1199. + inquote = 0; /* Ending a quoted segment */
  1200. + p++;
  1201. + if (!stripquote) *q++ = leftquote;
  1202. + } else {
  1203. + *q++ = *p++;
  1204. + }
  1205. + }
  1206. + strq_start = p; /* Where to start next search */
  1207. + *q = '\0';
  1208. + }
  1209. +
  1210. + if (skipdelim && strq_start) {
  1211. + /* Skip trailing delimiters */
  1212. + while (*strq_start && strchr(delim, *strq_start))
  1213. + strq_start++;
  1214. + }
  1215. + return token;
  1216. +}
  1217. +
  1218. +#endif
  1219. +
  1220. /* this file is to be found in the user's home directory */
  1221. #ifndef CVSRC_FILENAME
  1222. @@ -23,9 +220,68 @@
  1223. extern char *strtok ();
  1224. +#ifdef RSE_PATCH_CVSRC
  1225. +static void read_cvsrc_parentdirs ();
  1226. +static void read_cvsrc_file ();
  1227. +#endif
  1228. +
  1229. /* Read cvsrc, processing options matching CMDNAME ("cvs" for global
  1230. options, and update *ARGC and *ARGV accordingly. */
  1231. +#ifdef RSE_PATCH_CVSRC
  1232. +void
  1233. +read_cvsrc (argc, argv, cmdname)
  1234. + int *argc;
  1235. + char ***argv;
  1236. + char *cmdname;
  1237. +{
  1238. + /* try to read .cvsrc files from parent directories */
  1239. + read_cvsrc_parentdirs(argc, argv, cmdname);
  1240. +
  1241. + /* try to read .cvsrc file from home directory */
  1242. + read_cvsrc_file(argc, argv, cmdname, get_homedir());
  1243. +
  1244. + return;
  1245. +}
  1246. +
  1247. +/* read .cvsrc files from all parent directories (including the current dir) */
  1248. +static void
  1249. +read_cvsrc_parentdirs (argc, argv, cmdname)
  1250. + int *argc;
  1251. + char ***argv;
  1252. + char *cmdname;
  1253. +{
  1254. + char cwd[PATH_MAX];
  1255. + char *cp;
  1256. + int l;
  1257. +
  1258. + if (getcwd(cwd, sizeof(cwd)) == NULL)
  1259. + return;
  1260. + if ((l = strlen(cwd)) <= 0)
  1261. + return;
  1262. + if (cwd[l-1] != '/') {
  1263. + cwd[l++] = '/';
  1264. + cwd[l++] = '\0';
  1265. + }
  1266. + while (cwd[0] != '\0') {
  1267. + cwd[strlen(cwd)-1] = '\0';
  1268. + read_cvsrc_file(argc, argv, cmdname, cwd);
  1269. + if ((cp = strrchr(cwd, '/')) == NULL)
  1270. + break;
  1271. + *(cp+1) = '\0';
  1272. + }
  1273. + return;
  1274. +}
  1275. +
  1276. +/* read .cvsrc file from a particular directory */
  1277. +static void
  1278. +read_cvsrc_file (argc, argv, cmdname, homedir)
  1279. + int *argc;
  1280. + char ***argv;
  1281. + char *cmdname;
  1282. + char *homedir;
  1283. +{
  1284. +#else
  1285. void
  1286. read_cvsrc (argc, argv, cmdname)
  1287. int *argc;
  1288. @@ -33,6 +289,7 @@
  1289. char *cmdname;
  1290. {
  1291. char *homedir;
  1292. +#endif
  1293. char *homeinit;
  1294. FILE *cvsrcfile;
  1295. @@ -64,7 +321,9 @@
  1296. /* determine filename for ~/.cvsrc */
  1297. +#ifndef RSE_PATCH_CVSRC
  1298. homedir = get_homedir ();
  1299. +#endif
  1300. /* If we can't find a home directory, ignore ~/.cvsrc. This may
  1301. make tracking down problems a bit of a pain, but on the other
  1302. hand it might be obnoxious to complain when CVS will function
  1303. @@ -120,9 +379,15 @@
  1304. if (found)
  1305. {
  1306. /* skip over command in the options line */
  1307. +#ifdef RSE_PATCH_CVSRC
  1308. + for (optstart = strqtok (line + command_len, "\t \n", "\"'", "", 7);
  1309. + optstart;
  1310. + optstart = strqtok (NULL, "\t \n", "\"'", "", 7))
  1311. +#else
  1312. for (optstart = strtok (line + command_len, "\t \n");
  1313. optstart;
  1314. optstart = strtok (NULL, "\t \n"))
  1315. +#endif
  1316. {
  1317. new_argv [new_argc++] = xstrdup (optstart);
  1318. Index: src/diff.c
  1319. ===================================================================
  1320. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/diff.c,v
  1321. retrieving revision 1.1.1.6
  1322. diff -u -d -r1.1.1.6 diff.c
  1323. --- src/diff.c 28 Dec 2002 18:01:30 -0000 1.1.1.6
  1324. +++ src/diff.c 28 Dec 2002 20:14:06 -0000
  1325. @@ -271,7 +271,11 @@
  1326. optind = 0;
  1327. while ((c = getopt_long (argc, argv,
  1328. +#if defined(RSE_PATCH_HANDLE)
  1329. + "+abcdefh:ilnpstuwy0123456789BHNRTC:D:F:I:L:U:W:k:r:",
  1330. +#else
  1331. "+abcdefhilnpstuwy0123456789BHNRTC:D:F:I:L:U:W:k:r:",
  1332. +#endif
  1333. longopts, &option_index)) != -1)
  1334. {
  1335. switch (c)
  1336. @@ -280,7 +284,11 @@
  1337. xrealloc_and_strcat (&opts, &opts_allocated, " --side-by-side");
  1338. break;
  1339. case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
  1340. +#if defined(RSE_PATCH_HANDLE)
  1341. + case 'i': case 'n': case 'p': case 's': case 't':
  1342. +#else
  1343. case 'h': case 'i': case 'n': case 'p': case 's': case 't':
  1344. +#endif
  1345. case 'u': case 'w':
  1346. case '0': case '1': case '2': case '3': case '4': case '5':
  1347. case '6': case '7': case '8': case '9':
  1348. @@ -352,6 +360,17 @@
  1349. else
  1350. diff_date1 = Make_Date (optarg);
  1351. break;
  1352. +#ifdef RSE_PATCH_HANDLE
  1353. + case 'h': {
  1354. + time_t t1, t2;
  1355. + if (!handle2dates(optarg, &t1, &t2))
  1356. + error (1, 0, "invalid handle string");
  1357. + t1 -= 1; /* subtract one second to have a real difference */
  1358. + diff_date1 = date_from_time_t(t1);
  1359. + diff_date2 = date_from_time_t(t2);
  1360. + break;
  1361. + }
  1362. +#endif
  1363. case 'N':
  1364. empty_files = 1;
  1365. break;
  1366. @@ -487,7 +506,11 @@
  1367. char *head =
  1368. (vers->vn_rcs == NULL
  1369. ? NULL
  1370. +#ifdef RSE_PATCH_DIFFHEAD
  1371. + : RCS_head (vers->srcfile));
  1372. +#else
  1373. : RCS_branch_head (vers->srcfile, vers->vn_rcs));
  1374. +#endif
  1375. exists = head != NULL && !RCS_isdead(vers->srcfile, head);
  1376. if (head != NULL)
  1377. free (head);
  1378. @@ -891,7 +914,11 @@
  1379. if (diff_rev1 && strcmp (diff_rev1, TAG_HEAD) == 0)
  1380. use_rev1 = ((vers->vn_rcs == NULL || vers->srcfile == NULL)
  1381. ? NULL
  1382. +#ifdef RSE_PATCH_DIFFHEAD
  1383. + : RCS_head (vers->srcfile));
  1384. +#else
  1385. : RCS_branch_head (vers->srcfile, vers->vn_rcs));
  1386. +#endif
  1387. else
  1388. {
  1389. xvers = Version_TS (finfo, NULL, diff_rev1, diff_date1, 1, 0);
  1390. @@ -906,7 +933,11 @@
  1391. if (diff_rev2 && strcmp (diff_rev2, TAG_HEAD) == 0)
  1392. use_rev2 = ((vers->vn_rcs == NULL || vers->srcfile == NULL)
  1393. ? NULL
  1394. +#ifdef RSE_PATCH_DIFFHEAD
  1395. + : RCS_head (vers->srcfile));
  1396. +#else
  1397. : RCS_branch_head (vers->srcfile, vers->vn_rcs));
  1398. +#endif
  1399. else
  1400. {
  1401. xvers = Version_TS (finfo, NULL, diff_rev2, diff_date2, 1, 0);
  1402. Index: src/hash.c
  1403. ===================================================================
  1404. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/hash.c,v
  1405. retrieving revision 1.1.1.3
  1406. diff -u -d -r1.1.1.3 hash.c
  1407. --- src/hash.c 19 Sep 2000 00:06:35 -0000 1.1.1.3
  1408. +++ src/hash.c 16 Feb 2002 12:36:09 -0000
  1409. @@ -25,17 +25,25 @@
  1410. const char *key;
  1411. {
  1412. unsigned int h = 0;
  1413. +#ifndef RSE_PATCH_HASHFUNC
  1414. unsigned int g;
  1415. +#endif
  1416. assert(key != NULL);
  1417. while (*key != 0)
  1418. {
  1419. +#ifdef RSE_PATCH_HASHFUNC
  1420. + /* D.J. Bernstein's popular times 33 function
  1421. + (fast and distributes very well) */
  1422. + h = ((h << 5) + h) + FOLD_FN_CHAR(*key++);
  1423. +#else
  1424. unsigned int c = *key++;
  1425. /* The FOLD_FN_CHAR is so that findnode_fn works. */
  1426. h = (h << 4) + FOLD_FN_CHAR (c);
  1427. if ((g = h & 0xf0000000) != 0)
  1428. h = (h ^ (g >> 24)) ^ g;
  1429. +#endif
  1430. }
  1431. return (h % HASHSIZE);
  1432. Index: src/history.c
  1433. ===================================================================
  1434. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/history.c,v
  1435. retrieving revision 1.1.1.6
  1436. diff -u -d -r1.1.1.6 history.c
  1437. --- src/history.c 24 Sep 2002 20:47:09 -0000 1.1.1.6
  1438. +++ src/history.c 28 Dec 2002 10:48:13 -0000
  1439. @@ -235,6 +235,9 @@
  1440. static char *tz_name = "+0000";
  1441. char *logHistory = ALL_REC_TYPES;
  1442. +#ifdef RSE_PATCH_HISTORYFILE
  1443. +char *history_file = NULL;
  1444. +#endif
  1445. /* -r, -t, or -b options, malloc'd. These are "" if the option in
  1446. question is not specified or is overridden by another option. The
  1447. @@ -668,6 +671,10 @@
  1448. if (histfile)
  1449. fname = xstrdup (histfile);
  1450. +#ifdef RSE_PATCH_HISTORYFILE
  1451. + else if (history_file)
  1452. + fname = xstrdup (history_file);
  1453. +#endif
  1454. else
  1455. {
  1456. fname = xmalloc (strlen (current_parsed_root->directory) + sizeof (CVSROOTADM)
  1457. @@ -716,10 +723,18 @@
  1458. return;
  1459. if ( strchr(logHistory, type) == NULL )
  1460. return;
  1461. +#ifdef RSE_PATCH_HISTORYFILE
  1462. + if (history_file != NULL)
  1463. + fname = xstrdup (history_file);
  1464. + else {
  1465. +#endif
  1466. fname = xmalloc (strlen (current_parsed_root->directory) + sizeof (CVSROOTADM)
  1467. + sizeof (CVSROOTADM_HISTORY) + 3);
  1468. (void) sprintf (fname, "%s/%s/%s", current_parsed_root->directory,
  1469. CVSROOTADM, CVSROOTADM_HISTORY);
  1470. +#ifdef RSE_PATCH_HISTORYFILE
  1471. + }
  1472. +#endif
  1473. /* turn off history logging if the history file does not exist */
  1474. if (!isfile (fname))
  1475. @@ -731,7 +746,11 @@
  1476. if (trace)
  1477. fprintf (stderr, "%s-> fopen(%s,a)\n",
  1478. CLIENT_SERVER_STR, fname);
  1479. +#ifdef RSE_PATCH_NOLOCK
  1480. + if (nolock)
  1481. +#else
  1482. if (noexec)
  1483. +#endif
  1484. goto out;
  1485. fd = CVS_OPEN (fname, O_WRONLY | O_APPEND | O_CREAT | OPEN_BINARY, 0666);
  1486. if (fd < 0)
  1487. Index: src/import.c
  1488. ===================================================================
  1489. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/import.c,v
  1490. retrieving revision 1.1.1.6
  1491. diff -u -d -r1.1.1.6 import.c
  1492. --- src/import.c 24 Sep 2002 20:47:09 -0000 1.1.1.6
  1493. +++ src/import.c 28 Dec 2002 10:48:13 -0000
  1494. @@ -57,6 +57,140 @@
  1495. NULL
  1496. };
  1497. +#ifdef RSE_PATCH_IMPORTINFO
  1498. +
  1499. +static char *importinfo_vtag;
  1500. +
  1501. +static int
  1502. +importinfo_descend(thisdir)
  1503. + char *thisdir;
  1504. +{
  1505. + DIR *dirp;
  1506. + struct dirent *dp;
  1507. + int err = 0;
  1508. + List *dirlist = NULL;
  1509. +
  1510. + if ((dirp = CVS_OPENDIR(thisdir)) == NULL) {
  1511. + error(0, errno, "cannot open directory");
  1512. + err++;
  1513. + }
  1514. + else {
  1515. + errno = 0;
  1516. + while ((dp = readdir(dirp)) != NULL) {
  1517. + if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
  1518. + goto one_more_time_boys;
  1519. + if (strcmp(dp->d_name, CVSADM) == 0)
  1520. + goto one_more_time_boys;
  1521. + if (ign_name(dp->d_name))
  1522. + goto one_more_time_boys;
  1523. + if (
  1524. +#ifdef DT_DIR
  1525. + (dp->d_type == DT_DIR || (dp->d_type == DT_UNKNOWN && isdir (dp->d_name)))
  1526. +#else
  1527. + isdir (dp->d_name)
  1528. +#endif
  1529. + && !wrap_name_has(dp->d_name, WRAP_TOCVS)
  1530. + ) {
  1531. + Node *n;
  1532. + if (dirlist == NULL)
  1533. + dirlist = getlist();
  1534. + n = getnode();
  1535. + n->key = xstrdup(dp->d_name);
  1536. + addnode(dirlist, n);
  1537. + }
  1538. + else if (
  1539. +#ifdef DT_DIR
  1540. + dp->d_type == DT_LNK || (dp->d_type == DT_UNKNOWN && islink (dp->d_name))
  1541. +#else
  1542. + islink (dp->d_name)
  1543. +#endif
  1544. + ) {
  1545. + err++;
  1546. + }
  1547. + else {
  1548. + if (strcmp(thisdir, ".") == 0) {
  1549. + run_arg(dp->d_name);
  1550. + }
  1551. + else {
  1552. + char *p;
  1553. + p = xmalloc(strlen(thisdir)+1+strlen(dp->d_name)+1);
  1554. + (void)sprintf(p, "%s/%s", thisdir, dp->d_name);
  1555. + run_arg(p);
  1556. + free(p);
  1557. + }
  1558. + }
  1559. + one_more_time_boys:
  1560. + errno = 0;
  1561. + }
  1562. + if (errno != 0) {
  1563. + error(0, errno, "cannot read directory");
  1564. + err++;
  1565. + }
  1566. + (void)closedir(dirp);
  1567. + }
  1568. + if (dirlist != NULL) {
  1569. + Node *head, *p;
  1570. + head = dirlist->list;
  1571. + for (p = head->next; p != head; p = p->next) {
  1572. + if (strcmp(thisdir, ".") == 0) {
  1573. + err += importinfo_descend(p->key);
  1574. + }
  1575. + else {
  1576. + char *nextdir;
  1577. + nextdir = xmalloc(strlen(thisdir)+1+strlen(p->key)+1);
  1578. + (void)sprintf(nextdir, "%s/%s", thisdir, p->key);
  1579. + err += importinfo_descend(nextdir);
  1580. + free(nextdir);
  1581. + }
  1582. + }
  1583. + dellist(&dirlist);
  1584. + }
  1585. + return err;
  1586. +}
  1587. +
  1588. +/* importinfo configuration entry callback */
  1589. +static int
  1590. +importinfo_runproc(repository, filter)
  1591. + char *repository;
  1592. + char *filter;
  1593. +{
  1594. + char *s, *cp;
  1595. + int rv;
  1596. +
  1597. + /* if possible, do an own check to make sure that filter really exists */
  1598. + if (filter[0] == '/') {
  1599. + s = xstrdup(filter);
  1600. + for (cp = s; *cp; cp++) {
  1601. + if (isspace((unsigned char)*cp)) {
  1602. + *cp = '\0';
  1603. + break;
  1604. + }
  1605. + }
  1606. + if (!isfile(s)) {
  1607. + error (0, errno, "cannot find pre-admin filter '%s'", s);
  1608. + free(s);
  1609. + return (1);
  1610. + }
  1611. + free(s);
  1612. + }
  1613. +
  1614. + /* construct the filter command */
  1615. + run_setup(filter);
  1616. + run_arg(importinfo_vtag);
  1617. + run_arg(repository);
  1618. + ign_add_file(CVSDOTIGNORE, 1);
  1619. + wrap_add_file(CVSDOTWRAPPER, 1);
  1620. + rv = importinfo_descend(".");
  1621. + if (rv > 0)
  1622. + return rv;
  1623. +
  1624. + /* execute the filter command */
  1625. + rv = run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
  1626. +
  1627. + return rv;
  1628. +}
  1629. +#endif
  1630. +
  1631. int
  1632. import (argc, argv)
  1633. int argc;
  1634. @@ -290,6 +424,12 @@
  1635. error (1, 0, "attempt to import the repository");
  1636. }
  1637. +#ifdef RSE_PATCH_IMPORTINFO
  1638. + importinfo_vtag = argv[1];
  1639. + if (Parse_Info(CVSROOTADM_IMPORTINFO, argv[0], importinfo_runproc, 1) > 0)
  1640. + error(1, 0, "Pre-import check failed");
  1641. +#endif
  1642. +
  1643. /*
  1644. * Make all newly created directories writable. Should really use a more
  1645. * sophisticated security mechanism here.
  1646. @@ -329,7 +469,11 @@
  1647. "Use the following command to help the merge:");
  1648. cvs_output_tagged ("newline", NULL);
  1649. cvs_output_tagged ("newline", NULL);
  1650. +#ifdef RSE_PATCH_COSMETICS
  1651. + cvs_output_tagged ("text", " ");
  1652. +#else
  1653. cvs_output_tagged ("text", "\t");
  1654. +#endif
  1655. cvs_output_tagged ("text", program_name);
  1656. if (CVSroot_cmdline != NULL)
  1657. {
  1658. @@ -356,7 +500,11 @@
  1659. conflicts);
  1660. (void) fprintf (logfp,
  1661. "Use the following command to help the merge:\n\n");
  1662. +#ifdef RSE_PATCH_COSMETICS
  1663. + (void) fprintf (logfp, " %s checkout ", program_name);
  1664. +#else
  1665. (void) fprintf (logfp, "\t%s checkout ", program_name);
  1666. +#endif
  1667. (void) fprintf (logfp, "-j%s:yesterday -j%s %s\n\n",
  1668. argv[1], argv[1], argv[0]);
  1669. }
  1670. @@ -379,6 +527,9 @@
  1671. li->type = T_TITLE;
  1672. li->tag = xstrdup (vbranch);
  1673. li->rev_old = li->rev_new = NULL;
  1674. +#ifdef RSE_PATCH_EXTRAPERCENT
  1675. + li->date = NULL;
  1676. +#endif
  1677. p->data = (char *) li;
  1678. (void) addnode (ulist, p);
  1679. Update_Logfile (repository, message, logfp, ulist);
  1680. @@ -669,7 +820,11 @@
  1681. */
  1682. if (add_tags (vers->srcfile, vfile, vtag, targc, targv))
  1683. retval = 1;
  1684. +#ifdef RSE_PATCH_IMPORTTOUCH
  1685. + add_log ('T', vfile);
  1686. +#else
  1687. add_log ('U', vfile);
  1688. +#endif
  1689. freevers_ts (&vers);
  1690. return (retval);
  1691. }
  1692. Index: src/list.c
  1693. ===================================================================
  1694. RCS file: src/list.c
  1695. diff -N src/list.c
  1696. --- /dev/null 1 Jan 1970 00:00:00 -0000
  1697. +++ src/list.c 16 Feb 2002 12:36:09 -0000
  1698. @@ -0,0 +1,282 @@
  1699. +/*
  1700. + * Copyright (c) 1998, Dan Rich <drich@employees.com>
  1701. + *
  1702. + * You may distribute under the terms of the GNU General Public License as
  1703. + * specified in the README file that comes with the CVS source distribution.
  1704. + *
  1705. + * List Directory
  1706. + */
  1707. +
  1708. +#ifdef RSE_PATCH_RLIST
  1709. +
  1710. +#include <time.h>
  1711. +#include <pwd.h>
  1712. +#include <grp.h>
  1713. +
  1714. +#if 0
  1715. +#include "cvs.h"
  1716. +#endif
  1717. +
  1718. +static int cvslist_fileproc PROTO((void *callerdat, struct file_info * finfo));
  1719. +static Dtype cvslist_dirproc PROTO((void *callerdat, char *dir, char *repos, char *update_dir, List * entries));
  1720. +static int cvslist_output_dir PROTO((Node * node, void *closure));
  1721. +static int cvslist_output_file PROTO((char *name));
  1722. +static int cvslist_tag_proc PROTO((Node * p, void *closure));
  1723. +
  1724. +static char *numtag;
  1725. +static char *date = NULL;
  1726. +static int force_tag_match = 1;
  1727. +static int local = 0;
  1728. +static int verbose = 0;
  1729. +static int list_attic = 0;
  1730. +static RCSNode *xrcsnode;
  1731. +
  1732. +static const char *const status_usage[] = {
  1733. + "Usage: %s %s [-alRv] [-r tag|-D date] modules\n",
  1734. + "\t-a\tInclude attic files\n",
  1735. + "\t-v\tVerbose format; includes additional information for the file\n",
  1736. + "\t-l\tProcess this directory only (not recursive).\n",
  1737. + "\t-R\tProcess directories recursively.\n",
  1738. + "\t-r rev\tExisting revision/tag.\n",
  1739. + "\t-D\tExisting date.\n",
  1740. + "(Specify the --help global option for a list of other help options)\n",
  1741. + NULL
  1742. +};
  1743. +
  1744. +int cvslist(int argc, char **argv)
  1745. +{
  1746. + int c;
  1747. + int i;
  1748. + int which;
  1749. + int retval;
  1750. +
  1751. + if (argc == -1)
  1752. + usage(status_usage);
  1753. + optind = 0;
  1754. + while ((c = getopt(argc, argv, "+alRr:v")) != -1) {
  1755. + switch (c) {
  1756. + case 'a':
  1757. + list_attic = 1;
  1758. + break;
  1759. + case 'D':
  1760. + if (date)
  1761. + free(date);
  1762. + date = Make_Date(optarg);
  1763. + break;
  1764. + case 'l':
  1765. + local = 1;
  1766. + break;
  1767. + case 'R':
  1768. + local = 0;
  1769. + break;
  1770. + case 'r':
  1771. + numtag = optarg;
  1772. + break;
  1773. + case 'v':
  1774. + verbose = 1;
  1775. + break;
  1776. + case '?':
  1777. + default:
  1778. + usage(status_usage);
  1779. + break;
  1780. + }
  1781. + }
  1782. + argc -= optind;
  1783. + argv += optind;
  1784. +
  1785. + if (date && numtag)
  1786. + error(1, 0, "-r and -D options are mutually exclusive");
  1787. +
  1788. + wrap_setup();
  1789. +#ifdef CLIENT_SUPPORT
  1790. + if (current_parsed_root->isremote) {
  1791. + start_server();
  1792. + ign_setup();
  1793. + if (list_attic)
  1794. + send_arg("-a");
  1795. + if (local)
  1796. + send_arg("-l");
  1797. + if (verbose)
  1798. + send_arg("-v");
  1799. + if (numtag)
  1800. + option_with_arg("-r", numtag);
  1801. + if (date)
  1802. + client_senddate(date);
  1803. +#if 0
  1804. + if (supported_request("expand-modules")) {
  1805. + /* This is done here because we need to read responses from the
  1806. + server before we send the command checkout or export files. */
  1807. + client_expand_modules(argc, argv, local);
  1808. + }
  1809. +#endif
  1810. + /* Send any remaining arguments -- probably dir/file names */
  1811. + for (i = 0; i < argc; ++i)
  1812. + send_arg(argv[i]);
  1813. + send_to_server("list\012", 0); /* Send the command */
  1814. + return get_responses_and_close();
  1815. + }
  1816. +#endif
  1817. +#ifdef SERVER_SUPPORT
  1818. + /* If we're the server, make sure we're starting at the root */
  1819. + if (server_active)
  1820. + CVS_CHDIR(current_parsed_root->directory);
  1821. +#endif
  1822. +
  1823. +#if 0
  1824. + if (numtag != NULL)
  1825. + tag_check_valid(numtag, argc, argv, local, 0, "");
  1826. +#endif
  1827. +
  1828. + which = W_REPOS;
  1829. + if (list_attic)
  1830. + which |= W_ATTIC;
  1831. +
  1832. + /* start the recursion processor */
  1833. + cvs_output_tagged("+list", NULL);
  1834. + retval = start_recursion(cvslist_fileproc, (FILESDONEPROC)NULL,
  1835. + cvslist_dirproc, (DIRLEAVEPROC)NULL, NULL,
  1836. + argc, argv, local, which, 0, 1, (char *)NULL, 1);
  1837. + cvs_output_tagged("-list", NULL);
  1838. +
  1839. + return retval;
  1840. +}
  1841. +
  1842. +/*
  1843. + * Display file info
  1844. + */
  1845. +/* ARGSUSED */
  1846. +static int cvslist_fileproc(callerdat, finfo)
  1847. + void *callerdat;
  1848. + struct file_info *finfo;
  1849. +{
  1850. + char *buf;
  1851. + Vers_TS *vers;
  1852. +
  1853. + /* If a particular revision was specified, only show that one */
  1854. + if (numtag != NULL || date != NULL) {
  1855. + vers = Version_TS(finfo, NULL, NULL, NULL, 0, 0);
  1856. + if (RCS_getversion(vers->srcfile, numtag, date, force_tag_match, NULL) == NULL)
  1857. + return 0;
  1858. + }
  1859. +
  1860. + cvslist_output_file(finfo->fullname);
  1861. +
  1862. + if (verbose) {
  1863. + vers = Version_TS(finfo, NULL, NULL, NULL, 0, 0);
  1864. + if (vers->srcfile) {
  1865. + List *symbols = RCS_symbols(vers->srcfile);
  1866. +
  1867. + cvs_output_tagged("+info", NULL);
  1868. + if (vers->vn_rcs == NULL)
  1869. + cvs_output_tagged("finfo",
  1870. + " Repository revision:\tNo revision control file");
  1871. + else {
  1872. + buf = (char *)malloc(24 + strlen(vers->vn_rcs) + 1 +
  1873. + strlen(vers->srcfile->path) + 1);
  1874. + sprintf(buf, " Repository revision:\t%s\t%s",
  1875. + vers->vn_rcs, vers->srcfile->path);
  1876. + cvs_output_tagged("finfo", buf);
  1877. + }
  1878. + cvs_output_tagged("newline", NULL);
  1879. + cvs_output_tagged("finfo", " Existing Tags:");
  1880. + cvs_output_tagged("newline", NULL);
  1881. + if (symbols) {
  1882. + xrcsnode = finfo->rcs;
  1883. + (void)walklist(symbols, cvslist_tag_proc, NULL);
  1884. + }
  1885. + else
  1886. + cvs_output_tagged("finfo", "\tNo Tags Exist");
  1887. +
  1888. + cvs_output_tagged("-info", NULL);
  1889. + cvs_output_tagged("newline", NULL);
  1890. + }
  1891. + }
  1892. + return 0;
  1893. +}
  1894. +
  1895. +/*
  1896. + * Display directory info
  1897. + */
  1898. +/* ARGSUSED */
  1899. +static Dtype cvslist_dirproc(callerdat, dir, repos, update_dir, entries)
  1900. + void *callerdat;
  1901. + char *dir;
  1902. + char *repos;
  1903. + char *update_dir;
  1904. + List *entries;
  1905. +{
  1906. + char *buf;
  1907. + List *dirs;
  1908. +
  1909. + buf = (char *)malloc(strlen(update_dir) + 2);
  1910. + sprintf(buf, "%s", update_dir);
  1911. + cvs_output_tagged("fname", buf);
  1912. + cvs_output_tagged("newline", NULL);
  1913. + free(buf);
  1914. +
  1915. + if (local) { /* We need to output the current dirs */
  1916. + dirs = Find_Directories(update_dir, W_REPOS, NULL);
  1917. + walklist(dirs, cvslist_output_dir, update_dir);
  1918. + }
  1919. + return R_PROCESS;
  1920. +}
  1921. +
  1922. +static int cvslist_output_dir(node, closure)
  1923. + Node *node;
  1924. + void *closure;
  1925. +{
  1926. + char *buf;
  1927. +
  1928. + buf = (char *)malloc(strlen((char *)closure) + strlen(node->key) + 3);
  1929. + sprintf(buf, "%s/%s/", (char *)closure, node->key);
  1930. + cvs_output_tagged("fname", buf);
  1931. + cvs_output_tagged("newline", NULL);
  1932. + free(buf);
  1933. + return 0;
  1934. +}
  1935. +
  1936. +static int cvslist_output_file(name)
  1937. + char *name;
  1938. +{
  1939. + char *buf;
  1940. + char *nlptr;
  1941. +
  1942. + buf = (char *)malloc(strlen(name) + 1);
  1943. + strncpy(buf, name, strlen(name));
  1944. + *(buf+strlen(name)) = '\0';
  1945. +
  1946. + /* cvs_output_tagged doesn't like \n */
  1947. + if ((nlptr = strchr(buf, '\n')) != NULL)
  1948. + nlptr = '\0';
  1949. + cvs_output_tagged("fname", buf);
  1950. + cvs_output_tagged("newline", NULL);
  1951. + free(buf);
  1952. + return 0;
  1953. +}
  1954. +
  1955. +static int cvslist_tag_proc(p, closure)
  1956. + Node *p;
  1957. + void *closure;
  1958. +{
  1959. + char *branch = NULL;
  1960. + char *buf;
  1961. +
  1962. + if (RCS_nodeisbranch(xrcsnode, p->key))
  1963. + branch = RCS_whatbranch(xrcsnode, p->key);
  1964. +
  1965. + buf = xmalloc(80 + strlen(p->key)
  1966. + + (branch ? strlen(branch) : strlen(p->data)));
  1967. + sprintf(buf, "\t%-25s\t(%s: %s)", p->key,
  1968. + branch ? "branch" : "revision", branch ? branch : p->data);
  1969. + cvs_output_tagged("finfo", buf);
  1970. + cvs_output_tagged("newline", NULL);
  1971. + free(buf);
  1972. +
  1973. + if (branch)
  1974. + free(branch);
  1975. +
  1976. + return (0);
  1977. +}
  1978. +
  1979. +#endif /* RSE_PATCH_RLIST */
  1980. +
  1981. Index: src/lock.c
  1982. ===================================================================
  1983. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/lock.c,v
  1984. retrieving revision 1.1.1.7
  1985. diff -u -d -r1.1.1.7 lock.c
  1986. --- src/lock.c 28 Dec 2002 18:01:30 -0000 1.1.1.7
  1987. +++ src/lock.c 28 Dec 2002 20:14:06 -0000
  1988. @@ -403,7 +403,11 @@
  1989. (void) fprintf (stderr, "%s-> Reader_Lock(%s)\n", CLIENT_SERVER_STR,
  1990. xrepository);
  1991. +#ifdef RSE_PATCH_NOLOCK
  1992. + if (nolock)
  1993. +#else
  1994. if (noexec)
  1995. +#endif
  1996. return (0);
  1997. /* we only do one directory at a time for read locks! */
  1998. @@ -475,7 +479,11 @@
  1999. {
  2000. char *wait_repos;
  2001. +#ifdef RSE_PATCH_NOLOCK
  2002. + if (nolock)
  2003. +#else
  2004. if (noexec)
  2005. +#endif
  2006. return (0);
  2007. /* We only know how to do one list at a time */
  2008. Index: src/logmsg.c
  2009. ===================================================================
  2010. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/logmsg.c,v
  2011. retrieving revision 1.1.1.6
  2012. diff -u -d -r1.1.1.6 logmsg.c
  2013. --- src/logmsg.c 20 Sep 2002 02:48:59 -0000 1.1.1.6
  2014. +++ src/logmsg.c 28 Dec 2002 10:48:14 -0000
  2015. @@ -673,6 +673,42 @@
  2016. {
  2017. switch (*c)
  2018. {
  2019. +#ifdef RSE_PATCH_EXTRAPERCENT
  2020. + case 'o': {
  2021. + char T[2];
  2022. + str_list = xrealloc (str_list, (strlen (str_list) + 1 + 1));
  2023. + switch (li->type) {
  2024. + case T_ADDED: T[0] = 'A'; break;
  2025. + case T_MODIFIED: T[0] = 'M'; break;
  2026. + case T_REMOVED: T[0] = 'R'; break;
  2027. + default: T[0] = '?'; break;
  2028. + }
  2029. + T[1] = '\0';
  2030. + (void) strcat (str_list, T);
  2031. + break;
  2032. + }
  2033. + case 't':
  2034. + str_list =
  2035. + xrealloc (str_list,
  2036. + (strlen (str_list)
  2037. + + (li->tag ? strlen (li->tag) : 0)
  2038. + + 10)
  2039. + );
  2040. + (void) strcat (str_list, (li->tag ? li->tag : ""));
  2041. + break;
  2042. + case 'd': {
  2043. + time_t t;
  2044. + if (li->date != NULL) {
  2045. + t = get_date(li->date, NULL);
  2046. + if (t != ((time_t)-1)) {
  2047. + t += 1; /* re-adjust because of fudge */
  2048. + str_list = xrealloc (str_list, (strlen(str_list)+20));
  2049. + sprintf(str_list+strlen(str_list), "%ld", (long)t);
  2050. + }
  2051. + }
  2052. + break;
  2053. + }
  2054. +#endif
  2055. case 's':
  2056. str_list =
  2057. xrealloc (str_list,
  2058. Index: src/main.c
  2059. ===================================================================
  2060. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/main.c,v
  2061. retrieving revision 1.1.1.7
  2062. diff -u -d -r1.1.1.7 main.c
  2063. --- src/main.c 24 Oct 2002 18:38:37 -0000 1.1.1.7
  2064. +++ src/main.c 28 Dec 2002 10:50:11 -0000
  2065. @@ -41,6 +41,9 @@
  2066. int quiet = 0;
  2067. int trace = 0;
  2068. int noexec = 0;
  2069. +#ifdef RSE_PATCH_NOLOCK
  2070. +int nolock = 0;
  2071. +#endif
  2072. int logoff = 0;
  2073. /* Set if we should be writing CVSADM directories at top level. At
  2074. @@ -50,6 +53,15 @@
  2075. mode_t cvsumask = UMASK_DFLT;
  2076. +#ifdef RSE_PATCH_LOCALID
  2077. +char *RCS_citag = NULL;
  2078. +#endif
  2079. +
  2080. +#ifdef RSE_PATCH_PROLOGEPILOG
  2081. +char *cvs_prolog = NULL;
  2082. +char *cvs_epilog = NULL;
  2083. +#endif
  2084. +
  2085. char *CurDir;
  2086. /*
  2087. @@ -124,11 +136,17 @@
  2088. { "login", "logon", "lgn", login, 0 },
  2089. { "logout", NULL, NULL, logout, 0 },
  2090. #endif /* AUTH_CLIENT_SUPPORT */
  2091. +#ifdef RSE_PATCH_PSERVERD
  2092. + { "pserverd", NULL, NULL, pserverd },
  2093. +#endif
  2094. #if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
  2095. { "pserver", NULL, NULL, server, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR }, /* placeholder */
  2096. #endif
  2097. { "rannotate","rann", "ra", annotate, 0 },
  2098. { "rdiff", "patch", "pa", patch, 0 },
  2099. +#ifdef RSE_PATCH_RLIST
  2100. + { "rlist", "rls", NULL, cvslist, 0 },
  2101. +#endif
  2102. { "release", "re", "rel", release, 0 },
  2103. { "remove", "rm", "delete", cvsremove, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
  2104. { "rlog", "rl", NULL, cvslog, 0 },
  2105. @@ -143,9 +161,53 @@
  2106. { "version", "ve", "ver", version, 0 },
  2107. { "watch", NULL, NULL, watch, CVS_CMD_MODIFIES_REPOSITORY | CVS_CMD_USES_WORK_DIR },
  2108. { "watchers", NULL, NULL, watchers, CVS_CMD_USES_WORK_DIR },
  2109. +#ifdef RSE_PATCH_CVSROOT
  2110. + { "root", "ro", "repo", root, CVS_CMD_IGNORE_ADMROOT },
  2111. +#endif
  2112. { NULL, NULL, NULL, NULL, 0 },
  2113. };
  2114. +#ifdef RSE_PATCH_CUSTOMCMD
  2115. +
  2116. +/* the table of custom commands */
  2117. +#define CUSTOMCMD_MAX 20
  2118. +static int customcmd_num = 0;
  2119. +struct customcmd {
  2120. + char *name;
  2121. + char *command;
  2122. +};
  2123. +static struct customcmd customcmd_tab[CUSTOMCMD_MAX];
  2124. +
  2125. +/* the internal handler function for custom commands */
  2126. +static int
  2127. +customcmd_run(argc, argv)
  2128. + int argc;
  2129. + char **argv;
  2130. +{
  2131. + int i;
  2132. + char *cmd;
  2133. +
  2134. + /* support for `cvs -H <cmd>' */
  2135. + if (argc == -1) {
  2136. + (void)fprintf(stderr, "Usage: %s %s [command arguments]\n",
  2137. + program_name, command_name);
  2138. + error_exit();
  2139. + }
  2140. +
  2141. + /* execute the command */
  2142. + cmd = expand_path(argv[0], command_name, 0);
  2143. + run_setup(cmd);
  2144. + for (i = 1; i < argc; i++)
  2145. + run_arg(argv[i]);
  2146. + if (run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL) != 0)
  2147. + error(1, 0, "program `%s' of custom command `%s' returned non-zero",
  2148. + cmd, command_name);
  2149. + free(cmd);
  2150. +
  2151. + return 0;
  2152. +}
  2153. +#endif
  2154. +
  2155. static const char *const usg[] =
  2156. {
  2157. /* CVS usage messages never have followed the GNU convention of
  2158. @@ -186,9 +248,13 @@
  2159. paragraph in ../cvs.spec without assuming the reader knows what
  2160. version control means. */
  2161. +#ifdef RSE_PATCH_COSMETICS
  2162. + "For CVS updates and additional information, see http://www.cvshome.org/\n",
  2163. +#else
  2164. "For CVS updates and additional information, see\n",
  2165. " the CVS home page at http://www.cvshome.org/ or\n",
  2166. " Pascal Molli's CVS site at http://www.loria.fr/~molli/cvs-index.html\n",
  2167. +#endif
  2168. NULL,
  2169. };
  2170. @@ -215,11 +281,17 @@
  2171. " login Prompt for password for authenticating server\n",
  2172. " logout Removes entry in .cvspass for remote repository\n",
  2173. #endif /* AUTH_CLIENT_SUPPORT */
  2174. +#ifdef RSE_PATCH_PSERVERD
  2175. + " pserverd Password server daemon\n",
  2176. +#endif
  2177. #if (defined(AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)) && defined(SERVER_SUPPORT)
  2178. " pserver Password server mode\n",
  2179. #endif
  2180. " rannotate Show last revision where each line of module was modified\n",
  2181. " rdiff Create 'patch' format diffs between releases\n",
  2182. +#ifdef RSE_PATCH_RLIST
  2183. + " rlist List repository directories.\n",
  2184. +#endif
  2185. " release Indicate that a Module is no longer in use\n",
  2186. " remove Remove an entry from the repository\n",
  2187. " rlog Print out history information for a module\n",
  2188. @@ -234,6 +306,9 @@
  2189. " version Show current CVS version(s)\n",
  2190. " watch Set watches\n",
  2191. " watchers See who is watching a file\n",
  2192. +#ifdef RSE_PATCH_CVSROOT
  2193. + " root Maintain repository root locations\n",
  2194. +#endif
  2195. "(Specify the --help option for a list of other help options)\n",
  2196. NULL,
  2197. };
  2198. @@ -249,6 +324,9 @@
  2199. " -w Make checked-out files read-write (default).\n",
  2200. " -l Turn history logging off.\n",
  2201. " -n Do not execute anything that will change the disk.\n",
  2202. +#ifdef RSE_PATCH_NOLOCK
  2203. + " -u Do not create lock files (implies -l).\n",
  2204. +#endif
  2205. " -t Show trace of program execution -- try with -n.\n",
  2206. " -v CVS version and copyright.\n",
  2207. " -T tmpdir Use 'tmpdir' for temporary files.\n",
  2208. @@ -262,6 +340,10 @@
  2209. #endif
  2210. " -a Authenticate all net traffic.\n",
  2211. #endif
  2212. +#ifdef RSE_PATCH_PROLOGEPILOG
  2213. + " -P program Run prolog program before processing.\n",
  2214. + " -E program Run epilog program after processing.\n",
  2215. +#endif
  2216. " -s VAR=VAL Set CVS user variable.\n",
  2217. "(Specify the --help option for a list of other help options)\n",
  2218. NULL
  2219. @@ -332,6 +414,20 @@
  2220. if (strcmp (cmd_name, cm->fullname) == 0)
  2221. break;
  2222. }
  2223. +#ifdef RSE_PATCH_CUSTOMCMD
  2224. + {
  2225. + int i;
  2226. + unsigned long int ret = 0;
  2227. + for (i = 0; i < customcmd_num; i++) {
  2228. + if (strcmp(customcmd_tab[i].name, cmd_name) == 0) {
  2229. + ret |= CVS_CMD_IGNORE_ADMROOT;
  2230. + ret &= ~(CVS_CMD_USES_WORK_DIR);
  2231. + ret &= ~(CVS_CMD_MODIFIES_REPOSITORY);
  2232. + return ret;
  2233. + }
  2234. + }
  2235. + }
  2236. +#endif
  2237. if (!cm->fullname)
  2238. error (1, 0, "unknown command: %s", cmd_name);
  2239. return cm->attr;
  2240. @@ -403,11 +499,34 @@
  2241. int free_CVSroot = 0;
  2242. int free_Editor = 0;
  2243. int free_Tmpdir = 0;
  2244. +#ifdef RSE_PATCH_CVSROOT
  2245. + cvsroot_type *cvsroot_sync = NULL;
  2246. + int cvsroot_cmdline_isreal = 0;
  2247. +#endif
  2248. +#if defined(RSE_PATCH_CVSROOT) || defined(RSE_PATCH_CUSTOMCMD)
  2249. + int standalone_command = 0;
  2250. +#endif
  2251. int help = 0; /* Has the user asked for help? This
  2252. lets us support the `cvs -H cmd'
  2253. convention to give help for cmd. */
  2254. +#if defined(RSE_PATCH_NOLOCK) ||\
  2255. + defined(RSE_PATCH_PROLOGEPILOG) ||\
  2256. + defined(RSE_PATCH_CUSTOMCMD)
  2257. + static const char short_options[] = "+Qqrwtnlvb:T:e:d:Hfz:s:xa"
  2258. +#ifdef RSE_PATCH_NOLOCK
  2259. + "u"
  2260. +#endif
  2261. +#ifdef RSE_PATCH_PROLOGEPILOG
  2262. + "P:E:"
  2263. +#endif
  2264. +#ifdef RSE_PATCH_CUSTOMCMD
  2265. + "C:"
  2266. +#endif
  2267. + ;
  2268. +#else
  2269. static const char short_options[] = "+Qqrwtnlvb:T:e:d:Hfz:s:xa";
  2270. +#endif
  2271. static struct option long_options[] =
  2272. {
  2273. {"help", 0, NULL, 'H'},
  2274. @@ -416,6 +535,9 @@
  2275. {"help-synonyms", 0, NULL, 2},
  2276. {"help-options", 0, NULL, 4},
  2277. {"allow-root", required_argument, NULL, 3},
  2278. +#ifdef RSE_PATCH_MAPROOT
  2279. + {"map-root", required_argument, NULL, 5},
  2280. +#endif
  2281. {0, 0, 0, 0}
  2282. };
  2283. /* `getopt_long' stores the option index here, but right now we
  2284. @@ -470,6 +592,16 @@
  2285. }
  2286. if (getenv (CVSREAD_ENV) != NULL)
  2287. cvswrite = 0;
  2288. +#ifdef RSE_PATCH_NOLOCK
  2289. + if (getenv (CVSNOLOCK_ENV)) {
  2290. + nolock = 1;
  2291. + logoff = 1;
  2292. + }
  2293. +#endif
  2294. +#ifdef RSE_PATCH_PROLOGEPILOG
  2295. + cvs_prolog = getenv("CVSPROLOG");
  2296. + cvs_epilog = getenv("CVSEPILOG");
  2297. +#endif
  2298. /* Set this to 0 to force getopt initialization. getopt() sets
  2299. this to 1 internally. */
  2300. @@ -489,12 +621,63 @@
  2301. use_cvsrc = 0;
  2302. }
  2303. +#ifdef RSE_PATCH_GLOBALOPTION
  2304. + /*
  2305. + * Perform a pre-lookup of the command name in order to scan cvsrc
  2306. + * file also for command dependent global options. For instance a
  2307. + * "-d" option only for "commit" commands (useful if one uses a
  2308. + * local repository copy for all cvs commands, but commits have to
  2309. + * go directly to the master repository).
  2310. + */
  2311. + if (use_cvsrc) {
  2312. + command_name = argv[optind];
  2313. + if (command_name != NULL && command_name[0] != '\0') {
  2314. + for (cm = cmds; cm->fullname != NULL; cm++)
  2315. + {
  2316. + if (cm->nick1 && !strcmp(command_name, cm->nick1))
  2317. + break;
  2318. + if (cm->nick2 && !strcmp(command_name, cm->nick2))
  2319. + break;
  2320. + if (!strcmp(command_name, cm->fullname))
  2321. + break;
  2322. + }
  2323. + command_name = cm->fullname;
  2324. + }
  2325. + }
  2326. +#endif
  2327. +
  2328. /*
  2329. * Scan cvsrc file for global options.
  2330. */
  2331. if (use_cvsrc)
  2332. read_cvsrc (&argc, &argv, "cvs");
  2333. +#ifdef RSE_PATCH_GLOBALOPTION
  2334. + if (use_cvsrc) {
  2335. + if (command_name != NULL && command_name[0] != '\0') {
  2336. + char *cmd;
  2337. +#ifdef RSE_PATCH_GLOBALOPTION_PARTLY
  2338. + if ( strcmp(command_name, "commit") == 0
  2339. + || strcmp(command_name, "tag") == 0
  2340. + || strcmp(command_name, "rtag") == 0
  2341. + || strcmp(command_name, "history") == 0
  2342. + || strcmp(command_name, "admin") == 0
  2343. + || strcmp(command_name, "import") == 0
  2344. +#ifdef RSE_PATCH_RLIST
  2345. + || strcmp(command_name, "rlist") == 0
  2346. +#endif
  2347. + || strcmp(command_name, "rdiff") == 0) {
  2348. +#endif
  2349. + cmd = xmalloc(4 + strlen(command_name) + 1);
  2350. + sprintf(cmd, "cvs/%s", command_name);
  2351. + read_cvsrc (&argc, &argv, cmd);
  2352. +#ifdef RSE_PATCH_GLOBALOPTION_PARTLY
  2353. + }
  2354. +#endif
  2355. + }
  2356. + }
  2357. +#endif
  2358. +
  2359. optind = 0;
  2360. opterr = 1;
  2361. @@ -520,6 +703,17 @@
  2362. /* --allow-root */
  2363. root_allow_add (optarg);
  2364. break;
  2365. +#ifdef RSE_PATCH_MAPROOT
  2366. + case 5: {
  2367. + /* --map-root */
  2368. + char *cp;
  2369. + if ((cp = strchr(optarg, ':')) == NULL)
  2370. + error(1, 0, "invalid argument syntax for --map-root option");
  2371. + *cp++ = '\0';
  2372. + root_map_add(optarg, cp);
  2373. + break;
  2374. + }
  2375. +#endif
  2376. case 'Q':
  2377. really_quiet = 1;
  2378. /* FALL THROUGH */
  2379. @@ -537,6 +731,10 @@
  2380. break;
  2381. case 'n':
  2382. noexec = 1;
  2383. +#ifdef RSE_PATCH_NOLOCK
  2384. + case 'u': /* Fall through */
  2385. + nolock = 1;
  2386. +#endif
  2387. case 'l': /* Fall through */
  2388. logoff = 1;
  2389. break;
  2390. @@ -575,10 +773,34 @@
  2391. case 'd':
  2392. if (CVSroot_cmdline != NULL)
  2393. free (CVSroot_cmdline);
  2394. +#ifdef RSE_PATCH_MAPROOT
  2395. + {
  2396. + char *newarg;
  2397. + if (root_map_it(optarg, &newarg, 0))
  2398. + optarg = newarg;
  2399. + }
  2400. +#endif
  2401. +#ifdef RSE_PATCH_CVSROOT
  2402. + {
  2403. + cvsroot_type *e;
  2404. + if ((e = cvsroot_lookup(optarg, NULL, NULL)) != NULL) {
  2405. + if (!quiet)
  2406. + fprintf(stderr, "%s: using repository `%s'\n", program_name, e->masterpath);
  2407. + CVSroot_cmdline = xstrdup(e->masterpath);
  2408. + CVSroot = xstrdup(e->masterpath);
  2409. + cvsroot_free(e);
  2410. + }
  2411. + else {
  2412. + cvsroot_cmdline_isreal = 1;
  2413. +#endif
  2414. CVSroot_cmdline = xstrdup (optarg);
  2415. if (free_CVSroot)
  2416. free (CVSroot);
  2417. CVSroot = xstrdup (optarg);
  2418. +#ifdef RSE_PATCH_CVSROOT
  2419. + }
  2420. + }
  2421. +#endif
  2422. free_CVSroot = 1;
  2423. cvs_update_env = 1; /* need to update environment */
  2424. break;
  2425. @@ -620,6 +842,28 @@
  2426. We will issue an error later if stream
  2427. authentication is not supported. */
  2428. break;
  2429. +#ifdef RSE_PATCH_PROLOGEPILOG
  2430. + case 'P':
  2431. + cvs_prolog = xstrdup(optarg);
  2432. + break;
  2433. + case 'E':
  2434. + cvs_epilog = xstrdup(optarg);
  2435. + break;
  2436. +#endif
  2437. +#ifdef RSE_PATCH_CUSTOMCMD
  2438. + case 'C': {
  2439. + char *cp;
  2440. + if (customcmd_num >= CUSTOMCMD_MAX)
  2441. + error(1, 0, "maximum number of allowed -C options reached");
  2442. + if ((cp = strchr(optarg, ':')) == NULL)
  2443. + error(1, 0, "invalid argument to option -C (has to be \"name:cmd\")");
  2444. + *cp++ = '\0';
  2445. + customcmd_tab[customcmd_num].name = xstrdup(optarg);
  2446. + customcmd_tab[customcmd_num].command = xstrdup(cp);
  2447. + customcmd_num++;
  2448. + break;
  2449. + }
  2450. +#endif
  2451. case '?':
  2452. default:
  2453. usage (usg);
  2454. @@ -631,6 +875,28 @@
  2455. if (argc < 1)
  2456. usage (usg);
  2457. +#ifdef RSE_PATCH_CUSTOMCMD
  2458. + /* Look up the custom command. */
  2459. + cm = NULL;
  2460. + {
  2461. + int i;
  2462. + command_name = argv[0];
  2463. + for (i = 0; i < customcmd_num; i++) {
  2464. + if (strcmp(customcmd_tab[i].name, command_name) == 0) {
  2465. + struct cmd *ccm;
  2466. + ccm = (struct cmd *)xmalloc(sizeof(struct cmd));
  2467. + ccm->nick1 = NULL;
  2468. + ccm->nick2 = NULL;
  2469. + ccm->func = customcmd_run;
  2470. + ccm->fullname = customcmd_tab[i].name;
  2471. + argv[0] = customcmd_tab[i].command;
  2472. + cm = (const struct cmd *)ccm;
  2473. + standalone_command = 1;
  2474. + }
  2475. + }
  2476. + }
  2477. + if (cm == NULL) {
  2478. +#endif
  2479. /* Look up the command name. */
  2480. @@ -653,6 +919,10 @@
  2481. else
  2482. command_name = cm->fullname; /* Global pointer for later use */
  2483. +#ifdef RSE_PATCH_CUSTOMCMD
  2484. + }
  2485. +#endif
  2486. +
  2487. if (help)
  2488. {
  2489. argc = -1; /* some functions only check for this */
  2490. @@ -678,6 +948,71 @@
  2491. CVSUMASK_ENV, cp);
  2492. }
  2493. +#ifdef RSE_PATCH_CVSPID
  2494. + /* provide the process id of the parent CVS process to
  2495. + sub-processes (usually scripts called from *info files) in order
  2496. + to let them have a unique session handle */
  2497. + {
  2498. + char pidbuf[64];
  2499. + sprintf(pidbuf, "CVSPID=%lu", (unsigned long)getpid());
  2500. + putenv(pidbuf);
  2501. + }
  2502. +#endif
  2503. +
  2504. +#ifdef RSE_PATCH_SETXID
  2505. + if ( strcmp(command_name, "kserver") != 0
  2506. + && strcmp(command_name, "pserver") != 0
  2507. + && strcmp(command_name, "server") == 0) {
  2508. + uid_t uid, euid;
  2509. + gid_t gid, egid;
  2510. + struct passwd *pw;
  2511. + char *env;
  2512. +
  2513. + /* adjust group id */
  2514. + gid = getgid();
  2515. + egid = getegid();
  2516. + if (gid != egid)
  2517. + setgid(egid); /* upgrade real to effective gid */
  2518. + else
  2519. + setegid(gid); /* downgrade effective to real gid */
  2520. +
  2521. + /* adjust user id */
  2522. + uid = getuid();
  2523. + euid = geteuid();
  2524. + if (uid != euid)
  2525. + setuid(euid); /* upgrade real to effective uid */
  2526. + else
  2527. + seteuid(uid); /* downgrade effective to real uid */
  2528. +
  2529. + /* still do not adjust umask */
  2530. + umask(0);
  2531. +
  2532. + /* remember real user (especially for getcaller()) */
  2533. + pw = getpwuid(uid);
  2534. +#ifdef AUTH_SERVER_SUPPORT
  2535. + CVS_Username = xstrdup(pw->pw_name);
  2536. +#if HAVE_PUTENV
  2537. + env = xmalloc(sizeof("LOGNAME=")+strlen(CVS_Username));
  2538. + (void)sprintf(env, "LOGNAME=%s", CVS_Username);
  2539. + (void)putenv(env);
  2540. +#endif
  2541. +#endif
  2542. +
  2543. +#if HAVE_PUTENV
  2544. + /* remember running user */
  2545. + pw = getpwuid(getuid());
  2546. + env = xmalloc(sizeof("USER=")+strlen(pw->pw_name));
  2547. + (void)sprintf(env, "USER=%s", pw->pw_name);
  2548. + (void)putenv(env);
  2549. +#endif
  2550. + }
  2551. + else {
  2552. + /* delete effective user and group id */
  2553. + seteuid(getuid());
  2554. + setegid(getgid());
  2555. + }
  2556. +#endif
  2557. +
  2558. #ifdef SERVER_SUPPORT
  2559. # ifdef HAVE_KERBEROS
  2560. @@ -694,6 +1029,21 @@
  2561. }
  2562. # endif /* HAVE_KERBEROS */
  2563. +#ifdef RSE_PATCH_PSERVERD
  2564. + if (strcmp(command_name, "pserverd") == 0) {
  2565. + /*
  2566. + * perform the socket listening. This returns multiple times,
  2567. + * i.e., for each connection. But the parent never returns.
  2568. + */
  2569. + pserver_daemon(argc, argv);
  2570. +
  2571. + /*
  2572. + * switch to regular "cvs server" operation.
  2573. + */
  2574. + argc = 0;
  2575. + command_name = "server";
  2576. + }
  2577. +#endif
  2578. # if defined (AUTH_SERVER_SUPPORT) || defined (HAVE_GSSAPI)
  2579. if (strcmp (command_name, "pserver") == 0)
  2580. @@ -718,6 +1068,11 @@
  2581. #endif /* SERVER_SUPPORT */
  2582. +#ifdef RSE_PATCH_CVSROOT
  2583. + if (strcmp(command_name, "root") == 0)
  2584. + standalone_command = 1;
  2585. +#endif
  2586. +
  2587. /* This is only used for writing into the history file. For
  2588. remote connections, it might be nice to have hostname
  2589. and/or remote path, on the other hand I'm not sure whether
  2590. @@ -788,8 +1143,12 @@
  2591. in server mode, since the client will send the repository
  2592. directory after the connection is made. */
  2593. +#if defined(RSE_PATCH_CVSROOT) || defined(RSE_PATCH_CUSTOMCMD)
  2594. + if (!server_active && !standalone_command)
  2595. +#else
  2596. if (!server_active)
  2597. #endif
  2598. +#endif
  2599. {
  2600. char *CVSADM_Root;
  2601. @@ -845,6 +1204,54 @@
  2602. error (1, 0,
  2603. "CVS/Root file (if any).");
  2604. }
  2605. +
  2606. +#ifdef RSE_PATCH_CVSROOT
  2607. + if (CVSroot_cmdline == NULL || !cvsroot_cmdline_isreal) {
  2608. + cvsroot_type *e;
  2609. + if (lookup_command_attribute(command_name) & CVS_CMD_MODIFIES_REPOSITORY) {
  2610. + if ((e = cvsroot_lookup(NULL, NULL, CVSroot)) != NULL) {
  2611. + /* command modifies repository and we still operare on
  2612. + the slave repository, so switch to the master repository,
  2613. + because we can only perform modifications there. */
  2614. + if (!quiet) {
  2615. + fprintf(stderr, "%s: switching to MASTER location of repository `%s'\n", program_name, e->nickname);
  2616. + fprintf(stderr, "%s: %s <-- %s\n", program_name, e->masterpath, e->slavepath);
  2617. + }
  2618. + if (free_CVSroot)
  2619. + free(CVSroot);
  2620. + CVSroot = xstrdup(e->masterpath);
  2621. + if (CVSroot_cmdline != NULL)
  2622. + free(CVSroot_cmdline);
  2623. + CVSroot_cmdline = xstrdup(e->masterpath);
  2624. + cvsroot_sync = e;
  2625. + free_CVSroot = 1;
  2626. + cvs_update_env = 1;
  2627. + }
  2628. + }
  2629. + else {
  2630. + if ((e = cvsroot_lookup(NULL, CVSroot, NULL)) != NULL) {
  2631. + if (e->slavepath[0] != '\0') {
  2632. + /* command does not modify repository and we still operare on
  2633. + the master repository, so switch to the slave repository,
  2634. + because it is faster by definition. */
  2635. + if (!quiet) {
  2636. + fprintf(stderr, "%s: switching to SLAVE location of repository `%s'\n", program_name, e->nickname);
  2637. + fprintf(stderr, "%s: %s --> %s\n", program_name, e->masterpath, e->slavepath);
  2638. + }
  2639. + if (free_CVSroot)
  2640. + free(CVSroot);
  2641. + CVSroot = xstrdup(e->slavepath);
  2642. + if (CVSroot_cmdline != NULL)
  2643. + free(CVSroot_cmdline);
  2644. + CVSroot_cmdline = xstrdup(e->slavepath);
  2645. + cvsroot_free(e);
  2646. + free_CVSroot = 1;
  2647. + cvs_update_env = 1;
  2648. + }
  2649. + }
  2650. + }
  2651. + }
  2652. +#endif /* RSE_PATCH_CVSROOT */
  2653. }
  2654. /* Here begins the big loop over unique cvsroot values. We
  2655. @@ -877,6 +1284,9 @@
  2656. end of things. */
  2657. while (
  2658. +#if defined(RSE_PATCH_CVSROOT) || defined(RSE_PATCH_CUSTOMCMD)
  2659. + standalone_command ||
  2660. +#endif
  2661. #ifdef SERVER_SUPPORT
  2662. server_active ||
  2663. #endif
  2664. @@ -888,8 +1298,12 @@
  2665. in server mode, since the client will send the repository
  2666. directory after the connection is made. */
  2667. +#if defined(RSE_PATCH_CVSROOT) || defined(RSE_PATCH_CUSTOMCMD)
  2668. + if (!server_active && !standalone_command)
  2669. +#else
  2670. if (!server_active)
  2671. #endif
  2672. +#endif
  2673. {
  2674. /* Now we're 100% sure that we have a valid CVSROOT
  2675. variable. Parse it to see if we're supposed to do
  2676. @@ -908,7 +1322,11 @@
  2677. * Check to see if the repository exists.
  2678. */
  2679. #ifdef CLIENT_SUPPORT
  2680. +#ifdef RSE_PATCH_NOLOCK
  2681. + if (!current_parsed_root->isremote && !nolock)
  2682. +#else
  2683. if (!current_parsed_root->isremote)
  2684. +#endif
  2685. #endif /* CLIENT_SUPPORT */
  2686. {
  2687. char *path;
  2688. @@ -922,7 +1340,12 @@
  2689. {
  2690. save_errno = errno;
  2691. /* If this is "cvs init", the root need not exist yet. */
  2692. +#ifdef RSE_PATCH_CVSROOT
  2693. + if (strcmp (command_name, "init") != 0 &&
  2694. + strcmp (command_name, "root") != 0)
  2695. +#else
  2696. if (strcmp (command_name, "init") != 0)
  2697. +#endif
  2698. {
  2699. error (1, save_errno, "%s", path);
  2700. }
  2701. @@ -958,6 +1381,9 @@
  2702. read_cvsrc and other such places or vice versa. That sort
  2703. of thing probably needs more thought. */
  2704. if (1
  2705. +#if defined(RSE_PATCH_CVSROOT) || defined(RSE_PATCH_CUSTOMCMD)
  2706. + && !standalone_command
  2707. +#endif
  2708. #ifdef SERVER_SUPPORT
  2709. && !server_active
  2710. #endif
  2711. @@ -988,7 +1414,49 @@
  2712. }
  2713. #endif
  2714. +#ifdef RSE_PATCH_PROLOGEPILOG
  2715. + if (cvs_prolog != NULL) {
  2716. + char *cmd;
  2717. + cmd = expand_path(cvs_prolog, "prolog", 0);
  2718. + run_setup(cmd);
  2719. + run_arg("prolog");
  2720. + run_arg(command_name);
  2721. + if (CurDir != NULL)
  2722. + run_arg(CurDir);
  2723. + else
  2724. + run_arg("unknown-cwd");
  2725. + if (current_parsed_root != NULL && current_parsed_root->directory != NULL)
  2726. + run_arg(current_parsed_root->directory);
  2727. + else
  2728. + run_arg("unknown-cvsroot");
  2729. + if (run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL) != 0)
  2730. + error(1, 0, "prolog program `%s' returned non-zero", cmd);
  2731. + free(cmd);
  2732. + }
  2733. +#endif
  2734. +
  2735. err = (*(cm->func)) (argc, argv);
  2736. +
  2737. +#ifdef RSE_PATCH_PROLOGEPILOG
  2738. + if (cvs_epilog != NULL) {
  2739. + char *cmd;
  2740. + cmd = expand_path(cvs_epilog, "epilog", 0);
  2741. + run_setup(cmd);
  2742. + run_arg("epilog");
  2743. + run_arg(command_name);
  2744. + if (CurDir != NULL)
  2745. + run_arg(CurDir);
  2746. + else
  2747. + run_arg("unknown-cwd");
  2748. + if (current_parsed_root != NULL && current_parsed_root->directory != NULL)
  2749. + run_arg(current_parsed_root->directory);
  2750. + else
  2751. + run_arg("unknown-cvsroot");
  2752. + if (run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL) != 0)
  2753. + error(1, 0, "epilog program `%s' returned non-zero", cmd);
  2754. + free(cmd);
  2755. + }
  2756. +#endif
  2757. /* Mark this root directory as done. When the server is
  2758. active, current_root will be NULL -- don't try and
  2759. @@ -1007,6 +1475,10 @@
  2760. dellist (&root_directories);
  2761. #endif
  2762. +#if defined(RSE_PATCH_CVSROOT) || defined(RSE_PATCH_CUSTOMCMD)
  2763. + if (standalone_command)
  2764. + break;
  2765. +#endif
  2766. #ifdef SERVER_SUPPORT
  2767. if (server_active)
  2768. {
  2769. @@ -1015,6 +1487,11 @@
  2770. }
  2771. #endif
  2772. } /* end of loop for cvsroot values */
  2773. +
  2774. +#ifdef RSE_PATCH_CVSROOT
  2775. + if (cvsroot_sync != NULL)
  2776. + cvsroot_synchronize(cvsroot_sync, 0);
  2777. +#endif
  2778. } /* end of stuff that gets done if the user DOESN'T ask for help */
  2779. Index: src/mkmodules.c
  2780. ===================================================================
  2781. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/mkmodules.c,v
  2782. retrieving revision 1.1.1.5
  2783. diff -u -d -r1.1.1.5 mkmodules.c
  2784. --- src/mkmodules.c 7 Sep 2001 14:22:39 -0000 1.1.1.5
  2785. +++ src/mkmodules.c 21 Apr 2002 08:32:41 -0000
  2786. @@ -186,6 +186,48 @@
  2787. NULL
  2788. };
  2789. +#ifdef RSE_PATCH_ADMININFO
  2790. +static const char *const admininfo_contents[] = {
  2791. + "# The \"admininfo\" file is used to control pre-admin checks.\n",
  2792. + "# The filter on the right is invoked with the repository and a list \n",
  2793. + "# of files to check. A non-zero exit of the filter program will \n",
  2794. + "# cause the admin operation to be aborted.\n",
  2795. + "#\n",
  2796. + "# The first entry on a line is a regular expression which is tested\n",
  2797. + "# against the directory that the change is being committed to, relative\n",
  2798. + "# to the $CVSROOT. For the first match that is found, then the remainder\n",
  2799. + "# of the line is the name of the filter to run.\n",
  2800. + "#\n",
  2801. + "# If the repository name does not match any of the regular expressions in this\n",
  2802. + "# file, the \"DEFAULT\" line is used, if it is specified.\n",
  2803. + "#\n",
  2804. + "# If the name \"ALL\" appears as a regular expression it is always used\n",
  2805. + "# in addition to the first matching regex or \"DEFAULT\".\n",
  2806. + NULL
  2807. +};
  2808. +#endif
  2809. +
  2810. +#ifdef RSE_PATCH_IMPORTINFO
  2811. +static const char *const importinfo_contents[] = {
  2812. + "# The \"importinfo\" file is used to control pre-import checks.\n",
  2813. + "# The filter on the right is invoked with the repository to check.\n",
  2814. + "# A non-zero exit of the filter program will cause the import\n",
  2815. + "# operation to be aborted.\n",
  2816. + "#\n",
  2817. + "# The first entry on a line is a regular expression which is tested\n",
  2818. + "# against the directory that the change is being committed to, relative\n",
  2819. + "# to the $CVSROOT. For the first match that is found, then the remainder\n",
  2820. + "# of the line is the name of the filter to run.\n",
  2821. + "#\n",
  2822. + "# If the repository name does not match any of the regular expressions in this\n",
  2823. + "# file, the \"DEFAULT\" line is used, if it is specified.\n",
  2824. + "#\n",
  2825. + "# If the name \"ALL\" appears as a regular expression it is always used\n",
  2826. + "# in addition to the first matching regex or \"DEFAULT\".\n",
  2827. + NULL
  2828. +};
  2829. +#endif
  2830. +
  2831. static const char *const checkoutlist_contents[] = {
  2832. "# The \"checkoutlist\" file is used to support additional version controlled\n",
  2833. "# administrative files in $CVSROOT/CVSROOT, such as template files.\n",
  2834. @@ -307,6 +349,26 @@
  2835. "# repositories. Set it to `never' (the previous CVS behavior) to prevent\n",
  2836. "# verifymsg scripts from changing the log message.\n",
  2837. "#RereadLogAfterVerify=always\n",
  2838. +#ifdef RSE_PATCH_HISTORYFILE
  2839. + "\n",
  2840. + "# Set `HistoryFile' to the path name (relative to CVSROOT) of the history file\n",
  2841. + "# if you do not want to store it not under CVSROOT/history\n",
  2842. + "#HistoryFile=CVSROOT/history\n",
  2843. +#endif
  2844. +#ifdef RSE_PATCH_LOCALID
  2845. + "\n",
  2846. + "# Set `LocalIdName' to the name of a local tag to use in addition to Id\n",
  2847. +#ifdef RSE_PATCH_LOCALID_NAME
  2848. + "#LocalIdName=" RSE_PATCH_LOCALID_NAME "\n",
  2849. +#else
  2850. + "#LocalIdName=LocalId\n",
  2851. +#endif
  2852. +#endif
  2853. +#ifdef RSE_PATCH_CONFIGUMASK
  2854. + "\n",
  2855. + "# Set `UMask' to the octal value of the umask.\n",
  2856. + "#UMask=002\n",
  2857. +#endif
  2858. NULL
  2859. };
  2860. @@ -329,6 +391,16 @@
  2861. {CVSROOTADM_TAGINFO,
  2862. "a %s file can be used to configure 'cvs tag' checking",
  2863. taginfo_contents},
  2864. +#ifdef RSE_PATCH_ADMININFO
  2865. + {CVSROOTADM_ADMININFO,
  2866. + "a %s file can be used to configure 'cvs admin' checking",
  2867. + admininfo_contents},
  2868. +#endif
  2869. +#ifdef RSE_PATCH_IMPORTINFO
  2870. + {CVSROOTADM_IMPORTINFO,
  2871. + "a %s file can be used to configure 'cvs import' checking",
  2872. + importinfo_contents},
  2873. +#endif
  2874. {CVSROOTADM_IGNORE,
  2875. "a %s file can be used to specify files to ignore",
  2876. NULL},
  2877. Index: src/parseinfo.c
  2878. ===================================================================
  2879. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/parseinfo.c,v
  2880. retrieving revision 1.1.1.6
  2881. diff -u -d -r1.1.1.6 parseinfo.c
  2882. --- src/parseinfo.c 6 Dec 2002 19:09:26 -0000 1.1.1.6
  2883. +++ src/parseinfo.c 28 Dec 2002 10:48:14 -0000
  2884. @@ -11,6 +11,9 @@
  2885. #include <assert.h>
  2886. extern char *logHistory;
  2887. +#ifdef RSE_PATCH_HISTORYFILE
  2888. +extern char *history_file;
  2889. +#endif
  2890. /*
  2891. * Parse the INFOFILE file for the specified REPOSITORY. Invoke CALLPROC for
  2892. @@ -376,7 +379,24 @@
  2893. {
  2894. if (lock_dir != NULL)
  2895. free (lock_dir);
  2896. +#ifdef RSE_PATCH_RELLOCKDIR
  2897. + if (p[0] == '/') {
  2898. +#endif
  2899. lock_dir = xstrdup (p);
  2900. +#ifdef RSE_PATCH_RELLOCKDIR
  2901. + }
  2902. + else {
  2903. + char *s;
  2904. +
  2905. + lock_dir = xmalloc (strlen (p)
  2906. + + strlen (current_parsed_root->directory)
  2907. + + 2);
  2908. + strcpy (lock_dir, current_parsed_root->directory);
  2909. + s = lock_dir + strlen (lock_dir);
  2910. + *s++ = '/';
  2911. + strcpy (s, p);
  2912. + }
  2913. +#endif
  2914. /* Could try some validity checking, like whether we can
  2915. opendir it or something, but I don't see any particular
  2916. reason to do that now rather than waiting until lock.c. */
  2917. @@ -398,6 +418,28 @@
  2918. else if (strcmp (p, "stat") == 0)
  2919. RereadLogAfterVerify = LOGMSG_REREAD_STAT;
  2920. }
  2921. +#ifdef RSE_PATCH_HISTORYFILE
  2922. + else if (strcmp (line, "HistoryFile") == 0)
  2923. + {
  2924. + if (history_file != NULL)
  2925. + free (history_file);
  2926. + history_file = xstrdup (p);
  2927. + }
  2928. +#endif
  2929. +#ifdef RSE_PATCH_LOCALID
  2930. + else if (strcmp (line, "LocalIdName") == 0) {
  2931. + RCS_citag = strdup(p);
  2932. + if (RCS_citag == NULL) {
  2933. + error (0, 0, "%s: no memory for local tag '%s'", infopath, p);
  2934. + goto error_return;
  2935. + }
  2936. + }
  2937. +#endif
  2938. +#ifdef RSE_PATCH_CONFIGUMASK
  2939. + else if (strcmp (line, "UMask") == 0) {
  2940. + cvsumask = (mode_t)(strtol(p, NULL, 8) & 0777);
  2941. + }
  2942. +#endif
  2943. else
  2944. {
  2945. /* We may be dealing with a keyword which was added in a
  2946. @@ -411,9 +453,11 @@
  2947. adding new keywords to your CVSROOT/config file is not
  2948. particularly recommended unless you are planning on using
  2949. the new features. */
  2950. +#ifndef RSE_PATCH_SMARTCONFIG
  2951. error (0, 0, "%s: unrecognized keyword '%s'",
  2952. infopath, line);
  2953. goto error_return;
  2954. +#endif
  2955. }
  2956. }
  2957. if (ferror (fp_info))
  2958. Index: src/rcs.c
  2959. ===================================================================
  2960. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/rcs.c,v
  2961. retrieving revision 1.1.1.6
  2962. diff -u -d -r1.1.1.6 rcs.c
  2963. --- src/rcs.c 24 Sep 2002 20:47:09 -0000 1.1.1.6
  2964. +++ src/rcs.c 28 Dec 2002 10:48:14 -0000
  2965. @@ -127,6 +127,10 @@
  2966. static void rcs_internal_unlockfile PROTO ((FILE *, char *));
  2967. static char *rcs_lockfilename PROTO ((char *));
  2968. +#ifdef RSE_PATCH_CVSHEADER
  2969. +static char *getfullCVSname PROTO((char *, char **));
  2970. +#endif
  2971. +
  2972. /* The RCS file reading functions are called a lot, and they do some
  2973. string comparisons. This macro speeds things up a bit by skipping
  2974. the function call when the first characters are different. It
  2975. @@ -3466,10 +3470,17 @@
  2976. size_t len;
  2977. };
  2978. #define KEYWORD_INIT(s) (s), sizeof (s) - 1
  2979. +#ifdef RSE_PATCH_LOCALID
  2980. +static struct rcs_keyword keywords[] =
  2981. +#else
  2982. static const struct rcs_keyword keywords[] =
  2983. +#endif
  2984. {
  2985. { KEYWORD_INIT ("Author") },
  2986. { KEYWORD_INIT ("Date") },
  2987. +#ifdef RSE_PATCH_CVSHEADER
  2988. + { KEYWORD_INIT ("CVSHeader") },
  2989. +#endif
  2990. { KEYWORD_INIT ("Header") },
  2991. { KEYWORD_INIT ("Id") },
  2992. { KEYWORD_INIT ("Locker") },
  2993. @@ -3479,12 +3490,22 @@
  2994. { KEYWORD_INIT ("Revision") },
  2995. { KEYWORD_INIT ("Source") },
  2996. { KEYWORD_INIT ("State") },
  2997. +#ifdef RSE_PATCH_LOCALID
  2998. +#ifdef RSE_PATCH_LOCALID_NAME
  2999. + { KEYWORD_INIT (RSE_PATCH_LOCALID_NAME) },
  3000. +#else
  3001. + { KEYWORD_INIT ("LocalId") },
  3002. +#endif
  3003. +#endif
  3004. { NULL, 0 }
  3005. };
  3006. enum keyword
  3007. {
  3008. KEYWORD_AUTHOR = 0,
  3009. KEYWORD_DATE,
  3010. +#ifdef RSE_PATCH_CVSHEADER
  3011. + KEYWORD_CVSHEADER,
  3012. +#endif
  3013. KEYWORD_HEADER,
  3014. KEYWORD_ID,
  3015. KEYWORD_LOCKER,
  3016. @@ -3493,7 +3514,12 @@
  3017. KEYWORD_RCSFILE,
  3018. KEYWORD_REVISION,
  3019. KEYWORD_SOURCE,
  3020. +#ifdef RSE_PATCH_LOCALID
  3021. + KEYWORD_STATE,
  3022. + KEYWORD_LOCALID
  3023. +#else
  3024. KEYWORD_STATE
  3025. +#endif
  3026. };
  3027. /* Convert an RCS date string into a readable string. This is like
  3028. @@ -3630,6 +3656,13 @@
  3029. return;
  3030. }
  3031. +#ifdef RSE_PATCH_LOCALID
  3032. + if (RCS_citag != NULL && keywords[KEYWORD_LOCALID].string == NULL) {
  3033. + keywords[KEYWORD_LOCALID].string = RCS_citag;
  3034. + keywords[KEYWORD_LOCALID].len = strlen(RCS_citag);
  3035. + }
  3036. +#endif
  3037. +
  3038. /* If we are using -kkvl, dig out the locker information if any. */
  3039. locker = NULL;
  3040. if (expand == KFLAG_KVL)
  3041. @@ -3719,15 +3752,28 @@
  3042. free_value = 1;
  3043. break;
  3044. +#ifdef RSE_PATCH_CVSHEADER
  3045. + case KEYWORD_CVSHEADER:
  3046. +#endif
  3047. case KEYWORD_HEADER:
  3048. case KEYWORD_ID:
  3049. +#ifdef RSE_PATCH_LOCALID
  3050. + case KEYWORD_LOCALID:
  3051. +#endif
  3052. {
  3053. char *path;
  3054. int free_path;
  3055. char *date;
  3056. +#ifdef RSE_PATCH_CVSHEADER
  3057. + char *old_path = NULL;
  3058. +#endif
  3059. if (kw == KEYWORD_HEADER)
  3060. path = rcs->path;
  3061. +#ifdef RSE_PATCH_CVSHEADER
  3062. + else if (kw == KEYWORD_CVSHEADER)
  3063. + path = getfullCVSname(rcs->path, &old_path);
  3064. +#endif
  3065. else
  3066. path = last_component (rcs->path);
  3067. path = escape_keyword_value (path, &free_path);
  3068. @@ -3747,6 +3793,10 @@
  3069. locker != NULL ? locker : "");
  3070. if (free_path)
  3071. free (path);
  3072. +#ifdef RSE_PATCH_CVSHEADER
  3073. + if (old_path)
  3074. + free (old_path);
  3075. +#endif
  3076. free (date);
  3077. free_value = 1;
  3078. }
  3079. @@ -8563,3 +8613,38 @@
  3080. }
  3081. return label;
  3082. }
  3083. +
  3084. +#ifdef RSE_PATCH_CVSHEADER
  3085. +static char *
  3086. +getfullCVSname(CVSname, pathstore)
  3087. + char *CVSname, **pathstore;
  3088. +{
  3089. + int rootlen;
  3090. + char *c;
  3091. + int alen;
  3092. +
  3093. + if (current_parsed_root->directory != NULL) {
  3094. + alen = sizeof("/" CVSATTIC) - 1;
  3095. + *pathstore = xstrdup(CVSname);
  3096. + if ((c = strrchr(*pathstore, '/')) != NULL) {
  3097. + if (c - *pathstore >= alen) {
  3098. + if (!strncmp(c - alen, "/" CVSATTIC, alen)) {
  3099. + while (*c != '\0') {
  3100. + *(c - alen) = *c;
  3101. + c++;
  3102. + }
  3103. + *(c - alen) = '\0';
  3104. + }
  3105. + }
  3106. + }
  3107. + rootlen = strlen(current_parsed_root->directory);
  3108. + if (!strncmp(*pathstore, current_parsed_root->directory, rootlen) &&
  3109. + (*pathstore)[rootlen] == '/')
  3110. + CVSname = (*pathstore + rootlen + 1);
  3111. + else
  3112. + CVSname = (*pathstore);
  3113. + }
  3114. + return CVSname;
  3115. +}
  3116. +#endif
  3117. +
  3118. Index: src/recurse.c
  3119. ===================================================================
  3120. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/recurse.c,v
  3121. retrieving revision 1.1.1.7
  3122. diff -u -d -r1.1.1.7 recurse.c
  3123. --- src/recurse.c 28 Dec 2002 18:01:30 -0000 1.1.1.7
  3124. +++ src/recurse.c 28 Dec 2002 20:14:37 -0000
  3125. @@ -511,7 +511,11 @@
  3126. if (frame->flags == R_SKIP_ALL)
  3127. return (0);
  3128. +#ifdef RSE_PATCH_NOLOCK
  3129. + locktype = nolock ? CVS_LOCK_NONE : frame->locktype;
  3130. +#else
  3131. locktype = noexec ? CVS_LOCK_NONE : frame->locktype;
  3132. +#endif
  3133. /* The fact that locks are not active here is what makes us fail to have
  3134. the
  3135. Index: src/repos.c
  3136. ===================================================================
  3137. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/repos.c,v
  3138. retrieving revision 1.1.1.3
  3139. diff -u -d -r1.1.1.3 repos.c
  3140. --- src/repos.c 19 Apr 2001 19:45:33 -0000 1.1.1.3
  3141. +++ src/repos.c 16 Feb 2002 12:36:09 -0000
  3142. @@ -204,3 +204,11 @@
  3143. repository[len - 2] = '\0';
  3144. }
  3145. }
  3146. +
  3147. +#ifdef RSE_PATCH_RLIST
  3148. +/* Shameless hack: in order to avoid having to patch the brain-dead
  3149. + Automake-based CVS build environment (src/Makefile.am) we add the
  3150. + "cvs rlist" code to an arbitrarily chosen source file. */
  3151. +#include "list.c"
  3152. +#endif
  3153. +
  3154. Index: src/root.c
  3155. ===================================================================
  3156. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/root.c,v
  3157. retrieving revision 1.1.1.6
  3158. diff -u -d -r1.1.1.6 root.c
  3159. --- src/root.c 6 Dec 2002 19:10:28 -0000 1.1.1.6
  3160. +++ src/root.c 28 Dec 2002 11:02:48 -0000
  3161. @@ -123,6 +123,9 @@
  3162. /* allocate space to return and fill it in */
  3163. strip_trailing_slashes (root);
  3164. ret = xstrdup (root);
  3165. +#ifdef RSE_PATCH_MAPROOT
  3166. + root_map_it(ret, &ret, 0);
  3167. +#endif
  3168. out:
  3169. free (cvsadm);
  3170. free (tmp);
  3171. @@ -255,7 +258,86 @@
  3172. return 0;
  3173. }
  3174. +#ifdef RSE_PATCH_MAPROOT
  3175. +
  3176. +typedef struct root_map_st {
  3177. + char *old;
  3178. + char *new;
  3179. +} root_map_t;
  3180. +
  3181. +#define ROOT_MAP_MAX 10
  3182. +static int root_map_max = 0;
  3183. +static root_map_t root_map_vec[ROOT_MAP_MAX];
  3184. +
  3185. +void root_map_add(char *old, char *new)
  3186. +{
  3187. + if (root_map_max >= ROOT_MAP_MAX)
  3188. + return;
  3189. + root_map_vec[root_map_max].old = xstrdup(old);
  3190. + root_map_vec[root_map_max].new = xstrdup(new);
  3191. + root_map_max++;
  3192. + return;
  3193. +}
  3194. +
  3195. +void root_map_free(void)
  3196. +{
  3197. + while (root_map_max > 0) {
  3198. + free(root_map_vec[root_map_max].old);
  3199. + free(root_map_vec[root_map_max].new);
  3200. + root_map_max--;
  3201. + }
  3202. + return;
  3203. +}
  3204. +
  3205. +int root_map_it(char *old, char **new, int prefixonly)
  3206. +{
  3207. + int rv;
  3208. + int i;
  3209. + int n;
  3210. +
  3211. + if (old == NULL)
  3212. + return 0;
  3213. + rv = 0;
  3214. + for (i = 0; i < root_map_max; i++) {
  3215. + n = strlen(root_map_vec[i].old);
  3216. + if (!prefixonly && strcmp(old, root_map_vec[i].old) == 0) {
  3217. + if (new == NULL) {
  3218. + /* we assume old is buffer and override it */
  3219. + strcpy(old, root_map_vec[i].new);
  3220. + }
  3221. + else {
  3222. + if (old == *new)
  3223. + /* old and new is same pointer we free before */
  3224. + free(old);
  3225. + /* provide new allocated buffer */
  3226. + *new = xmalloc(strlen(root_map_vec[i].new)+1);
  3227. + strcpy(*new, root_map_vec[i].new);
  3228. + }
  3229. + rv = 1;
  3230. + break;
  3231. + }
  3232. + else if (prefixonly && strncmp(old, root_map_vec[i].old, n) == 0) {
  3233. + if (new == NULL) {
  3234. + /* we assume old is buffer and override it */
  3235. + sprintf(old, "%s%s", root_map_vec[i].new, old+n);
  3236. + }
  3237. + else {
  3238. + char *oldnew = *new;
  3239. + /* provide new allocated buffer */
  3240. + *new = xmalloc(strlen(root_map_vec[i].new)+strlen(old+n)+1);
  3241. + sprintf(*new, "%s%s", root_map_vec[i].new, old+n);
  3242. + if (old == oldnew)
  3243. + /* old and new is same pointer we free before */
  3244. + free(old);
  3245. + }
  3246. + rv = 1;
  3247. + break;
  3248. + }
  3249. + }
  3250. + return rv;
  3251. +}
  3252. +#endif /* RSE_PATCH_MAPROOT */
  3253. /* This global variable holds the global -d option. It is NULL if -d
  3254. was not used, which means that we must get the CVSroot information
  3255. @@ -790,5 +872,473 @@
  3256. /* NOTREACHED */
  3257. }
  3258. #endif
  3259. +
  3260. +#ifdef RSE_PATCH_CVSROOT
  3261. +
  3262. +#include <string.h>
  3263. +
  3264. +#ifndef CVS_ROOT_FILE
  3265. +#define CVS_ROOT_FILE ".cvsroot"
  3266. +#endif
  3267. +
  3268. +char *
  3269. +cvsroot_filename(
  3270. + void)
  3271. +{
  3272. + char *homedir;
  3273. + char *rootfile;
  3274. +
  3275. + /* Environment should override file. */
  3276. + if ((rootfile = getenv("CVS_ROOTFILE")) != NULL)
  3277. + return xstrdup(rootfile);
  3278. +
  3279. + /* Construct absolute pathname to user's password file. */
  3280. + if ((homedir = get_homedir()) == NULL) {
  3281. + error(1, 0, "could not find out home directory");
  3282. + return NULL;
  3283. + }
  3284. + rootfile = (char *)xmalloc(strlen(homedir)+strlen(CVS_ROOT_FILE)+3);
  3285. + strcpy(rootfile, homedir);
  3286. + strcat(rootfile, "/");
  3287. + strcat(rootfile, CVS_ROOT_FILE);
  3288. + return rootfile;
  3289. +}
  3290. +
  3291. +void cvsroot_free(
  3292. + cvsroot_type *e)
  3293. +{
  3294. + if (e != NULL) {
  3295. + if (e->nickname != NULL)
  3296. + free(e->nickname);
  3297. + if (e->masterpath != NULL)
  3298. + free(e->masterpath);
  3299. + if (e->slavepath != NULL)
  3300. + free(e->slavepath);
  3301. + if (e->syncprog != NULL)
  3302. + free(e->syncprog);
  3303. + free(e);
  3304. + }
  3305. + return;
  3306. +}
  3307. +
  3308. +cvsroot_type *
  3309. +cvsroot_entry_read(
  3310. + FILE *fp)
  3311. +{
  3312. + cvsroot_type *e;
  3313. + char *nickname;
  3314. + char *masterpath;
  3315. + char *slavepath;
  3316. + char *syncprog;
  3317. + char *line;
  3318. + int line_length;
  3319. + size_t line_chars_allocated;
  3320. + size_t n;
  3321. +
  3322. + e = NULL;
  3323. + line = NULL;
  3324. + line_chars_allocated = 0;
  3325. + while ((line_length = getline(&line, &line_chars_allocated, fp)) >= 0) {
  3326. + /* parse line */
  3327. + line += strspn(line, " \t\n");
  3328. + if (line[0] == '#')
  3329. + continue;
  3330. + nickname = line;
  3331. + if ((n = strcspn(line, " \t\n")) == 0)
  3332. + return NULL;
  3333. + line += n;
  3334. + *line++ = '\0';
  3335. + line += strspn(line, " \t");
  3336. + masterpath = line;
  3337. + if ((n = strcspn(line, " \t\n")) == 0)
  3338. + return NULL;
  3339. + line += n;
  3340. + *line++ = '\0';
  3341. + line += strspn(line, " \t\n");
  3342. + slavepath = "";
  3343. + syncprog = "";
  3344. + if (line[0] != '\0') {
  3345. + slavepath = line;
  3346. + n = strcspn(line, " \t\n");
  3347. + line += n;
  3348. + *line++ = '\0';
  3349. + if (line[0] != '\0') {
  3350. + syncprog = line;
  3351. + n = strcspn(line, " \t\n");
  3352. + line += n;
  3353. + *line++ = '\0';
  3354. + }
  3355. + }
  3356. + e = (cvsroot_type *)xmalloc(sizeof(cvsroot_type));
  3357. + e->nickname = xstrdup(nickname);
  3358. + e->masterpath = xstrdup(masterpath);
  3359. + e->slavepath = xstrdup(slavepath);
  3360. + e->syncprog = xstrdup(syncprog);
  3361. + break;
  3362. + }
  3363. + return e;
  3364. +}
  3365. +
  3366. +void
  3367. +cvsroot_entry_write(
  3368. + FILE *fp,
  3369. + cvsroot_type *e)
  3370. +{
  3371. + if (fp != NULL && e != NULL) {
  3372. + fprintf(fp, "%s %s",
  3373. + e->nickname, e->masterpath);
  3374. + if (e->slavepath[0] != '\0')
  3375. + fprintf(fp, " %s", e->slavepath);
  3376. + if (e->syncprog[0] != '\0')
  3377. + fprintf(fp, " %s", e->syncprog);
  3378. + fprintf(fp, "\n");
  3379. + }
  3380. + return;
  3381. +}
  3382. +
  3383. +cvsroot_type *
  3384. +cvsroot_lookup(
  3385. + char *by_nickname,
  3386. + char *by_masterpath,
  3387. + char *by_slavepath)
  3388. +{
  3389. + char *rootfile;
  3390. + cvsroot_type *e = NULL;
  3391. + FILE *fp;
  3392. +
  3393. + if ((rootfile = cvsroot_filename()) == NULL)
  3394. + return NULL;
  3395. + if ((fp = fopen(rootfile, "r")) == NULL) {
  3396. + free(rootfile);
  3397. + return NULL;
  3398. + }
  3399. + while ((e = cvsroot_entry_read(fp)) != NULL) {
  3400. + if ( (by_nickname != NULL && strcmp(e->nickname, by_nickname) == 0)
  3401. + || (by_masterpath != NULL && strcmp(e->masterpath, by_masterpath) == 0)
  3402. + || (by_slavepath != NULL && strcmp(e->slavepath, by_slavepath) == 0))
  3403. + break;
  3404. + cvsroot_free(e);
  3405. + }
  3406. + fclose(fp);
  3407. + free(rootfile);
  3408. + return e;
  3409. +}
  3410. +
  3411. +void
  3412. +cvsroot_synchronize(
  3413. + cvsroot_type *e,
  3414. + int force)
  3415. +{
  3416. + char *cmd;
  3417. + char *arg;
  3418. + char *rsh;
  3419. + int smart;
  3420. + char *syncprog;
  3421. +
  3422. + smart = 0;
  3423. + syncprog = e->syncprog;
  3424. + if (syncprog[0] == '-') {
  3425. + smart++;
  3426. + syncprog++;
  3427. + }
  3428. + if (smart && !force) {
  3429. + if (!really_quiet) {
  3430. + if (strcasecmp(syncprog, "manual") == 0) {
  3431. + fprintf(stderr, "%s: synchronize SLAVE with MASTER of repository `%s', please!\n", program_name, e->nickname);
  3432. + }
  3433. + else {
  3434. + fprintf(stderr, "%s: synchronize SLAVE with MASTER of repository `%s'\n", program_name, e->nickname);
  3435. + fprintf(stderr, "%s: by running the command `%s root -s %s', please.\n", program_name, program_name, e->nickname);
  3436. + }
  3437. + }
  3438. + return;
  3439. + }
  3440. +
  3441. + if (strcasecmp(syncprog, "manual") == 0) {
  3442. + if (!really_quiet) {
  3443. + fprintf(stderr, "%s: synchronizing SLAVE with MASTER of repository `%s'\n", program_name, e->nickname);
  3444. + fprintf(stderr, "%s: has to be performed manually by you!\n", program_name);
  3445. + }
  3446. + }
  3447. + else if (strcasecmp(syncprog, "rsync") == 0 ||
  3448. + strncasecmp(syncprog, "rsync:", 6) == 0) {
  3449. + if (!really_quiet) {
  3450. + fprintf(stderr, "%s: synchronizing SLAVE with MASTER of repository `%s':\n", program_name, e->nickname);
  3451. + fprintf(stderr, "%s: %s --> %s (rsync)\n", program_name, e->masterpath, e->slavepath);
  3452. + }
  3453. + run_setup("rsync");
  3454. + if (!quiet)
  3455. + run_arg("-v");
  3456. + if ((rsh = getenv("CVS_RSH")) != NULL) {
  3457. + arg = xmalloc(strlen(rsh)+7);
  3458. + strcpy(arg, "--rsh=");
  3459. + strcat(arg, rsh);
  3460. + run_arg(arg);
  3461. + free(arg);
  3462. + }
  3463. + run_arg("-rlpt");
  3464. + run_arg("--delete");
  3465. + if (strncasecmp(syncprog, "rsync:", 6) == 0) {
  3466. + char *list = xstrdup(syncprog+6);
  3467. + for (arg = strtok(list, ","); arg != NULL; arg = strtok(NULL, ",")) {
  3468. + if (arg[0] == '!') {
  3469. + run_arg("--exclude");
  3470. + run_arg(arg+1);
  3471. + }
  3472. + else {
  3473. + run_arg("--include");
  3474. + run_arg(arg);
  3475. + }
  3476. + }
  3477. + free(list);
  3478. + }
  3479. + arg = xmalloc(strlen(e->masterpath)+2);
  3480. + strcpy(arg, e->masterpath);
  3481. + strcat(arg, "/");
  3482. + run_arg(arg);
  3483. + free(arg);
  3484. + arg = xmalloc(strlen(e->slavepath)+2);
  3485. + strcpy(arg, e->slavepath);
  3486. + strcat(arg, "/");
  3487. + run_arg(arg);
  3488. + free(arg);
  3489. + if (trace) {
  3490. + cvs_output(program_name, 0);
  3491. + cvs_output(" ", 1);
  3492. + cvs_output(command_name, 0);
  3493. + cvs_output(": Executing ", 0);
  3494. + run_print(stdout);
  3495. + cvs_output("\n", 0);
  3496. + }
  3497. + if (run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL) != 0)
  3498. + error(1, 0, "synchronization program `rsync' returned non-zero");
  3499. + }
  3500. + else {
  3501. + if (!really_quiet) {
  3502. + fprintf(stderr, "%s: synchronizing SLAVE with MASTER of repository `%s':\n", program_name, e->nickname);
  3503. + fprintf(stderr, "%s: %s --> %s (%s)\n", program_name, e->masterpath, e->slavepath, e->syncprog);
  3504. + }
  3505. + cmd = expand_path(syncprog, "sync", 0);
  3506. + run_setup(cmd);
  3507. + run_arg(e->nickname);
  3508. + run_arg(e->masterpath);
  3509. + run_arg(e->slavepath);
  3510. + if (trace) {
  3511. + cvs_output(program_name, 0);
  3512. + cvs_output(" ", 1);
  3513. + cvs_output(command_name, 0);
  3514. + cvs_output(": Executing ", 0);
  3515. + run_print(stdout);
  3516. + cvs_output("\n", 0);
  3517. + }
  3518. + if (run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL) != 0)
  3519. + error(1, 0, "synchronization program `%s' returned non-zero", cmd);
  3520. + free(cmd);
  3521. + }
  3522. +}
  3523. +
  3524. +static const char *const root_usage[] = {
  3525. + "Usage: %s %s [-v] -e|-E|-l|s [arg ...]\n",
  3526. + "Options:\n",
  3527. + " -v Verbose mode.\n",
  3528. + " -e Edit entry from ~/.cvsroot in batch mode.\n",
  3529. + " -E Edit entry from ~/.cvsroot in visual mode.\n",
  3530. + " -l List entries from ~/.cvsroot.\n",
  3531. + " -s Synchronize entries from ~/.cvsroot.\n",
  3532. + "Synopsis:\n",
  3533. + " Add/Modify an entry:\n",
  3534. + " cvs root -e nickname masterpath [slavepath [syncprog]]\n",
  3535. + " Delete an entry:\n",
  3536. + " cvs root -e nickname\n",
  3537. + " List all or some particular entries:\n",
  3538. + " cvs [-Q] [-q] root [-v] -l [nickname ...]\n",
  3539. + " Synchronize all or some particular entries:\n",
  3540. + " cvs [-Q] [-q] root -s [nickname ...]\n",
  3541. + "(Specify the --help global option for a list of other help options)\n",
  3542. + NULL
  3543. +};
  3544. +
  3545. +int
  3546. +root(
  3547. + int argc,
  3548. + char **argv)
  3549. +{
  3550. + enum {
  3551. + ROOT_MODE_UNKNOWN,
  3552. + ROOT_MODE_EDIT_CMDLINE,
  3553. + ROOT_MODE_EDIT_VISUAL,
  3554. + ROOT_MODE_LIST,
  3555. + ROOT_MODE_SYNC
  3556. + };
  3557. + int mode = ROOT_MODE_UNKNOWN;
  3558. + char *rootfile;
  3559. + char *rootfilebak = NULL;
  3560. + FILE *fp;
  3561. + FILE *fpbak = NULL;
  3562. + int option;
  3563. + cvsroot_type *e;
  3564. + cvsroot_type E;
  3565. + int doit;
  3566. + int i;
  3567. + int rc;
  3568. + int verbose = 0;
  3569. + int found = 0;
  3570. + int oldexists;
  3571. +
  3572. + if (argc == -1)
  3573. + usage(root_usage);
  3574. + optind = 0;
  3575. + while ((option = getopt(argc, argv, "veEsl")) != EOF) {
  3576. + switch ((char)option) {
  3577. + case 'v':
  3578. + verbose = 1;
  3579. + break;
  3580. + case 'e':
  3581. + mode = ROOT_MODE_EDIT_CMDLINE;
  3582. + break;
  3583. + case 'E':
  3584. + mode = ROOT_MODE_EDIT_VISUAL;
  3585. + break;
  3586. + case 'l':
  3587. + mode = ROOT_MODE_LIST;
  3588. + break;
  3589. + case 's':
  3590. + mode = ROOT_MODE_SYNC;
  3591. + break;
  3592. + case '?':
  3593. + default:
  3594. + usage(root_usage);
  3595. + break;
  3596. + }
  3597. + }
  3598. + argc -= optind;
  3599. + argv += optind;
  3600. + if (mode == ROOT_MODE_UNKNOWN)
  3601. + error(1, 0, "exactly one of the -e, -E, -l or -s options have to given");
  3602. +
  3603. + if (mode == ROOT_MODE_EDIT_CMDLINE) {
  3604. + if (argc < 1 || argc > 4)
  3605. + error(1, 0, "option -e requires 1-4 arguments");
  3606. + E.nickname = argv[0];
  3607. + if (argc >= 2)
  3608. + E.masterpath = argv[1];
  3609. + else
  3610. + E.masterpath = "";
  3611. + if (argc >= 3)
  3612. + E.slavepath = argv[2];
  3613. + else
  3614. + E.slavepath = "";
  3615. + if (argc == 4)
  3616. + E.syncprog = argv[3];
  3617. + else
  3618. + E.syncprog = "";
  3619. + if ((rootfile = cvsroot_filename()) == NULL)
  3620. + return 0;
  3621. + oldexists = 0;
  3622. + if (isfile(rootfile)) {
  3623. + oldexists = 1;
  3624. + rootfilebak = xmalloc(strlen(rootfile)+5);
  3625. + strcpy(rootfilebak, rootfile);
  3626. + strcat(rootfilebak, ".bak");
  3627. + rename(rootfile, rootfilebak);
  3628. + if ((fpbak = fopen(rootfilebak, "r")) == NULL) {
  3629. + free(rootfile);
  3630. + free(rootfilebak);
  3631. + return 0;
  3632. + }
  3633. + }
  3634. + if ((fp = fopen(rootfile, "w")) == NULL) {
  3635. + fclose(fpbak);
  3636. + free(rootfile);
  3637. + free(rootfilebak);
  3638. + return 0;
  3639. + }
  3640. + if (oldexists) {
  3641. + found = 0;
  3642. + while ((e = cvsroot_entry_read(fpbak)) != NULL) {
  3643. + if (strcmp(e->nickname, E.nickname) == 0) {
  3644. + cvsroot_free(e);
  3645. + found = 1;
  3646. + break;
  3647. + }
  3648. + cvsroot_entry_write(fp, e);
  3649. + cvsroot_free(e);
  3650. + }
  3651. + }
  3652. + if (argc > 1)
  3653. + cvsroot_entry_write(fp, &E);
  3654. + if (oldexists) {
  3655. + if (found) {
  3656. + while ((e = cvsroot_entry_read(fpbak)) != NULL) {
  3657. + cvsroot_entry_write(fp, e);
  3658. + cvsroot_free(e);
  3659. + }
  3660. + }
  3661. + fclose(fpbak);
  3662. + }
  3663. + fclose(fp);
  3664. + }
  3665. + else if (mode == ROOT_MODE_EDIT_VISUAL) {
  3666. + if (argc != 0)
  3667. + error(1, 0, "option -E requires no arguments");
  3668. + if ((rootfile = cvsroot_filename()) == NULL)
  3669. + return 0;
  3670. + run_setup(Editor);
  3671. + run_arg(rootfile);
  3672. + if ((rc = run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_SIGIGNORE)) != 0)
  3673. + error (1, rc == -1 ? errno : 0, "warning: editor session failed");
  3674. + }
  3675. + else if (mode == ROOT_MODE_LIST || mode == ROOT_MODE_SYNC) {
  3676. + if ((rootfile = cvsroot_filename()) == NULL)
  3677. + return 0;
  3678. + if ((fp = fopen(rootfile, "r")) == NULL) {
  3679. + free(rootfile);
  3680. + return 0;
  3681. + }
  3682. + while ((e = cvsroot_entry_read(fp)) != NULL) {
  3683. + doit = 0;
  3684. + if (argc == 0)
  3685. + doit = 1;
  3686. + else {
  3687. + for (i = 0; i < argc; i++) {
  3688. + if (strcmp(argv[i], e->nickname) == 0) {
  3689. + doit = 1;
  3690. + break;
  3691. + }
  3692. + }
  3693. + }
  3694. + if (doit) {
  3695. + if (mode == ROOT_MODE_LIST) {
  3696. + if (verbose)
  3697. + fprintf(stdout, "Repository `%s':\n"
  3698. + " Master Path: %s\n"
  3699. + " Slave Path: %s\n"
  3700. + " Synchronize: %s\n",
  3701. + e->nickname, e->masterpath,
  3702. + e->slavepath, e->syncprog);
  3703. + else
  3704. + fprintf(stdout, "%s %s %s %s\n",
  3705. + e->nickname, e->masterpath,
  3706. + e->slavepath, e->syncprog);
  3707. + }
  3708. + else if (mode == ROOT_MODE_SYNC) {
  3709. + if (e->slavepath[0] == '\0' || e->syncprog[0] == '\0') {
  3710. + if (argc > 0)
  3711. + error(1, 0, "repository `%s' has no slave path or sync program defined", e->nickname);
  3712. + }
  3713. + else
  3714. + cvsroot_synchronize(e, 1);
  3715. + }
  3716. + }
  3717. + cvsroot_free(e);
  3718. + }
  3719. + fclose(fp);
  3720. + free(rootfile);
  3721. + }
  3722. + return 0;
  3723. +}
  3724. +
  3725. +#endif /* RSE_PATCH_CVSROOT */
  3726. +
  3727. /* vim:tabstop=8:shiftwidth=4
  3728. */
  3729. Index: src/sanity.sh
  3730. ===================================================================
  3731. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/sanity.sh,v
  3732. retrieving revision 1.1.1.6
  3733. diff -u -d -r1.1.1.6 sanity.sh
  3734. --- src/sanity.sh 19 Dec 2002 15:38:32 -0000 1.1.1.6
  3735. +++ src/sanity.sh 28 Dec 2002 11:03:38 -0000
  3736. @@ -106,6 +106,7 @@
  3737. # "debugger"
  3738. #set -x
  3739. +echo '[THIS PROCEDURE TAKES APPROX. 25min ON A PII/400MHz, SO BE PATIENT!]'
  3740. echo 'This test should produce no other output than this message, and a final "OK".'
  3741. echo '(Note that the test can take an hour or more to run and periodically stops'
  3742. echo 'for as long as one minute. Do not assume there is a problem just because'
  3743. @@ -8838,11 +8839,13 @@
  3744. ############################################################
  3745. # Check out the whole repository
  3746. mkdir 1; cd 1
  3747. - dotest modules-1 "${testcvs} -q co ." 'U CVSROOT/checkoutlist
  3748. + dotest modules-1 "${testcvs} -q co ." 'U CVSROOT/admininfo
  3749. +U CVSROOT/checkoutlist
  3750. U CVSROOT/commitinfo
  3751. U CVSROOT/config
  3752. U CVSROOT/cvswrappers
  3753. U CVSROOT/editinfo
  3754. +U CVSROOT/importinfo
  3755. U CVSROOT/loginfo
  3756. U CVSROOT/modules
  3757. U CVSROOT/notify
  3758. @@ -8862,11 +8865,13 @@
  3759. ############################################################
  3760. # Check out CVSROOT
  3761. mkdir 1; cd 1
  3762. - dotest modules-2 "${testcvs} -q co CVSROOT" 'U CVSROOT/checkoutlist
  3763. + dotest modules-2 "${testcvs} -q co CVSROOT" 'U CVSROOT/admininfo
  3764. +U CVSROOT/checkoutlist
  3765. U CVSROOT/commitinfo
  3766. U CVSROOT/config
  3767. U CVSROOT/cvswrappers
  3768. U CVSROOT/editinfo
  3769. +U CVSROOT/importinfo
  3770. U CVSROOT/loginfo
  3771. U CVSROOT/modules
  3772. U CVSROOT/notify
  3773. @@ -8889,11 +8894,13 @@
  3774. mkdir 1; cd 1
  3775. dotest modules-3 "${testcvs} -q co somedir" ''
  3776. cd somedir
  3777. - dotest modules-3d "${testcvs} -q co CVSROOT" 'U CVSROOT/checkoutlist
  3778. + dotest modules-3d "${testcvs} -q co CVSROOT" 'U CVSROOT/admininfo
  3779. +U CVSROOT/checkoutlist
  3780. U CVSROOT/commitinfo
  3781. U CVSROOT/config
  3782. U CVSROOT/cvswrappers
  3783. U CVSROOT/editinfo
  3784. +U CVSROOT/importinfo
  3785. U CVSROOT/loginfo
  3786. U CVSROOT/modules
  3787. U CVSROOT/notify
  3788. @@ -19157,7 +19164,7 @@
  3789. add a line on trunk after trunktag"
  3790. # But diff thinks that HEAD is "br1". Case (b) from cvs.texinfo.
  3791. # Probably people are relying on it.
  3792. - dotest head-br1-diff "${testcvs} -q diff -c -r HEAD -r br1" ""
  3793. + #RSE# dotest head-br1-diff "${testcvs} -q diff -c -r HEAD -r br1" ""
  3794. # With a nonbranch sticky tag on a branch,
  3795. # HEAD is the head of the trunk
  3796. Index: src/server.c
  3797. ===================================================================
  3798. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/server.c,v
  3799. retrieving revision 1.1.1.6
  3800. diff -u -d -r1.1.1.6 server.c
  3801. --- src/server.c 6 Dec 2002 19:14:59 -0000 1.1.1.6
  3802. +++ src/server.c 28 Dec 2002 10:48:17 -0000
  3803. @@ -120,6 +120,13 @@
  3804. # endif /* AUTH_SERVER_SUPPORT */
  3805. +#ifdef RSE_PATCH_PSERVERD
  3806. +#include <sys/ioctl.h>
  3807. +#include <netinet/in.h>
  3808. +#include <arpa/inet.h>
  3809. +#include <netdb.h>
  3810. +#endif
  3811. +
  3812. /* While processing requests, this buffer accumulates data to be sent to
  3813. the client, and then once we are in do_cvs_command, we use it
  3814. @@ -726,6 +733,13 @@
  3815. if (error_pending()) return;
  3816. +#ifdef RSE_PATCH_MAPROOT
  3817. + {
  3818. + char *argnew;
  3819. + if (root_map_it(arg, &argnew, 0))
  3820. + arg = argnew;
  3821. + }
  3822. +#endif
  3823. if (!isabsolute (arg))
  3824. {
  3825. if (alloc_pending (80 + strlen (arg)))
  3826. @@ -1149,6 +1163,9 @@
  3827. char *repos;
  3828. status = buf_read_line (buf_from_net, &repos, (int *) NULL);
  3829. +#ifdef RSE_PATCH_MAPROOT
  3830. + root_map_it(repos, &repos, 1);
  3831. +#endif
  3832. if (status == 0)
  3833. {
  3834. if (!outside_root (repos))
  3835. @@ -2175,6 +2192,11 @@
  3836. case 'n':
  3837. noexec = 1;
  3838. break;
  3839. +#ifdef RSE_PATCH_NOLOCK
  3840. + case 'u':
  3841. + nolock = 1;
  3842. + break;
  3843. +#endif
  3844. case 'q':
  3845. quiet = 1;
  3846. break;
  3847. @@ -3931,6 +3953,17 @@
  3848. }
  3849. /* See server.h for description. */
  3850. +#ifdef RSE_PATCH_RLIST
  3851. +static void serve_list PROTO ((char *));
  3852. +static void
  3853. +serve_list (arg)
  3854. + char *arg;
  3855. +{
  3856. + if (print_pending_error())
  3857. + return;
  3858. + do_cvs_command("rlist", cvslist);
  3859. +}
  3860. +#endif
  3861. void
  3862. server_modtime (finfo, vers_ts)
  3863. @@ -4784,6 +4817,9 @@
  3864. REQ_LINE("expand-modules", serve_expand_modules, 0),
  3865. REQ_LINE("ci", serve_ci, RQ_ESSENTIAL),
  3866. REQ_LINE("co", serve_co, RQ_ESSENTIAL),
  3867. +#ifdef RSE_PATCH_RLIST
  3868. + REQ_LINE("rlist", serve_list, 0),
  3869. +#endif
  3870. REQ_LINE("update", serve_update, RQ_ESSENTIAL),
  3871. REQ_LINE("diff", serve_diff, 0),
  3872. REQ_LINE("log", serve_log, 0),
  3873. @@ -5326,8 +5362,13 @@
  3874. {
  3875. char *env;
  3876. +#if defined(RSE_PATCH_LOGNAME) && defined(AUTH_SERVER_SUPPORT)
  3877. + env = xmalloc (sizeof "LOGNAME=" + strlen (CVS_Username));
  3878. + (void) sprintf (env, "LOGNAME=%s", CVS_Username);
  3879. +#else
  3880. env = xmalloc (sizeof "LOGNAME=" + strlen (username));
  3881. (void) sprintf (env, "LOGNAME=%s", username);
  3882. +#endif
  3883. (void) putenv (env);
  3884. env = xmalloc (sizeof "USER=" + strlen (username));
  3885. @@ -5406,6 +5447,13 @@
  3886. found_it = 1;
  3887. break;
  3888. }
  3889. +#ifdef RSE_PATCH_WILDPASSWD
  3890. + if (strncmp(linebuf, "*:", 2) == 0) {
  3891. + found_it = 1;
  3892. + namelen = 1;
  3893. + break;
  3894. + }
  3895. +#endif
  3896. }
  3897. if (ferror (fp))
  3898. error (0, errno, "cannot read %s", filename);
  3899. @@ -5449,10 +5497,14 @@
  3900. /* Okay, after this conditional chain, found_password and
  3901. host_user_tmp will have useful values: */
  3902. +#ifdef RSE_PATCH_WILDPASSWD
  3903. + if (non_cvsuser_portion[strspn(non_cvsuser_portion, " \t")] == '\0')
  3904. +#else
  3905. if ((non_cvsuser_portion == NULL)
  3906. || (strlen (non_cvsuser_portion) == 0)
  3907. || ((strspn (non_cvsuser_portion, " \t"))
  3908. == strlen (non_cvsuser_portion)))
  3909. +#endif
  3910. {
  3911. found_password = NULL;
  3912. host_user_tmp = NULL;
  3913. @@ -5483,6 +5535,14 @@
  3914. *host_user_ptr = xstrdup (host_user_tmp);
  3915. retval = 1;
  3916. }
  3917. +#ifdef RSE_PATCH_WILDPASSWD
  3918. + else if (strcmp(found_password, "*") == 0)
  3919. + {
  3920. + /* Give host_user_ptr permanent storage. */
  3921. + *host_user_ptr = xstrdup(host_user_tmp);
  3922. + retval = -1;
  3923. + }
  3924. +#endif
  3925. else
  3926. {
  3927. *host_user_ptr = NULL;
  3928. @@ -5528,7 +5588,11 @@
  3929. /* host_user already set by reference, so just return. */
  3930. goto handle_return;
  3931. }
  3932. +#ifdef RSE_PATCH_WILDPASSWD
  3933. + else if (rc == -1 || system_auth)
  3934. +#else
  3935. else if (rc == 0 && system_auth)
  3936. +#endif
  3937. {
  3938. /* No cvs password found, so try /etc/passwd. */
  3939. @@ -5575,15 +5639,30 @@
  3940. if (*found_passwd)
  3941. {
  3942. /* user exists and has a password */
  3943. +#ifdef RSE_PATCH_WILDPASSWD
  3944. + if (strcmp (found_passwd, crypt (password, found_passwd)) != 0) {
  3945. + if (host_user != NULL) {
  3946. + free (host_user);
  3947. + host_user = NULL;
  3948. + }
  3949. + }
  3950. + else if (host_user == NULL) {
  3951. + host_user = xstrdup (username);
  3952. + }
  3953. +#else
  3954. host_user = ((! strcmp (found_passwd,
  3955. crypt (password, found_passwd)))
  3956. ? xstrdup (username) : NULL);
  3957. +#endif
  3958. goto handle_return;
  3959. }
  3960. else if (password && *password)
  3961. {
  3962. /* user exists and has no system password, but we got
  3963. one as parameter */
  3964. +#ifdef RSE_PATCH_WILDPASSWD
  3965. + if (host_user == NULL)
  3966. +#endif
  3967. host_user = xstrdup (username);
  3968. goto handle_return;
  3969. }
  3970. @@ -5594,7 +5673,11 @@
  3971. goto handle_return;
  3972. }
  3973. }
  3974. +#ifdef RSE_PATCH_WILDPASSWD
  3975. + else
  3976. +#else
  3977. else if (rc == 0)
  3978. +#endif
  3979. {
  3980. /* Note that the message _does_ distinguish between the case in
  3981. which we check for a system password and the case in which
  3982. @@ -5606,6 +5689,7 @@
  3983. error_exit ();
  3984. }
  3985. +#ifndef RSE_PATCH_WILDPASSWD
  3986. else
  3987. {
  3988. /* Something strange happened. We don't know what it was, but
  3989. @@ -5613,6 +5697,7 @@
  3990. host_user = NULL;
  3991. goto handle_return;
  3992. }
  3993. +#endif
  3994. handle_return:
  3995. if (host_user)
  3996. @@ -5752,6 +5837,10 @@
  3997. strip_trailing_newlines (username);
  3998. strip_trailing_newlines (password);
  3999. +#ifdef RSE_PATCH_MAPROOT
  4000. + root_map_it(repository, &repository, 0);
  4001. +#endif
  4002. +
  4003. /* ... and make sure the protocol ends on the right foot. */
  4004. /* See above comment about error handling. */
  4005. getline_safe (&tmp, &tmp_allocated, stdin, PATH_MAX);
  4006. @@ -6575,3 +6664,520 @@
  4007. cvs_output (text, 0);
  4008. }
  4009. }
  4010. +
  4011. +#ifdef RSE_PATCH_PSERVERD
  4012. +
  4013. +/* ========================================================================= */
  4014. +
  4015. +#if !defined(SIGCHLD) && defined(SIGCLD)
  4016. +#define SIGCHLD SIGCLD
  4017. +#endif
  4018. +
  4019. +static void pserver_handshake(void);
  4020. +
  4021. +/*
  4022. + * Main procedure stub. This is called in two contexts: first under "cvs
  4023. + * -H pserverd" where we just display the usage; second inside the CVS
  4024. + * main loop where we have to act as the regular "cvs server".
  4025. + */
  4026. +
  4027. +static const char *const pserverd_usage[] = {
  4028. + "Usage: %s %s [-v] [-d] [-l addr[:port]] [-p pidfile] [-A user] [-R user:repos:chroot]\n",
  4029. + "\t-v\tVerbose mode.\n",
  4030. + "\t-d\tDetach into background and run as a daemon.\n",
  4031. + "\t-l\tListen to a particular address/port.\n",
  4032. + "\t-p\tWrite the daemon's PID to a file.\n",
  4033. + "\t-A\tForce global -l -n -u options for a particular user.\n",
  4034. + "\t-R\tPerform a chroot(2) for a user/repository pair.\n",
  4035. + "(Specify the --help global option for a list of other help options)\n",
  4036. + NULL
  4037. +};
  4038. +
  4039. +int
  4040. +pserverd(
  4041. + int argc,
  4042. + char **argv)
  4043. +{
  4044. + if (argc == -1)
  4045. + usage(pserverd_usage);
  4046. + return server(argc, argv);
  4047. +}
  4048. +
  4049. +/*
  4050. + * The pserver daemon. This listens on a particular TCP/IP socket for
  4051. + * connections. If one occurs, it forks and returns to the caller inside
  4052. + * the child process. The parent process runs forever.
  4053. + */
  4054. +
  4055. +static struct {
  4056. + char *user;
  4057. + char *repos;
  4058. + char *chroot;
  4059. +} pserver_chroot;
  4060. +
  4061. +static char *pserverd_anonymous_user = NULL;
  4062. +static int pserverd_verbose = 0;
  4063. +
  4064. +static int
  4065. +tcp_setinaddr(
  4066. + struct sockaddr_in *addr,
  4067. + const char *host,
  4068. + const char *service,
  4069. + const char *protocol)
  4070. +{
  4071. + struct hostent *hp;
  4072. + char *end;
  4073. + long portno;
  4074. + struct servent *serv;
  4075. +
  4076. + memset(addr, 0, sizeof *addr);
  4077. + addr->sin_family = AF_INET;
  4078. +
  4079. + /* set host part of address */
  4080. + if (host == NULL)
  4081. + addr->sin_addr.s_addr = INADDR_ANY;
  4082. + else {
  4083. + addr->sin_addr.s_addr = inet_addr(host);
  4084. + if (addr->sin_addr.s_addr == (unsigned long) -1) {
  4085. + if ((hp = gethostbyname(host)) == NULL)
  4086. + return -1;
  4087. + memcpy(&addr->sin_addr, hp->h_addr, hp->h_length);
  4088. + addr->sin_family = hp->h_addrtype;
  4089. + }
  4090. + }
  4091. +
  4092. + /* set port part of address */
  4093. + if (service == NULL)
  4094. + addr->sin_port = htons(0);
  4095. + else {
  4096. + portno = strtol(service, &end, 10);
  4097. + if (portno > 0 && portno <= 65535 && end != service && *end == '\0')
  4098. + addr->sin_port = htons(portno);
  4099. + else {
  4100. + if ((serv = getservbyname(service, protocol)) == NULL)
  4101. + return -1;
  4102. + addr->sin_port = serv->s_port;
  4103. + }
  4104. + }
  4105. + return 0;
  4106. +}
  4107. +
  4108. +static int
  4109. +tcp_listen(
  4110. + const char *host,
  4111. + const char *port)
  4112. +{
  4113. + int s;
  4114. + struct protoent *proto;
  4115. + struct sockaddr_in server;
  4116. + int yes = 1;
  4117. +
  4118. + if (tcp_setinaddr(&server, host, port, "tcp") < 0)
  4119. + return -1;
  4120. + if ((proto = getprotobyname("tcp")) == NULL)
  4121. + return -1;
  4122. + if ((s = socket(PF_INET, SOCK_STREAM, proto->p_proto)) < 0)
  4123. + return -1;
  4124. + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes));
  4125. + if (bind(s, (struct sockaddr *)&server, sizeof(server)) < 0) {
  4126. + close(s);
  4127. + return -1;
  4128. + }
  4129. + if (listen(s, 256) < 0) {
  4130. + close(s);
  4131. + return -1;
  4132. + }
  4133. + return s;
  4134. +}
  4135. +
  4136. +static int
  4137. +proc_daemon(
  4138. + int nochdir,
  4139. + int noclose)
  4140. +{
  4141. + int fd;
  4142. + int rc;
  4143. +
  4144. + /*
  4145. + * Ignore tty related signals
  4146. + */
  4147. +#ifdef SIGTTOU
  4148. + signal(SIGTTOU, SIG_IGN);
  4149. +#endif
  4150. +#ifdef SIGTTIN
  4151. + signal(SIGTTIN, SIG_IGN);
  4152. +#endif
  4153. +#ifdef SIGTSTP
  4154. + signal(SIGTSTP, SIG_IGN);
  4155. +#endif
  4156. +
  4157. + /*
  4158. + * fork so the parent can exit, this returns control to the command line
  4159. + * or shell invoking your program. This step is required so that the new
  4160. + * process is guaranteed not to be a process group leader (The next step,
  4161. + * setsid, would fail if you're a process group leader).
  4162. + */
  4163. + rc = fork();
  4164. + switch (rc) {
  4165. + case -1: return -1;
  4166. + case 0: break;
  4167. + default: _exit(0); /* exit original process */
  4168. + }
  4169. +
  4170. + /*
  4171. + * setsid to become a process group and session group leader. Since a
  4172. + * controlling terminal is associated with a session, and this new session
  4173. + * has not yet acquired a controlling terminal our process now has no
  4174. + * controlling terminal, which is a Good Thing for daemons.
  4175. + */
  4176. +#ifdef HAVE_SETSID
  4177. + if (setsid() == -1)
  4178. + return -1;
  4179. +#else
  4180. + if (setpgid(0, getpid()) == -1)
  4181. + return -1;
  4182. +#ifndef _PATH_TTY
  4183. +#define _PATH_TTY "/dev/tty"
  4184. +#endif
  4185. + if ((fd = open(_PATH_TTY, O_RDWR)) == -1)
  4186. + return -1;
  4187. + ioctl(fd, TIOCNOTTY, NULL);
  4188. + close(fd);
  4189. +#endif
  4190. +
  4191. + /*
  4192. + * fork again so the parent, (the session group leader), can exit. This
  4193. + * means that we, as a non-session group leader, can never regain a
  4194. + * controlling terminal.
  4195. + */
  4196. + rc = fork();
  4197. + switch (rc) {
  4198. + case -1: return -1;
  4199. + case 0: break;
  4200. + default: _exit(0); /* exit original process */
  4201. + }
  4202. +
  4203. + /*
  4204. + * chdir("/") to ensure that our process doesn't keep any directory in
  4205. + * use. Failure to do this could make it so that an administrator couldn't
  4206. + * unmount a filesystem, because it was our current directory.
  4207. + * [Equivalently, we could change to any directory containing files
  4208. + * important to the daemon's operation.]
  4209. + */
  4210. + if (!nochdir)
  4211. + chdir("/");
  4212. +
  4213. + /*
  4214. + * give us complete control over the permissions of anything we write. We
  4215. + * don't know what umask we may have inherited. [This step is optional]
  4216. + */
  4217. + umask(0);
  4218. +
  4219. + /*
  4220. + * close fds 0, 1, and 2. This releases the standard in, out, and error we
  4221. + * inherited from our parent process. We have no way of knowing where
  4222. + * these fds might have been redirected to.
  4223. + */
  4224. + if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) {
  4225. + dup2(fd, STDIN_FILENO);
  4226. + dup2(fd, STDOUT_FILENO);
  4227. + dup2(fd, STDERR_FILENO);
  4228. + if (fd > 2)
  4229. + close(fd);
  4230. + }
  4231. + return 0;
  4232. +}
  4233. +
  4234. +static void
  4235. +pserver_daemon_reapchild(
  4236. + int signo)
  4237. +{
  4238. + pid_t child;
  4239. + int status;
  4240. + char buf[128];
  4241. +
  4242. + while ((child = waitpid(-1, &status, WNOHANG)) > (pid_t)0) {
  4243. + if (pserverd_verbose) {
  4244. + sprintf(buf, "cvs pserverd[%ld]: child process (pid %ld): terminated.\n",
  4245. + (long)getpid(), (long)child);
  4246. + write(STDOUT_FILENO, buf, strlen(buf));
  4247. + }
  4248. + }
  4249. + signal(signo, &pserver_daemon_reapchild);
  4250. + return;
  4251. +}
  4252. +
  4253. +int
  4254. +pserver_daemon(
  4255. + int argc,
  4256. + char **argv)
  4257. +{
  4258. + int sd;
  4259. + pid_t child;
  4260. + int option;
  4261. + char *host = NULL;
  4262. + char *port = "2401";
  4263. + char *listen = NULL;
  4264. + struct sockaddr_in them;
  4265. + int detach = 0;
  4266. + char *pidfile = NULL;
  4267. + FILE *fp;
  4268. + char *cp;
  4269. + int len;
  4270. + int ns;
  4271. +
  4272. + /* make sure we are running with root priviledges, because
  4273. + we need it later for chroot, switch_to_user, etc. */
  4274. + if (geteuid() != 0)
  4275. + error(1, 0, "root priviledges required for pserver operation");
  4276. +
  4277. + /* process "cvs pserverd" command options */
  4278. + optind = 0;
  4279. + while ((option = getopt(argc, argv, "vl:dp:A:R:")) != EOF) {
  4280. + switch ((char) option) {
  4281. + case 'v':
  4282. + pserverd_verbose = 1;
  4283. + break;
  4284. + case 'l':
  4285. + listen = xstrdup(optarg);
  4286. + break;
  4287. + case 'd':
  4288. + detach = 1;
  4289. + pserverd_verbose = 0;
  4290. + break;
  4291. + case 'p':
  4292. + pidfile = xstrdup(optarg);
  4293. + break;
  4294. + case 'A':
  4295. + pserverd_anonymous_user = xstrdup(optarg);
  4296. + break;
  4297. + case 'R':
  4298. + cp = xstrdup(optarg);
  4299. + pserver_chroot.user = cp;
  4300. + if ((cp = strchr(cp, ':')) == NULL)
  4301. + error(1, 0, "invalid -R option argument");
  4302. + *cp++ = '\0';
  4303. + pserver_chroot.repos = cp;
  4304. + if ((cp = strchr(cp, ':')) == NULL)
  4305. + error(1, 0, "invalid -R option argument");
  4306. + *cp++ = '\0';
  4307. + pserver_chroot.chroot = cp;
  4308. + break;
  4309. + case '?':
  4310. + default:
  4311. + usage(pserverd_usage);
  4312. + break;
  4313. + }
  4314. + }
  4315. + argc -= optind;
  4316. + argv += optind;
  4317. + if (argc < 0)
  4318. + usage(pserverd_usage);
  4319. +
  4320. + /* optionally go into the background as a real daemon */
  4321. + if (detach)
  4322. + proc_daemon(0, 0);
  4323. +
  4324. + /* optionally write out the pid */
  4325. + if (pidfile != NULL) {
  4326. + if ((fp = fopen(pidfile, "w")) == NULL)
  4327. + error(1, 0, "unable to write pid to file %s: %s",
  4328. + pidfile, strerror(errno));
  4329. + fprintf(fp, "%ld\n", (long)getpid());
  4330. + fclose(fp);
  4331. + }
  4332. +
  4333. + /* listen on the TCP/IP socket */
  4334. + if (listen != NULL) {
  4335. + if ((port = strrchr(listen, ':')) != NULL)
  4336. + *(port++) = '\0';
  4337. + if (strcasecmp(listen, "*") == 0 || strcmp(listen, "0.0.0.0") == 0)
  4338. + host = NULL;
  4339. + else
  4340. + host = listen;
  4341. + }
  4342. + if ((sd = tcp_listen(host, port)) < 0)
  4343. + error(1, 0, "unable to listen (%s:%s): %s",
  4344. + host != NULL ? host : "*", port, strerror(errno));
  4345. +
  4346. + /* make sure we reap the childs */
  4347. + signal(SIGCHLD, &pserver_daemon_reapchild);
  4348. +
  4349. + /* daemon loop */
  4350. + for (;;) {
  4351. + len = sizeof(them);
  4352. + ns = accept(sd, (struct sockaddr *)&them, &len);
  4353. + if (ns < 0) {
  4354. + if (errno == EINTR)
  4355. + continue;
  4356. + error(1, 0, "accept(2) failed: %s", strerror(errno));
  4357. + }
  4358. + switch (child = fork()) {
  4359. + case -1:
  4360. + error(1, 0, "unable to fork(2): %s", strerror(errno));
  4361. + break;
  4362. + case 0:
  4363. + /* child */
  4364. + close(sd);
  4365. + signal(SIGCHLD, SIG_DFL);
  4366. +
  4367. + /* connect stdin/stdout to socket */
  4368. + dup2(ns, STDIN_FILENO);
  4369. + dup2(ns, STDOUT_FILENO);
  4370. +
  4371. + /*
  4372. + * perform "cvs pserver" authentication handshake.
  4373. + */
  4374. + pserver_handshake();
  4375. +
  4376. + /*
  4377. + * just return to caller, i.e., the main() procedure
  4378. + * which in turn will dispatch into "cvs server" code
  4379. + * for us...
  4380. + */
  4381. + return 0;
  4382. + break;
  4383. + default:
  4384. + /* parent */
  4385. + if (pserverd_verbose)
  4386. + fprintf(stderr, "cvs pserverd[%ld]: child process (pid %ld): started.\n",
  4387. + (long)getpid(), (long)child);
  4388. + close(ns);
  4389. + break;
  4390. + }
  4391. + }
  4392. + exit(0);
  4393. + return 0;
  4394. +}
  4395. +
  4396. +static void
  4397. +pserver_handshake(
  4398. + void)
  4399. +{
  4400. + char *tmp = NULL;
  4401. + size_t tmp_allocated = 0;
  4402. + char *repository = NULL;
  4403. + size_t repository_allocated = 0;
  4404. + char *username = NULL;
  4405. + size_t username_allocated = 0;
  4406. + char *password = NULL;
  4407. + size_t password_allocated = 0;
  4408. + char *host_user = NULL;
  4409. + char *descrambled_password;
  4410. + int verify_and_exit = 0;
  4411. + char *chrootdir = NULL;
  4412. + int on;
  4413. +
  4414. +#ifdef SO_KEEPALIVE
  4415. + /* Set SO_KEEPALIVE on the socket, so that we don't hang forever
  4416. + if the client dies while we are waiting for input. */
  4417. + on = 1;
  4418. + (void)setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE,
  4419. + (char *)&on, sizeof(on));
  4420. +#endif
  4421. +
  4422. + /* Make sure the protocol starts off on the right foot... */
  4423. + getline(&tmp, &tmp_allocated, stdin);
  4424. +
  4425. + if (strcmp (tmp, "BEGIN VERIFICATION REQUEST\n") == 0)
  4426. + verify_and_exit = 1;
  4427. + else if (strcmp (tmp, "BEGIN AUTH REQUEST\n") == 0)
  4428. + ;
  4429. + else
  4430. + error (1, 0, "bad auth protocol start: %s", tmp);
  4431. +
  4432. + /* Get the three important pieces of information in order. */
  4433. + getline(&repository, &repository_allocated, stdin);
  4434. + getline(&username, &username_allocated, stdin);
  4435. + getline(&password, &password_allocated, stdin);
  4436. +
  4437. + /* Make them pure. */
  4438. + strip_trailing_newlines(repository);
  4439. + strip_trailing_newlines(username);
  4440. + strip_trailing_newlines(password);
  4441. +
  4442. +#ifdef RSE_PATCH_MAPROOT
  4443. + root_map_it(repository, &repository, 0);
  4444. +#endif
  4445. +
  4446. + /* ... and make sure the protocol ends on the right foot. */
  4447. + getline(&tmp, &tmp_allocated, stdin);
  4448. + if (strcmp (tmp, verify_and_exit ?
  4449. + "END VERIFICATION REQUEST\n" : "END AUTH REQUEST\n") != 0)
  4450. + error (1, 0, "bad auth protocol end: %s", tmp);
  4451. +
  4452. + if (!root_allow_ok(repository))
  4453. + goto i_hate_you;
  4454. + parse_config(repository);
  4455. +
  4456. + /* We need the real cleartext before we hash it. */
  4457. + descrambled_password = descramble(password);
  4458. + host_user = check_password(username, descrambled_password, repository);
  4459. + memset(descrambled_password, 0, strlen(descrambled_password));
  4460. + free(descrambled_password);
  4461. +
  4462. + if (host_user == NULL) {
  4463. + i_hate_you:
  4464. + printf("I HATE YOU\n");
  4465. + fflush(stdout);
  4466. + if (pserverd_verbose)
  4467. + fprintf(stderr, "cvs pserverd[%ld]: status=FAILED user=%s root=%s\n",
  4468. + (long)getpid(), username, repository);
  4469. + error_exit();
  4470. + }
  4471. +
  4472. + /* Don't go any farther if we're just responding to "cvs login". */
  4473. + if (verify_and_exit) {
  4474. + printf("I LOVE YOU\n");
  4475. + fflush(stdout);
  4476. + if (pserverd_verbose)
  4477. + fprintf(stderr, "cvs pserverd[%ld]: status=OK user=%s root=%s (huser=%s)\n",
  4478. + (long)getpid(), username, repository, host_user);
  4479. + exit(0);
  4480. + }
  4481. +
  4482. + /* Set Pserver_Repos so that we can check later that the same
  4483. + repository is sent in later client/server protocol. */
  4484. + Pserver_Repos = xmalloc(strlen(repository)+1);
  4485. + strcpy(Pserver_Repos, repository);
  4486. +
  4487. + /* Optionally perform a chroot */
  4488. + if (pserver_chroot.user != NULL) {
  4489. + if ( strcmp(username, pserver_chroot.user) == 0
  4490. + && ( strcmp(repository, pserver_chroot.repos) == 0
  4491. + || strcmp(pserver_chroot.repos, "*") == 0 )) {
  4492. + chrootdir = pserver_chroot.chroot;
  4493. + if (chdir(chrootdir) == -1)
  4494. + error(1, 0, "failed to chdir(2) to %s: %s", chrootdir, strerror(errno));
  4495. + if (chroot(chrootdir) == -1)
  4496. + error(1, 0, "failed to chroot(2) to %s: %s", chrootdir, strerror(errno));
  4497. + }
  4498. + }
  4499. +
  4500. + /* Additionally switch to read-only mode for anonymous user */
  4501. + if (pserverd_anonymous_user != NULL) {
  4502. + if (strcmp(username, pserverd_anonymous_user) == 0) {
  4503. +#ifdef RSE_PATCH_NOLOCK
  4504. + nolock = 1;
  4505. +#endif
  4506. + logoff = 1;
  4507. + }
  4508. + }
  4509. +
  4510. + /* Switch to run as this user. */
  4511. + switch_to_user(host_user);
  4512. + free(tmp);
  4513. + free(repository);
  4514. + free(username);
  4515. + free(password);
  4516. +
  4517. + printf("I LOVE YOU\n");
  4518. + fflush(stdout);
  4519. + if (pserverd_verbose)
  4520. + fprintf(stderr, "cvs pserverd[%ld]: status=OK user=%s root=%s (huser=%s hroot=%s)\n",
  4521. + (long)getpid(), username, repository, host_user, chrootdir != NULL ? chrootdir : "/");
  4522. + return;
  4523. +}
  4524. +
  4525. +#endif /* RSE_PATCH_PSERVERD */
  4526. +
  4527. Index: src/subr.c
  4528. ===================================================================
  4529. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/subr.c,v
  4530. retrieving revision 1.1.1.6
  4531. diff -u -d -r1.1.1.6 subr.c
  4532. --- src/subr.c 19 Apr 2002 20:39:05 -0000 1.1.1.6
  4533. +++ src/subr.c 28 Dec 2002 10:48:17 -0000
  4534. @@ -336,6 +336,22 @@
  4535. uid_t uid;
  4536. #endif
  4537. +#ifdef RSE_PATCH_CVSUSER
  4538. +#ifndef RSE_PATCH_CVSUSER_CALLER
  4539. +#define RSE_PATCH_CVSUSER_CALLER "cvs"
  4540. +#endif
  4541. + uid = getuid();
  4542. + if ((pw = (struct passwd *)getpwnam(RSE_PATCH_CVSUSER_CALLER)) != NULL) {
  4543. + if (pw->pw_uid == uid) {
  4544. + char *name;
  4545. + if ((name = getenv("CVSUSER")) != NULL) {
  4546. + cache = xstrdup(name);
  4547. + return cache;
  4548. + }
  4549. + }
  4550. + }
  4551. +#endif
  4552. +
  4553. /* If there is a CVS username, return it. */
  4554. #ifdef AUTH_SERVER_SUPPORT
  4555. if (CVS_Username != NULL)
  4556. @@ -763,6 +779,73 @@
  4557. return backup_name;
  4558. }
  4559. +
  4560. +#ifdef RSE_PATCH_HANDLE
  4561. +/* handle: 2000041317203601
  4562. + date1: 2000/04/13 17:20:36
  4563. + date2: 2000/04/13 17:20:37 */
  4564. +int handle2dates(char *handle, time_t *t1, time_t *t2)
  4565. +{
  4566. + int Y,M,D,h,m,s,o;
  4567. + char buf[17];
  4568. + time_t t;
  4569. + struct tm tm;
  4570. + int rev = 0;
  4571. + int i;
  4572. +
  4573. + /* check for correct handle format */
  4574. + if (handle == NULL)
  4575. + return 0;
  4576. + if (handle[0] == '!') {
  4577. + handle++;
  4578. + rev = 1;
  4579. + }
  4580. + if (strlen(handle) != 16)
  4581. + return 0;
  4582. + for (i = 0; i < 16; i++)
  4583. + if (!isdigit(handle[i]))
  4584. + return 0;
  4585. +
  4586. + /* parse out handle parts */
  4587. + strcpy(buf, handle);
  4588. + o = atoi(buf+14);
  4589. + buf[14] = '\0';
  4590. + s = atoi(buf+12);
  4591. + buf[12] = '\0';
  4592. + m = atoi(buf+10);
  4593. + buf[10] = '\0';
  4594. + h = atoi(buf+8);
  4595. + buf[8] = '\0';
  4596. + D = atoi(buf+6);
  4597. + buf[6] = '\0';
  4598. + M = atoi(buf+4);
  4599. + buf[4] = '\0';
  4600. + Y = atoi(buf);
  4601. +
  4602. + /* assemble parts into a time value */
  4603. + memset(&tm, 0, sizeof tm);
  4604. + tm.tm_sec = s;
  4605. + tm.tm_min = m;
  4606. + tm.tm_hour = h;
  4607. + tm.tm_mday = D;
  4608. + tm.tm_mon = M - 1;
  4609. + tm.tm_year = Y - 1900;
  4610. + t = mktime(&tm);
  4611. + if (t == -1)
  4612. + return 0;
  4613. +
  4614. + /* output the first and second time */
  4615. + if (rev) {
  4616. + *t2 = t;
  4617. + *t1 = t + o;
  4618. + }
  4619. + else {
  4620. + *t1 = t;
  4621. + *t2 = t + o;
  4622. + }
  4623. + return 1;
  4624. +}
  4625. +#endif
  4626. /*
  4627. * Copy a string into a buffer escaping any shell metacharacters. The
  4628. Index: src/tag.c
  4629. ===================================================================
  4630. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/tag.c,v
  4631. retrieving revision 1.1.1.7
  4632. diff -u -d -r1.1.1.7 tag.c
  4633. --- src/tag.c 28 Dec 2002 18:01:30 -0000 1.1.1.7
  4634. +++ src/tag.c 28 Dec 2002 20:14:07 -0000
  4635. @@ -1300,7 +1300,11 @@
  4636. /* The tags is valid but not mentioned in val-tags. Add it. */
  4637. datum value;
  4638. +#ifdef RSE_PATCH_NOLOCK
  4639. + if (noexec || nowrite || nolock)
  4640. +#else
  4641. if (noexec || nowrite)
  4642. +#endif
  4643. {
  4644. if (db != NULL)
  4645. dbm_close (db);
  4646. Index: src/update.c
  4647. ===================================================================
  4648. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/update.c,v
  4649. retrieving revision 1.1.1.7
  4650. diff -u -d -r1.1.1.7 update.c
  4651. --- src/update.c 28 Dec 2002 18:01:30 -0000 1.1.1.7
  4652. +++ src/update.c 28 Dec 2002 20:14:07 -0000
  4653. @@ -203,7 +203,11 @@
  4654. break;
  4655. case 'p':
  4656. pipeout = 1;
  4657. +#ifdef RSE_PATCH_NOLOCK
  4658. + nolock = noexec = 1; /* so no locks will be created */
  4659. +#else
  4660. noexec = 1; /* so no locks will be created */
  4661. +#endif
  4662. break;
  4663. case 'j':
  4664. if (join_rev2)
  4665. @@ -1815,6 +1819,17 @@
  4666. patch can't handle that. */
  4667. fail = 1;
  4668. }
  4669. +#ifdef RSE_PATCH_FASTERUPDATE
  4670. + else {
  4671. + /*
  4672. + * Don't send a diff if just sending the entire file
  4673. + * would be smaller...
  4674. + */
  4675. + fseek(e, 0L, SEEK_END);
  4676. + if (file_info->st_size < ftell(e))
  4677. + fail = 1;
  4678. + }
  4679. +#endif
  4680. fclose (e);
  4681. }
  4682. @@ -2581,8 +2596,16 @@
  4683. write_letter (finfo, 'C');
  4684. }
  4685. else
  4686. +#ifdef RSE_PATCH_MERGENOKEYWORD
  4687. + {
  4688. + if (*t_options == '\0')
  4689. + t_options = "-kk"; /* to ignore keyword expansions */
  4690. +#endif
  4691. status = RCS_merge (finfo->rcs, vers->srcfile->path, finfo->file,
  4692. t_options, rev1, rev2);
  4693. +#ifdef RSE_PATCH_MERGENOKEYWORD
  4694. + }
  4695. +#endif
  4696. if (status != 0 && status != 1)
  4697. {
  4698. Index: src/version.c
  4699. ===================================================================
  4700. RCS file: /e/ossp/pkg/tool/cvs/cvs/cvs/src/version.c,v
  4701. retrieving revision 1.1.1.7
  4702. diff -u -d -r1.1.1.7 version.c
  4703. --- src/version.c 29 Apr 2002 04:25:58 -0000 1.1.1.7
  4704. +++ src/version.c 28 Dec 2002 11:09:23 -0000
  4705. @@ -62,6 +62,9 @@
  4706. some idea of how long ago their version of CVS was
  4707. released. */
  4708. (void) fputs (PACKAGE_STRING, stdout);
  4709. +#ifdef RSE_PATCHES
  4710. + (void) fputs (" [RSE]", stdout);
  4711. +#endif
  4712. (void) fputs (config_string, stdout);
  4713. #ifdef CLIENT_SUPPORT