2
* main.c: svnpath - Edit system path for Inno Setup Windows installer.
7
* ====================================================================
8
* Copyright (c) 2000-2004 CollabNet. All rights reserved.
10
* This software is licensed as described in the file COPYING, which
11
* you should have received as part of this distribution. The terms
12
* are also available at http://subversion.tigris.org/license-1.html.
13
* If newer versions of this license are posted there, you may use a
14
* newer version instead, at your option.
16
* This software consists of voluntary contributions made by many
17
* individuals. For exact contribution history, see the revision
18
* history and logs, available at http://subversion.tigris.org/.
19
* ====================================================================
21
* Compiling with MinGW (use version 2.x with gcc 3.2 or better):
22
* Make sure that MinGW/bin is in your path and type:
23
* windres.exe -i svnpath.rc -I rc -o svnpath.res -O coff
24
* gcc -s -Os -Wall -mwindows -march=i386 -o svnpath.exe svnpath.res main.c
25
* Compiling with MS Visual C (use VC 5.x.):
26
* Make a new Win32 Console Application project with the name svnpath
27
* and add this file to your project.
28
* NOTE: Do not even think about using something newer than VC 5.x. This is
29
* an installation program and the required runtime files are newer
30
* than some of the targed OS's (Win 2000 and older).
31
* Compiling with the free Borland compiler bcc55:
32
* Make sure that the bcc bin directory is in your path and type:
33
* bcc32.exe -WC -O1 -fp -esvnpath main.c
36
* * Some Win32 API equivalents are used in stead of the standard C functions
37
* in order to reduce executable size (when compiled with VC).
38
* This functions as: lstrcpy, lstrcat.
39
* * Keep away from Cygwin and pre MinGW 2.x. This app must run on all Win32
40
* OS's independed of any extra dll's.
43
/* ==================================================================== */
57
/*** Global variables ***/
58
static char g_AuExBatFile[17] = "C:\\Autoexec.bat";
59
static char g_AuExSvnFile[17] = "C:\\Autoexec.svn";
61
char g_cSvnLineRem1[80]; /* Look at the svn_set_auexlines routine */
62
char g_cSvnLineRem2[80]; /* for setting the values */
63
char g_cSvnLinePath[256]; /* */
66
int svn_add9x (char cPath[255]);
67
int svn_addnt (char cPath[BUFSIZE]);
68
void svn_error_msg(char cMsg[255]);
71
int svn_read_regval (HKEY hKey, char cValue[10], char cKey[BUFSIZE],
72
char *pcPathCur[BUFSIZE], DWORD *lpType);
73
int svn_remove9x (char cPath[255]);
74
int svn_removent (char cPath[255]);
75
int svn_run_cmd (char cAction[10], char cPath[255]);
76
int svn_set_auexlines (char cPath[255]);
77
int svn_svnpath_exists (char cPath[255]);
81
* Initial program flow
84
main (int argc, char *argv[])
86
int counter=0, iCmdArgError=1, iRetVal=1;
91
case 1: /* missing arguments */
92
lstrcpy ( cMsg, "Missing arguments.");
98
if (! strcmp(argv[1], "--help") || ! strcmp(argv[1], "-h"))
100
iRetVal=svn_print_help();
104
case 3: /* add|remove path */
105
if (! strcmp(argv[1], "add") || ! strcmp(argv[1], "remove"))
107
iRetVal=svn_run_cmd(argv[1], argv[2]);
117
/* It's still hope to run a command when another program (IS) has
118
* started svnpath, so we will try to resolve it. */
120
lstrcpy ( cMsg, "Argument Error: Wrong arguments\n\n");
121
lstrcat ( cMsg, "This program received the following arguments:");
123
for (counter=1; counter<argc; counter++)
125
lstrcat ( cMsg, "\n '");
126
lstrcat ( cMsg, argv[counter]);
127
lstrcat ( cMsg, "'");
130
if ((!strcmp(argv[1], "add") || !strcmp(argv[1], "remove")) && (argc > 3))
132
iRetVal=svn_run_cmd(argv[1], argv[2]);
146
* Adding the path to the %PATH% environment in Autoexec.bat for Win9x
149
svn_add9x (char cPath[255])
155
/* Fill up cSvnPath with the svn contents of Autoexec.bat */
156
svn_set_auexlines(cPath);
157
lstrcpy (cSvnCnt, g_cSvnLineRem1);
158
lstrcat (cSvnCnt, g_cSvnLineRem2);
159
lstrcat (cSvnCnt, g_cSvnLinePath);
161
/* Make a backup of Autoexec.bat to Autoexec.svn if it exists, write the
162
* svn stuff to Autoexec.bat */
163
if( _access(g_AuExBatFile, 0 ) != -1)
165
/* The file exists, so we make sure that we have write permission before
167
if((_access(g_AuExBatFile, 2)) == -1)
169
_chmod(g_AuExBatFile, _S_IWRITE);
173
/* Make the backup */
174
CopyFileA(g_AuExBatFile, g_AuExSvnFile, FALSE);
177
/* Write the svn stuff to the file */
178
FH_AUBAT = fopen(g_AuExBatFile, "a+t");
179
fputs(cSvnCnt, FH_AUBAT);
182
/* Turn back to Read only if that was the original state */
185
_chmod(g_AuExBatFile, _S_IREAD);
193
* Adding the path to the %PATH% environment in the registry on Win-NT's
196
svn_addnt (char cPathSvn[255])
199
char cPathTmp[BUFSIZE];
202
char cKey[BUFSIZE], cPathNew[BUFSIZE], cPathCur[BUFSIZE];
203
DWORD dwBufLen, lpType;
204
char *pcPathCur[BUFSIZE];
208
lstrcpy (cPathTmp, cPathSvn);
210
if (svn_svnpath_exists(cPathTmp))
215
lstrcpy(cKey, "SYSTEM\\CurrentControlSet\\");
216
lstrcat(cKey, "Control\\Session Manager\\Environment");
218
/* Get value, value type and current path from HKLM and try to append
219
* the svnpath to it */
220
svn_read_regval (HKEY_LOCAL_MACHINE, "Path", cKey, &*pcPathCur, &lpType);
222
/* Reopen the key for writing */
223
lRet = RegCreateKeyEx(
224
HKEY_LOCAL_MACHINE, cKey, 0, NULL,
225
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
228
/* Add the subversion path to the path */
229
lstrcpy(cPathNew, cPathCur);
230
lstrcat(cPathNew, ";");
231
lstrcat(cPathNew, cPathSvn);
233
lRet = RegSetValueExA(hKey, "Path", 0, lpType,
234
(BYTE*)cPathNew, strlen(cPathNew)+1);
237
/* If it went wrong to do it with HKLM, then try HKCU */
240
strcpy (cPathCur, "");
242
lRet = svn_read_regval(HKEY_CURRENT_USER, "Path",
243
"Environment", &*pcPathCur, &lpType);
245
/* Current Path may be empty */
247
if (strlen(cPathCur))
249
lstrcpy(cPathNew, cPathCur);
250
lstrcat(cPathNew, ";");
253
lpType = REG_EXPAND_SZ;
255
lstrcat(cPathNew, cPathSvn);
257
/* Reopen the key for writing */
258
lRet = RegCreateKeyEx(
259
HKEY_CURRENT_USER, "Environment", 0, NULL,
260
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
263
lRet = RegSetValueExA(hKey, "Path", 0, lpType,
264
(LPBYTE)cPathNew, strlen(cPathNew)+1);
277
/* Tell the system about the new path */
278
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
279
(LPARAM) "Environment", SMTO_ABORTIFHUNG,
285
/*** svn_error_msg ***/
287
* Displays a message box with a error message
290
svn_error_msg(char cMsg[150])
293
long lMsgBoxFlag=MB_YESNO+MB_ICONWARNING+MB_SETFOREGROUND+MB_TOPMOST;
295
lstrcat(cMsg, "\n\nDo you want to read the help for svnpath?");
297
lRet=MessageBox(0, cMsg, "svnpath - Error" , lMsgBoxFlag);
305
/*** svn_os_is_nt ***/
307
* Determing if the OS type is Windows NT or not. Returns 1 if true
312
/* NOTE: Use OSVERSIONINFO and not OSVERSIONINFOEX, older VC's have bogus
317
BOOL bOsVersionInfoEx;
318
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
319
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
321
if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )
323
osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
324
if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )
330
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
338
/*** svn_print_help ***/
340
* Printing out help on the console
345
char cMsgBoxCaption[80];
346
char cMsgBoxMsg[1024];
347
long lMsgBoxFlag=MB_OK+MB_ICONINFORMATION+MB_SETFOREGROUND;
349
lstrcpy(cMsgBoxCaption, "Help for svnpath");
352
lstrcpy(cMsgBoxMsg, "svnpath - Add/remove a path on the system's PATH environment variable\n\n");
354
lstrcat(cMsgBoxMsg, "usage:\tsvnpath add|remove \"Path\"\n");
355
lstrcat(cMsgBoxMsg, "\tsvnpath -h|--help\n\n");
357
lstrcat(cMsgBoxMsg, "Example:\tsvnpath add \"C:\\Path\\to\\svn.exe\"\n\n");
360
lstrcat(cMsgBoxMsg, "Command explanations:\n");
361
lstrcat(cMsgBoxMsg, " add <path>\n");
362
lstrcat(cMsgBoxMsg, " Adding the path to the system's PATH environment variable\n");
363
lstrcat(cMsgBoxMsg, " remove <path>,\n");
364
lstrcat(cMsgBoxMsg, " Removing the path from the system's PATH environment ");
365
lstrcat(cMsgBoxMsg, "variable\n\n");
367
lstrcat(cMsgBoxMsg, " * On the Windows 9x variations, the Autoexec.bat file are ");
368
lstrcat(cMsgBoxMsg, "edited\n");
369
lstrcat(cMsgBoxMsg, " * On the Windows NT variations, the registry are edited. The ");
370
lstrcat(cMsgBoxMsg, "program tries\n");
371
lstrcat(cMsgBoxMsg, " to edit the Environment in HKLM first. If that fails, then ");
372
lstrcat(cMsgBoxMsg, "the Environment\n in HKCU are used.\n\n");
374
lstrcat(cMsgBoxMsg, " -h, --help: Print help (this page)\n\n");
376
lstrcat(cMsgBoxMsg, "Notes:\n");
377
lstrcat(cMsgBoxMsg, " * For playing safe: -Make sure that the given path allways is ");
378
lstrcat(cMsgBoxMsg, "quoted between\n");
379
lstrcat(cMsgBoxMsg, " two \"'s wherewer the path contains spaces or not\n");
381
MessageBox(0,cMsgBoxMsg, cMsgBoxCaption , lMsgBoxFlag);
386
/*** svn_read_regval ***/
388
* Reading a registry value
391
svn_read_regval (HKEY hKey, char cValue[10], char cKey[BUFSIZE],
392
char *pcPathCur[BUFSIZE], DWORD *lpType)
398
/* Get the key value and put in pcPathCur */
399
lRet = RegOpenKeyExA(hKey, cKey,
400
0, KEY_READ, &hKey );
402
lRet = RegQueryValueExA(hKey, cValue, NULL, &*lpType,
403
(LPBYTE) &**pcPathCur, &dwBufLen);
417
/*** svn_remove9x ***/
419
* Removing the path from the %PATH% environment in Autoexec.bat for Win-9x
422
svn_remove9x (char cPath[255])
426
FILE *FH_AUBAT, *FH_AUSVN;
427
char cLineBuffer[255];
428
char cSvnLineBuffer[255];
432
lstrcpy (cPathTmp, cPath);
433
if (! svn_svnpath_exists(cPathTmp))
438
/* Make a backup of Autoexec.bat to Autoexec.svn if it exists, write the
439
* svn stuff to Autoexec.bat */
440
if(_access(g_AuExBatFile, 0) != -1)
442
/* The file exists, so we make sure that we have write permission
443
* before we continue*/
444
if((_access(g_AuExBatFile, 2 )) == -1)
446
_chmod(g_AuExBatFile, _S_IWRITE);
450
/* Make the backup */
451
CopyFileA(g_AuExBatFile, g_AuExSvnFile, FALSE);
454
/* Open Autoexec.svn and parse it line by line. Save the new contents
456
FH_AUSVN=fopen(g_AuExSvnFile, "rt");
457
FH_AUBAT=fopen(g_AuExBatFile, "wt");
459
/* Give cSvnLineBuffer the first line to remove from Autoexec.bat */
460
svn_set_auexlines(cPath);
461
lstrcpy (cSvnLineBuffer, g_cSvnLineRem1);
463
while(fgets(cLineBuffer, 255, FH_AUSVN) != NULL)
465
if (strstr (cLineBuffer, cSvnLineBuffer) == NULL)
467
fputs(cLineBuffer, FH_AUBAT);
475
lstrcpy (cSvnLineBuffer, g_cSvnLineRem2);
478
lstrcpy (cSvnLineBuffer, g_cSvnLinePath);
487
/* Turn back to Read only if that was the original state */
490
_chmod(g_AuExBatFile, _S_IREAD);
496
/*** svn_removent ***/
498
* Removing the path from the %PATH% environment in the registry on Win-NT's
501
svn_removent (char cPathSvn[255])
504
char cPathTmp[BUFSIZE];
507
char cKey[BUFSIZE], cPathNew[BUFSIZE], cPathCur[BUFSIZE];
508
DWORD dwBufLen, lpType;
509
char *pcPathCur[BUFSIZE];
516
lstrcpy (cPathTmp, cPathSvn);
518
if (! svn_svnpath_exists(cPathTmp))
523
lstrcpy(cKey, "SYSTEM\\CurrentControlSet\\");
524
lstrcat(cKey, "Control\\Session Manager\\Environment");
526
/* Get value, value type and current path from HKLM and try to append
527
* the svnpath to it */
528
lRet = svn_read_regval(HKEY_LOCAL_MACHINE, "Path",
529
cKey, &*pcPathCur, &lpType);
531
/* Reopen the key for writing */
532
lRet = RegCreateKeyEx(
533
HKEY_LOCAL_MACHINE, cKey, 0, NULL,
534
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
537
/* Remove the Subversion path from the system path and put the new path
540
pcSubPath = strtok (cPathCur,";");
541
strcpy(cPathNew, "");
543
while (pcSubPath != NULL)
545
if (strcmp(pcSubPath, cPathSvn))
547
if (strlen(cPathNew)==0)
549
lstrcpy(cPathNew, pcSubPath);
553
lstrcat(cPathNew, ";");
554
lstrcat(cPathNew, pcSubPath);
557
pcSubPath = strtok (NULL, ";");
560
lRet = RegSetValueExA(hKey, "Path", 0, lpType,
561
(BYTE*)cPathNew, strlen(cPathNew)+1);
564
/* If it went wrong to do it with HKLM, then try HKCU */
567
strcpy(cPathCur, "");
568
lRet = svn_read_regval(HKEY_CURRENT_USER, "Path", "Environment",
569
&*pcPathCur, &lpType);
571
pcSubPath = strtok (cPathCur,";");
573
strcpy(cPathNew, "");
574
while (pcSubPath != NULL)
576
if (strcmp(pcSubPath, cPathSvn))
578
if (strlen(cPathNew)==0)
580
lstrcpy(cPathNew, pcSubPath);
584
lstrcat(cPathNew, ";");
585
lstrcat(cPathNew, pcSubPath);
589
pcSubPath = strtok (NULL, ";");
592
/* Reopen the key for writing */
593
lRet = RegCreateKeyEx(
594
HKEY_CURRENT_USER, "Environment", 0, NULL,
595
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
598
lRet = RegSetValueExA(hKey, "Path", 0, lpType,
599
(LPBYTE)cPathNew, strlen(cPathNew)+1);
614
/* Tell the system about the new path */
615
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
616
(LPARAM) "Environment", SMTO_ABORTIFHUNG,
623
/*** svn_run_cmd ***/
625
* Running the ordinary command line when adding/removing a path
628
svn_run_cmd (char cAction[10], char cPath[255])
634
if (! strcmp(cAction, "add"))
636
iRetVal=svn_addnt(cPath);
638
else if (! strcmp(cAction, "remove"))
640
iRetVal=svn_removent(cPath);
645
if (! strcmp(cAction, "add"))
647
iRetVal=svn_add9x(cPath);
649
else if (! strcmp(cAction, "remove"))
651
iRetVal=svn_remove9x(cPath);
658
/*** svn_set_auexlines ***/
660
* Filling the g_cSvnLine* variables with the svn contents of Autoexec.bat
663
svn_set_auexlines (char cPath[255])
665
lstrcpy (g_cSvnLineRem1, "REM *** For Subversion: ");
666
lstrcat (g_cSvnLineRem1, "Don't touch this and the two next lines ***\n");
668
lstrcpy (g_cSvnLineRem2, "REM *** They will be removed when Subversion is ");
669
lstrcat (g_cSvnLineRem2, "uninstalled ***\n");
671
lstrcat (g_cSvnLinePath, "PATH=%PATH%;\"");
672
lstrcat (g_cSvnLinePath, cPath);
673
lstrcat (g_cSvnLinePath, "\"\n");
678
/*** svn_svnpath_exists ***/
680
* Checking if the svn path is in the system's PATH. Returns 0 if not and 1 if
684
svn_svnpath_exists (char cPath[255])
691
dwLenPath = GetEnvironmentVariable("PATH", cSysPath, 1024);
693
/* Split %PATH% to it's sub paths and compare each of them with cPath. */
696
pcSubPath = strtok (cSysPath,";");
698
while (pcSubPath != NULL)
700
if (! strcmp(strupr(pcSubPath), strupr(cPath)) &&
701
strlen(pcSubPath) == strlen(cPath))
706
pcSubPath = strtok (NULL, ";");