changes to correctly use some HP printer inf files
[samba.git] / source / utils / make_printerdef.c
1  /*
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Create printer definition files.
5
6    Copyright (C) Jean-Francois.Micouleau@utc.fr, 10/26/97 - 1998
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24
25 /*
26 #define DEBUGIT
27 */
28
29 char *files_to_copy;
30 char *driverfile, *datafile, *helpfile, *languagemonitor, *datatype;
31 char buffer[50][255];
32 char sbuffer[50][255];
33 char sub_dir[50][2][255];
34
35 void usage(char *name)
36 {
37  fprintf(stderr,"%s: printer.def \"Printer Name\"\n", name);
38 }
39
40 char *myfgets(char *s, int n, FILE *stream)
41 {
42   char *LString1;
43   char *LString2;
44   char *temp;
45   char String[255];
46   char NewString[255];
47   int i;
48
49   fgets(s,n,stream);
50   while (LString1 = strchr(s,'%')) {
51     if (!(LString2 = strchr(LString1+1,'%'))) break;
52     *LString2 = '\0';
53     strcpy(String,LString1+1);
54     i = 0;
55     while(*sbuffer[i]!='\0') {
56       if (strncmp(sbuffer[i],String,strlen(String))==0)
57       {
58         strcpy(String,sbuffer[i]);
59         if (temp = strchr(String,'=')) ++temp;
60         strcpy(String,temp);
61         break;
62       }
63       i++;      
64     }
65     *LString1 = '\0';
66     strcpy(NewString,s);
67     strcat(NewString,String);
68     strcat(NewString,LString2+1);
69     strcpy(s, NewString);
70   }
71   return(s);
72 }
73
74 /*
75    This function split a line in two parts
76    on both side of the equal sign
77    "entry=value"
78 */
79 char *scan(char *chaine,char **entry)
80 {
81   char *value;
82   char *temp;
83   int i=0;
84  
85   *entry=(char *)malloc(255*sizeof(char));
86   value=(char *)malloc(255*sizeof(char));
87   strcpy(*entry,chaine);
88   temp=chaine;
89   while( temp[i]!='=' && temp[i]!='\0') {
90         i++;
91   }
92   (*entry)[i]='\0'; 
93   strcpy(value,temp+i+1);      
94   return (value);
95 }
96
97 void build_subdir()
98 {
99   int i=0;
100   char *entry;
101   char *data;
102  
103   while (*buffer[i]!='\0') { 
104     data=scan(buffer[i],&entry);
105 #ifdef DEBUGIT
106     fprintf(stderr,"\tentry=data %s:%s\n",entry,data);
107 #endif      
108
109     if (strcmp(data,"11")==0) {
110       strcpy(sub_dir[i][0],entry);
111       strcpy(sub_dir[i][1],"");
112     }
113     if (strcmp(data,"23")==0) {
114       strcpy(sub_dir[i][0],entry);
115       strcpy(sub_dir[i][1],"color\\");
116     }
117 #ifdef DEBUGIT
118     fprintf(stderr,"\tsubdir %s:%s\n",sub_dir[i][0],sub_dir[i][1]);
119 #endif      
120     i++;
121   }
122 }
123
124 /*
125    Lockup Strings entry in a file
126    Return all the lines between the entry and the next one or the end of file
127    An entry is something between braces.
128 */
129 void lookup_strings(FILE *fichier)
130 {
131   int found=0,pointeur=0,i=0;
132   char *temp,*temp2;
133   
134   temp=(char *)malloc(255*sizeof(char));
135   temp2=(char *)malloc(255*sizeof(char));
136   
137   *sbuffer[0]='\0';
138   
139   strcpy(temp2,"[Strings]");
140   
141   rewind(fichier);
142 #ifdef DEBUGIT
143   fprintf(stderr,"\tLooking for Strings\n");
144 #endif
145   
146   while (!feof(fichier) && found==0) {
147         *temp='\0';
148         fgets(temp,255,fichier);
149         if (strncmp(temp,temp2,strlen(temp2))==0) found=1;
150   }
151
152
153   while (!feof(fichier) && found==1) {
154         *temp='\0';
155         fgets(temp,255,fichier);
156         if (*temp=='[') {
157                 found=2;
158                 *sbuffer[pointeur]='\0';
159         }
160         else {
161                 strcpy(sbuffer[pointeur],temp);
162                 i=strlen(sbuffer[pointeur])-1;
163                 while (sbuffer[pointeur][i]=='\r' || sbuffer[pointeur][i]=='\n')
164                         sbuffer[pointeur][i--]='\0';
165                 pointeur++;
166         }  
167   }
168 #ifdef DEBUGIT
169   fprintf(stderr,"\t\tFound %d entries\n",pointeur-1);
170 #endif
171 }
172
173
174 /*
175    Lockup an entry in a file
176    Return all the lines between the entry and the next one or the end of file
177    An entry is something between braces.
178 */
179 void lookup_entry(FILE *fichier,char *chaine)
180 {
181   int found=0,pointeur=0,i=0;
182   char *temp,*temp2;
183   
184   temp=(char *)malloc(255*sizeof(char));
185   temp2=(char *)malloc(255*sizeof(char));
186   
187   *buffer[0]='\0';
188   
189   strcpy(temp2,"[");
190   strcat(temp2,chaine);
191   strcat(temp2,"]");
192   
193   rewind(fichier);
194 #ifdef DEBUGIT
195   fprintf(stderr,"\tLooking for %s\n",chaine);
196 #endif
197   
198   while (!feof(fichier) && found==0) {
199         *temp='\0';
200         myfgets(temp,255,fichier);
201         if (strncmp(temp,temp2,strlen(temp2))==0) found=1;
202   }
203
204
205   while (!feof(fichier) && found==1) {
206         *temp='\0';
207         myfgets(temp,255,fichier);
208         if (*temp=='[') {
209                 found=2;
210                 *buffer[pointeur]='\0';
211         }
212         else {
213                 strcpy(buffer[pointeur],temp);
214                 i=strlen(buffer[pointeur])-1;
215                 while (buffer[pointeur][i]=='\r' || buffer[pointeur][i]=='\n')
216                         buffer[pointeur][i--]='\0';
217                 pointeur++;
218         }  
219   }
220 #ifdef DEBUGIT
221   fprintf(stderr,"\t\tFound %d entries\n",pointeur-1);
222 #endif
223 }
224
225 char *find_desc(FILE *fichier,char *text)
226 {
227   char *chaine;
228   char *long_desc;
229   char *short_desc;
230   char *crap = NULL;
231   char *p;
232
233   int found=0;
234
235   chaine=(char *)malloc(255*sizeof(char));
236   long_desc=(char *)malloc(40*sizeof(char));
237   short_desc=(char *)malloc(40*sizeof(char));
238   if (!chaine || !long_desc || !short_desc) {
239     fprintf(stderr,"Unable to malloc memory\n");
240     exit(1);
241   }
242
243   rewind(fichier);
244   while (!feof(fichier) && found==0)
245   {
246     myfgets(chaine,255,fichier);
247
248     long_desc=strtok(chaine,"=");
249     crap=strtok(NULL,",\r");
250
251     p=long_desc;
252     while(*p!='"' && *p!='\0')
253      p++;
254     if (*p=='"' && *(p+1)!='\0') p++;       
255     long_desc=p;
256
257     if (*p!='\0')
258     {
259       p++;
260       while(*p!='\"')
261        p++;
262       *p='\0';
263     }
264     if (!strcmp(text,long_desc)) 
265         found=1;
266   }
267   free(chaine);
268   if (!found || !crap) return(NULL);
269   while(*crap==' ') crap++;
270   strcpy(short_desc,crap);
271   return(short_desc);
272 }
273
274 void scan_copyfiles(FILE *fichier, char *chaine)
275 {
276   char *part;
277   char *mpart;
278   int i;
279   char direc[255];
280 #ifdef DEBUGIT
281   fprintf(stderr,"In scan_copyfiles Lookup up of %s\n",chaine);
282 #endif 
283   fprintf(stderr,"\nCopy the following files to your printer$ share location:\n");
284   part=strtok(chaine,",");
285   do {
286      /* If the entry start with a @ then it's a file to copy
287      else it's an entry refering to files to copy
288      the main difference is when it's an entry
289      you can have a directory to append before the file name
290     */
291     if (*part=='@') {
292       if (strlen(files_to_copy) != 0)
293         strcat(files_to_copy,",");
294       strcat(files_to_copy,&part[1]);
295       fprintf(stderr,"%s\n",&part[1]);
296     } else {
297       lookup_entry(fichier,part);
298       i=0;
299       strcpy(direc,"");
300       while (*sub_dir[i][0]!='\0') {
301 #ifdef DEBUGIT
302         fprintf(stderr,"\tsubdir %s:%s\n",sub_dir[i][0],sub_dir[i][1]);
303 #endif      
304         if (strcmp(sub_dir[i][0],part)==0)
305                 strcpy(direc,sub_dir[i][1]);
306         i++;
307       } 
308       i=0;
309       while (*buffer[i]!='\0') {
310 /*
311  * HP inf files have strange entries that this attempts to address
312  * Entries in the Copy sections normally have only a single file name
313  * on each line. I have seen the following format in various HP inf files:
314  * 
315  * pscript.hlp =  pscript.hl_
316  * hpdcmon.dll,hpdcmon.dl_
317  * ctl3dv2.dll,ctl3dv2.dl_,ctl3dv2.tmp
318  *
319  * In the first 2 cases you want the first file name - in the last case
320  * you only want the last file name (at least that is what a Win95
321  * machine sent). This may still be wrong but at least I get the same list
322  * of files as seen on a printer test page.
323  */
324         part = strchr(buffer[i],'=');
325         if (part) {
326           *part = '\0';
327           while (--part > buffer[i])
328             if ((*part == ' ') || (*part =='\t')) *part = '\0';
329             else break;
330         } else {
331           part = strchr(buffer[i],',');
332           if (part) {
333             if (mpart = strrchr(part+1,',')) {
334                 strcpy(buffer[i],mpart+1);
335             } else
336                 *part = '\0';
337             while (--part > buffer[i])
338               if ((*part == ' ') || (*part =='\t')) *part = '\0';
339               else break;
340           }
341         }
342         if (strlen(files_to_copy) != 0)
343           strcat(files_to_copy,",");
344         strcat(files_to_copy,direc);
345         strcat(files_to_copy,buffer[i]);
346         fprintf(stderr,"%s%s\n",direc,buffer[i]);
347         i++;
348       } 
349     }
350     part=strtok(NULL,",");
351   }
352   while (part!=NULL);
353   fprintf(stderr,"\n");
354 }
355
356
357 void scan_short_desc(FILE *fichier, char *short_desc)
358 {
359   int i=0;
360   char *chaine;
361   char *temp;
362   char *copyfiles=0,*datasection=0;
363  
364   helpfile=0;
365   languagemonitor=0;
366   datatype="RAW";
367   chaine=(char *)malloc(255*sizeof(char));
368   temp=(char *)malloc(255*sizeof(char));
369   
370   driverfile=short_desc;
371   datafile=short_desc;
372
373   lookup_entry(fichier,short_desc);
374
375   while(*buffer[i]!='\0') {
376 #ifdef DEBUGIT
377     fprintf(stderr,"\tLookup up of %s\n",buffer[i]);
378 #endif
379     if (strncasecmp(buffer[i],"CopyFiles",9)==0) 
380         copyfiles=scan(buffer[i],&temp);
381     else if (strncasecmp(buffer[i],"DataSection",11)==0) 
382         datasection=scan(buffer[i],&temp);
383     else if (strncasecmp(buffer[i],"DataFile",8)==0) 
384         datafile=scan(buffer[i],&temp);
385     else if (strncasecmp(buffer[i],"DriverFile",10)==0) 
386         driverfile=scan(buffer[i],&temp);
387     else if (strncasecmp(buffer[i],"HelpFile",8)==0) 
388         helpfile=scan(buffer[i],&temp);
389     else if (strncasecmp(buffer[i],"LanguageMonitor",15)==0) 
390         languagemonitor=scan(buffer[i],&temp);
391     else if (strncasecmp(buffer[i],"DefaultDataType",15)==0) 
392         datatype=scan(buffer[i],&temp);
393     i++;        
394   }
395
396   if (datasection) {
397     lookup_entry(fichier,datasection);
398
399     i = 0;
400     while(*buffer[i]!='\0') {
401 #ifdef DEBUGIT
402       fprintf(stderr,"\tLookup up of %s\n",buffer[i]);
403 #endif
404       if (strncasecmp(buffer[i],"CopyFiles",9)==0) 
405           copyfiles=scan(buffer[i],&temp);
406       else if (strncasecmp(buffer[i],"DataSection",11)==0) 
407           datasection=scan(buffer[i],&temp);
408       else if (strncasecmp(buffer[i],"DataFile",8)==0) 
409           datafile=scan(buffer[i],&temp);
410       else if (strncasecmp(buffer[i],"DriverFile",10)==0) 
411           driverfile=scan(buffer[i],&temp);
412       else if (strncasecmp(buffer[i],"HelpFile",8)==0) 
413           helpfile=scan(buffer[i],&temp);
414       else if (strncasecmp(buffer[i],"LanguageMonitor",15)==0) 
415           languagemonitor=scan(buffer[i],&temp);
416       else if (strncasecmp(buffer[i],"DefaultDataType",15)==0) 
417           datatype=scan(buffer[i],&temp);
418       i++;      
419     }
420   }
421
422   if (languagemonitor) {
423         temp = strtok(languagemonitor,",");
424         if (*temp == '"') ++temp;
425         strcpy(languagemonitor,temp);
426         if (temp = strchr(languagemonitor,'"')) *temp = '\0';
427   }
428
429   if (i) fprintf(stderr,"End of section found\n");
430  
431   fprintf(stderr,"CopyFiles: %s\n",copyfiles);
432   fprintf(stderr,"Datasection: %s\n",datasection);
433   fprintf(stderr,"Datafile: %s\n",datafile);
434   fprintf(stderr,"Driverfile: %s\n",driverfile);
435   fprintf(stderr,"Helpfile: %s\n",helpfile);
436   fprintf(stderr,"LanguageMonitor: %s\n",languagemonitor);
437   if (copyfiles) scan_copyfiles(fichier,copyfiles);
438 }
439
440 int main(int argc, char *argv[])
441 {
442   char *short_desc;
443   FILE *inf_file;
444
445   if (argc!=3)
446   {
447     usage(argv[0]);
448     return(-1);
449   }
450
451   inf_file=fopen(argv[1],"r");  
452   if (!inf_file)
453   {
454     fprintf(stderr,"Description file not found, bye\n");
455     return(-1);
456   }
457
458   lookup_strings(inf_file);
459
460   short_desc=find_desc(inf_file,argv[2]);
461   if (short_desc==NULL)
462   {
463     fprintf(stderr,"Printer not found\n");
464     return(-1);
465   }
466   else fprintf(stderr,"Found:%s\n",short_desc);
467
468   lookup_entry(inf_file,"DestinationDirs");
469   build_subdir();
470
471   files_to_copy=(char *)malloc(2048*sizeof(char));
472   *files_to_copy='\0';
473   scan_short_desc(inf_file,short_desc);
474   fprintf(stdout,"%s:%s:%s:",
475     argv[2],driverfile,datafile);
476   fprintf(stdout,"%s:",
477     helpfile?helpfile:"");
478   fprintf(stdout,"%s:",
479     languagemonitor?languagemonitor:"");
480   fprintf(stdout,"%s:",datatype);
481   fprintf(stdout,"%s\n",files_to_copy);
482   return 0;
483 }
484