cvs.patch.rse 137 KB

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