1#!/bin/ch
2/* Ch package installer script in Ch */
3// pkginstall.ch version 1.0.2, April 8, 2005
4// *) If a package already installed, after uninstallation,
5//    install the new package immediately.
6// pkginstall.ch version 1.0.1, April 8, 2005
7// *) fixed installation in a dir with blank space
8// pkginstall.ch version 1.0.1, April 6, 2005
9// *) fixed installation with large number of .chf files in lib
10// pkginstall.ch version 1.0, March 23 2005
11/*
12     By default, pkginstall installs a package in the current
13     directory  into the <CHHOME>/package and copies required header
14     files in package/include into the CHHOME/toolkit/include
15     directory. It has minimized changes.
16
17     If you want to install ch package into your preferred directory,
18     you can specify it in the comand line. During the installation,
19     it will modify _ipath and _ppath in .chrc in Unix or _chrc
20     in Windows in the  user home  directory.  During installation,
21     an installation file is created under the <CHHOME>/package/installed
22     directory with  a list of the installed directories and files.
23
24     This program can also uninstall a Ch Package by removing header
25     files  installed  into  the CHHOME/toolkit/include directory
26     and the package in the CHHOME/package directory based on the
27     corresponding  package   file  in  CHHOME/package/installed
28     directory.
29
30     Usage: pkginstall.ch [-u] [-d directory] PackageName
31       -u             uninstall 'packagename'
32       -d directory   directory to install 'PackageName'
33       Examples:
34         (1) uninstallation:
35               pkginstall.ch -u chpng
36         (2) installation to the default directory:
37               pkginstall.ch chpng
38         (3) installation to your preferred directory:
39               pkginstall.ch -d /your/preferred/directory chpng
40*/
41
42#include <stdio.h>
43#include <string.h>
44#include <unistd.h>
45#include <stdbool.h>
46
47int main(int argc, char **argv) {
48   char usage[] =
49      "Usage: pkginstall.ch [-u] [-d directory] package\n"
50      "       -u             uninstall 'package'\n"
51      "       -d directory   directory to install 'package'\n"
52      "       Examples:\n"
53      "         (1) uninstallation:\n"
54      "               pkginstall.ch -u chpng \n"
55      "         (2) installation to the default directory:\n"
56      "               pkginstall.ch chpng\n"
57      "         (3) installation to your preferred directory:\n"
58      "               pkginstall.ch -d /your/preferred/directory chpng\n";
59   string_t pkgname;             // chpng
60   string_t chhome;              // C:/ch
61   string_t chtoolkit;           // C:/ch/toolkit
62   string_t chtoolkitinc;        // C:/ch/toolkit/include
63   string_t chpackage;           // C:/ch/package
64   string_t chpackagename;       // C:/ch/package/chpng
65   string_t chpackagenameinc;    // C:/ch/package/chpng/include
66   string_t chpackageinstalled;  // C:/ch/package/installed
67   string_t chpackageinstallpkg; // C:/ch/package/installed/chpng
68   string_t installedfiles;      // files listed in $chpackageinstallpkg
69   string_t headerfiles;         // installed header files in $chtoolkitinc
70   int u_option = false;         // -u option
71   int d_option = false;         // -d option
72   char *s, check;
73   string_t cwd = _cwd;
74   string_t token;
75   string_t str_temp;
76   string_t dotchrc;             // .chrc or _chrc
77   string_t str_chrc_file;       // contents of ~/.chrc or ~/_chrc
78   int install_file_ok = 0;
79   int pkg_dir_ok = 0;
80   FILE *fptr_installed;
81   FILE *fptr_chrc;
82
83   argc--; argv++;
84   while(argc>0 && **argv =='-')
85   {
86      for(s = argv[0]+1; *s&&*s!=' '; s++)  /* empty space not valid option */
87      switch(*s)
88      {
89         case 'u':
90            u_option = true;   /* uninstall package */
91            break;
92         case 'd':             /* the directory to install package */
93            d_option = true;
94            argc--; argv++;
95            chpackage = *argv;
96            break;
97         default:
98            fprintf(stderr,"Warning: invalid option %c\n\n", *s);
99            fprintf(stderr,usage);
100            exit(1);
101            break;
102      }
103      argc--; argv++;
104   }
105
106   if(argc==1) {            /* get the package name */
107     if((*argv)[strlen(*argv)-1] == '/') /* change "chpng/" to "chpng" */
108     {
109       fprintf(stderr, "Error: invalid package name '%s'\n\n", *argv);
110       fprintf(stderr,usage);
111       exit(1);
112     }
113     pkgname = *argv;
114   }
115   else {
116      fprintf(stderr,usage);
117      exit(1);
118   }
119
120   /* Get installation directories for Ch package */
121   chhome=getenv("CHHOME");
122   if (chhome==NULL) {
123      printf("Sorry, CHHOME cannot be found\n");
124      printf("Please install Ch first from http://www.softintegration.com\n");
125      exit(0);
126   }
127   chtoolkit = stradd(chhome, "/toolkit");
128   chtoolkitinc = stradd(chhome, "/toolkit/include");
129   if(d_option == false) {
130     chpackage = stradd(chhome, "/package");
131     chpackageinstalled = stradd(chhome, "/package/installed");
132     chpackageinstallpkg = stradd(chhome, "/package/installed/", pkgname);
133   }
134   chpackagename = stradd(chpackage, "/", pkgname);
135   chpackagenameinc = stradd(chpackagename, "/include");
136
137   if(access(chpackage, W_OK))
138   {
139      if(u_option == true) {
140        fprintf(stderr, "You do not have privilege to remove this package.\n");
141        fprintf(stderr, "Please login as 'root' to run this script\n");
142        exit(0);
143      }
144      else if(d_option == true) {
145        fprintf(stderr, "You do not have privilege to install this package in '%s'\n", chpackagename);
146        exit(0);
147      }
148      else {
149        fprintf(stderr, "You do not have privilege to install this package in '%s'\n", chpackagename);
150        fprintf(stderr, "Please login as 'root' to run this script\n");
151        fprintf(stderr, "or provide a directory to install this package.\n\n");
152        fprintf(stderr,usage);
153        exit(0);
154      }
155
156   }
157
158   if(u_option)  /* uninstall package */
159   {
160      // package exists ?
161      if(!access(chpackagename, R_OK))
162        pkg_dir_ok = 1;
163      // installation file exists ?
164      if(!access(chpackageinstallpkg, R_OK))
165        install_file_ok = 1;
166
167      if( pkg_dir_ok && !install_file_ok) {
168         fprintf(stderr, "\nPackage '%s' appears to have been installed\n"
169           "but the Installation information file does not exist.\n"
170           "Would you like to completely remove the directory %s (Y or N)?:" , pkgname, chpackagename);
171         check = getchar();
172         if (!(check=='y' || check == 'Y'))
173         {
174            exit(1);
175         }
176         while(getchar() != '\n');
177         printf("\n");
178         rm -rf $chpackagename
179      }
180      else if(!pkg_dir_ok && !install_file_ok)
181      {
182          fprintf(stderr, "\nPackage '%s' was not installed\n", pkgname);
183          exit(0);
184      }
185      else
186      {
187         if(!pkg_dir_ok)
188         {
189           fprintf(stderr, "\nThe package directory does not exist but an installation"
190		        " file for the\npackage was found.  Removing possible"
191	                " remaining files.\n");
192         }
193         installedfiles = `cat $chpackageinstallpkg`;
194         foreach(token; installedfiles)
195         {
196            rm -rf $token
197         }
198         rm -rf $chpackageinstallpkg
199      }
200      printf("\nPackage '%s' has been uninstalled.\n\n", pkgname);
201      exit(0);
202   }
203   /* end uninstall option */
204
205   if(access(pkgname, R_OK))
206   {
207      fprintf(stderr, "\nPackage '%s' not found in the current diretory.\n\n", pkgname);
208      exit(1);
209   }
210
211   if(!access(chpackageinstallpkg, R_OK))
212   {
213      printf("\nPackage '%s' was already installed.\n"
214             "Uninstall package '%s'(Y or N)?: ", pkgname, pkgname);
215      check = getchar();
216      if( check != 'y' && check != 'Y' )
217         exit(0);
218      while(getchar() != '\n');
219      ./pkginstall.ch -u $pkgname
220      ./pkginstall.ch $pkgname
221      exit(0);
222   }
223
224   if(!access(chpackagename, R_OK))
225   {
226      fprintf(stderr, "\nIt appears that the %s package was installed by manually without running\n"
227                      "pkginstall.ch or the package directory was not completely removed\n"
228		      "during previous uninstallation.\n"
229		      "Overwrite and continue installation (Y or N)?: ", pkgname);
230      check = getchar();
231      if (!(check=='y' || check == 'Y'))
232      {
233         exit(1);
234      }
235      while(getchar() != '\n');
236	  printf("\n");
237   }
238
239   printf("Install package '%s' to %s now, please wait...\n", pkgname, chpackage);
240#ifdef _WIN32_
241      tar cf $(pkgname).tar $(pkgname)
242      cd $chpackage
243      tar xf "$cwd/$(pkgname).tar"
244      cd $cwd
245      rm -f $(pkgname).tar
246#else
247      tar cf - $(pkgname) | (cd $chpackage; tar xf - )
248#endif
249
250   /* install in the default package dir CHHOME/package */
251   if(d_option == false) {
252      if(access(chpackageinstalled, R_OK) )
253      {
254         mkdir $chpackageinstalled
255      }
256      if((fptr_installed = fopen(chpackageinstallpkg, "w")) == NULL)
257      {
258        fprintf(stderr, "\n\nERROR: fopen: cannot open file %s for write.\n\n", chpackageinstallpkg);
259         exit(1);
260      }
261
262      fprintf(fptr_installed, "%s\n", chpackagename);
263      cd $chpackagenameinc
264      headerfiles = `ls`;
265      foreach(token; headerfiles)
266      {
267         cp -rfp $token $chtoolkitinc
268         fprintf(fptr_installed, "%s\n", stradd(chtoolkitinc, "/",token));
269      }
270      fclose( fptr_installed);
271   }
272   else
273   {
274#if defined(_WIN32_)
275      dotchrc = "_chrc";
276#else
277      dotchrc = ".chrc";
278#endif
279      cd ~
280      if(access(dotchrc, F_OK)) {
281           fprintf(stderr, "\nERROR: ~/'%s' does not exist\n"
282	                   "run 'ch -d' to create it.\n");
283           exit(0);
284      }
285      str_chrc_file = `cat $dotchrc`;
286      str_temp = stradd("_ipath=stradd(_ipath,\"",chpackagenameinc, ";\");");
287      foreach(token;str_chrc_file;"\0";" ")
288      {
289        if(!strcmp(token, str_temp))
290        {
291           token = "found";
292           break;
293        }
294      }
295      if(token == NULL)
296      {
297
298        if( (fptr_chrc = fopen(dotchrc, "a")) == NULL)
299        {
300           fprintf(stderr, "\nERROR: fopen: Unable to open ~/%s for append\n", dotchrc);
301        }
302        else
303        {
304           fprintf(fptr_chrc, "%s\n", str_temp);
305           str_temp = stradd("_ppath=stradd(_ppath,\"",chpackage, ";\");");
306           fprintf(fptr_chrc, "%s\n", str_temp);
307           fclose( fptr_chrc);
308        }
309      }
310      cd -
311   }
312
313   printf("Package '%s' has been successfully installed.\n\n", pkgname);
314   if(!access(stradd(chpackagename, "/demos"), R_OK)) {
315     printf("Please try demo programs for this package in \n"
316          "%s\n\n", stradd(chpackagename, "/demos"));
317   }
318   if(!access("postinstall.ch", R_OK))
319   {
320      printf("You must run the post installation program,\n"
321             "   %s\nbefore running any demos.\n\n", "postinstall.ch");
322   }
323
324   return 0;
325}
326