## 7. Annex

## 7.1 Environment variables used by MacCVS/WinCVS

Most the communication of MacCVS & WinCVS with cvs is done thru environment variables.

The cvs documentation will tell you about these variables. We'll refer here only to the most used ones or to the one only used by WinCVS/MacCVS.

The reason you may want to be aware of this variables is because you want to use the AppleEvent capability of MacCVS or the MPW tools.

Mac Note : Some of the variables are noted as "globals" : it means that if you do not define it, the MPW tool or MacCVS by AppleEvent will get these values directly from the MacCVS preferences. So you don't need to define them, unless you want to overide these values.

- CVSROOT : your CVSROOT, something like alexp@cvs.strata3d.com:path/to/repository/.
- CVSREAD : if set to "yes" or "1" or any non-null value, means you want to check-out read-only.
- USER (Mac only) : the user account you use on the remote server.
- LOGNAME : overides the result of getlogin(). Set it on Windows when your cvs account is different from your login account (for example "administrator").
- CVS_GETPASS (MacCVS/WinCVS only) : used by CvsGui to prompt a password for the pserver authentication. You have only to define it the first time you login to the cvs server (see cvs login). After don't define it, that's not safe to define a clear password. cvs stores the password in a scrambled file named ".cvspass". You might prefer to login in MacCVS/WinCVS before so you don't have to use it.
- HOME (global) : used by cvs to get globals settings files like the .cvspass, .cvsrc... You need it most of the time so it's usefull to define it to your preference folder on Mac and somewhere else for Windows. Mac only : the '@@@' trick have been removed and you should give now a regular Mac path instead (e.g. System:System Folder:Preferences:). The default is automatically set to your preference folder.
- IC_ON_TXT (global) (Mac only) : Use Internet Config services also on text files when set to "1".
- ISO8859 (global) : use ISO-Latin-1 encoding on text files when set to "1".
- CVS_PSERVER_PORT (global) : default to null. Overides the default port for pserver authentication (usually 2401).
- CVS_RCMD_PORT (global) : default to null. Overides the default port for rcmd authentication (usually 514).
- CVS_SERVER (global) : default to null. Overides the default cvs server's name (usually "cvs").
- MAC_DEFAULT_RESOURCE_ENCODING (global) : the value can be either "HQX" or "AppleSingle".
- MAC_BINARY_TYPES_PLAIN (global) : the value is a semi-colon separated set of Mac signatures that you want to be turned into plain binary on the server (ex: "MMPr;JPEG"). This option will force to ignore the resource fork.
- MAC_BINARY_TYPES_HQX (global) : the value is a semi-colon separated set of Mac signatures that you want to be turned into hqx format on the server.
- MAC_BINARY_TYPES_SINGLE (global) : the value is a semi-colon separated set of Mac signatures that you want to be turned into AppleSingle format on the server.

## 7.2 A discussion about MacCVS architecture and the CR/LF problem

email of Miro Jurisic to Alexandre Parenteau

I think it's very important that you know what was going on, so I'll write a hopefully clear description here... if you have any questions please ask :)

- 1. How MSL writes to a file: When MSL writes to a disk file, every \r will be replaced with \n, and every \n will be replaced with \r, if the file was _not_ opened in the binary mode. If the file was opened in binary mode, this replacement does not occur. The exact place where this replacement occurs is in __flush_buffer (buffer_io.c). This routine is called from fclose to write the data out before a file is closed.
- 2. How MSL writes to console: When MSL writes to a console, it treats it as an ASCII file. This means that when __flush_buffer is called for the console, \n\r conversion occurs, and then WriteCharsToConsole is written.
- 3. What 'Map newlines to CR' does: If this is turned on in language settings, compilers will switch \n and \r when compiling your code

Now that we got those clearly written, let's see what the cvsLib glue does:

cvsLib has its own WriteCharsToConsole which calls into MacCVS. This is setup when the library is loaded (in function loadCVS). Specifically, cvsLib's WriteCharsToConsole calls MacCVS' consoleout. consoleout does one of two things: if MacCVS is being run via AppleEvents, it writes output to the reply event. Otherwise, if calls fwrite on stdout to write the data to the console.

Okay, so the way that the 3.0b3 code works is like this:

- Case 1: MacCVS writing to the console : MacCVS calls printf (or fprintf/write on stdout/stderr). Since MacCVS is compiled with 'Map newlines to CR' off, there is exactl one conversion going on, and that is MSL converting \r\n when flushing the console buffer. That works fine.
- Case 2: cvsLib writing to an ASCII file (the broken case) : cvsLib calls fwrite/fprintf. Since cvsLib is compiled with 'Map newlines to CR', \r\n conversion occurs _twice_: first, at compile time, becaue of the settings; second, at the time __flush_buffer is called, because we are writing to an ASCII file. This causes files written by cvsLib to have the wrong linebreaks.
- Case 3: cvsLib writing to the console (the tricky case) : cvsLib calls fwrite/fprintf/printf on stdout/stderr. First \n\r conversion occured at compile time. When it is the time to flush the console buffer, __flush_bufer is called. It performs a \n\r conversion and then calls WriteCharsToConsole. This is the glue WriteCharsToConsole, which calls consoleout. consoleout calls fwrite, which eventually calls __flush_buffer again. __flush_buffer performs another conversion, and then calls the real WriteCharsToConsole. Since there were 3 conversions happening, the overall effect is that \n is converted to \r and vice versa.

Hopefully, now you see where the problem is (this is where I was late Monday afternoon).

I decided that it was not necessary to go through the process of loading and unloading cvsLib all the time (I was not aware of the problems that would cause), so I rearranged the libraries between fragments. I fixed the \n\r problem, but I introduced a new problem: cvs was crashing reproducibly the _second_ time a cvs command was invoked. This is where I went to bed on Monday.

On Tuesday, I woke up and started stepping through the code to determine why the garbage collector is blowing up. I traced the problem to some globals being freed twice. What was going on? Since I changed the linkage so that cvsLib was only loaded once, its globals were initialized when MacCVS was started up. The first time cvsLib was called, it allocated space for some strings and set some globals to point to them. Before returning it freed those globals - but it didn't set them to NULL after freeing them. The second time cvsLib was invoked, some of those globals were freed again (because they weren't NULL), which was wrong.

At that point I realized that the library must be loaded and unloaded repeatedly; I also got your email in which you said that GUSI should be loaded and unloaded repeatedly because it contains those static destructors that clean up MacTCP state.

After reading that I stepped away from my computer, went to the drawing board, and concluded that it is impossible to do anything but to have a closer look at the cvsLib glue, and see whether the hidden conversion can be eliminated. This turned out to be far simpler that I could hope for: instead of calling fwrite from consoleout, I called directly WriteCharsToConsole, thereby avoiding the extra conversing that was the problem. Of course, I also had to turn 'Map newline to CR' in the settings, to even everything out. The result is that:

- Case 1: MacCVS writing to the console : Nothing changed
- Case 2: cvsLib writing to an ASCII file (the fixed case) : Since there is only one \r\n conversion going on (in __flush_buffer), the files are written correctly.
- Case 3: cvsLIb writing to console (the less tricky case) : Two conversion were removed: the compile-time conversion, and the hidden conversion in the cvsLib glue. Therefore, nothing changed - the console still works perfectly.

Whew!

Please let me know if you are unclear on this... now I have a good view of the problem and how I fixed it, and some really great insight on how pieces of MacCVS fit together.

...

cheers,

meeroh