cvs.patches.rse 138 KB

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