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
29char *files_to_copy;
30char *driverfile, *datafile, *helpfile, *languagemonitor, *datatype, *vendorsetup;
31char buffer[50][sizeof(pstring)];
32char sbuffer[50][sizeof(pstring)];
33char sub_dir[50][2][sizeof(pstring)];
34
35static void usage(char *name)
36{
37 fprintf(stderr,"%s: printer.def \"Printer Name\"\n", name);
38}
39
40static char *myfgets(char *s, int n, FILE *stream)
41{
42  char *LString1;
43  char *LString2;
44  char *temp;
45  pstring String;
46  pstring NewString;
47  int i;
48
49  fgets(s,n,stream);
50  while ((LString1 = strchr(s,'%')) != NULL) {
51    if (!(LString2 = strchr(LString1+1,'%'))) break;
52    *LString2 = '\0';
53    pstrcpy(String,LString1+1);
54    i = 0;
55    while(*sbuffer[i]!='\0') {
56      if (strncmp(sbuffer[i],String,strlen(String))==0)
57      {
58	pstrcpy(String,sbuffer[i]);
59	if ((temp = strchr(String,'=')) != NULL) ++temp;
60	pstrcpy(String,temp);
61	break;
62      }
63      i++;
64    }
65    *LString1 = '\0';
66    pstrcpy(NewString,s);
67    pstrcat(NewString,String);
68    pstrcat(NewString,LString2+1);
69    pstrcpy(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*/
79static char *scan(char *chaine,char **entry)
80{
81  char *value;
82  char *temp;
83  int i=0;
84
85  *entry=(char *)malloc(sizeof(pstring));
86  value=(char *)malloc(sizeof(pstring));
87
88  if(*entry == NULL || value == NULL) {
89    fprintf(stderr,"scan: malloc fail !\n");
90    exit(1);
91  }
92
93  pstrcpy(*entry,chaine);
94  temp=chaine;
95  while( temp[i]!='=' && temp[i]!='\0') {
96 	i++;
97  }
98  (*entry)[i]='\0';
99  if (temp[i]!='\0') {
100        i++;
101  }
102  while( temp[i]==' ' && temp[i]!='\0') {
103 	i++;
104  }
105  pstrcpy(value,temp+i);
106  return (value);
107}
108
109static void build_subdir(void)
110{
111  int i=0;
112  int j=0;
113  char *entry;
114  char *data;
115
116  while (*buffer[i]!='\0') {
117    data=scan(buffer[i],&entry);
118#ifdef DEBUGIT
119    fprintf(stderr,"\tentry=data %s:%s\n",entry,data);
120#endif
121    j = strlen(entry);
122    while (j) {
123      if (entry[j-1] != ' ') break;
124      j--;
125    }
126    entry[j] = '\0';
127
128    if (strncmp(data,"11",2)==0) {
129      pstrcpy(sub_dir[i][0],entry);
130      pstrcpy(sub_dir[i][1],"");
131    }
132    if (strncmp(data,"23",2)==0) {
133      pstrcpy(sub_dir[i][0],entry);
134      pstrcpy(sub_dir[i][1],"color\\");
135    }
136#ifdef DEBUGIT
137    fprintf(stderr,"\tsubdir %s:%s\n",sub_dir[i][0],sub_dir[i][1]);
138#endif
139    i++;
140  }
141}
142
143/*
144   Lockup Strings entry in a file
145   Return all the lines between the entry and the next one or the end of file
146   An entry is something between braces.
147*/
148static void lookup_strings(FILE *fichier)
149{
150  int found=0,pointeur=0,i=0;
151  char *temp,*temp2;
152
153  temp=(char *)malloc(sizeof(pstring));
154  temp2=(char *)malloc(sizeof(pstring));
155
156  if(temp == NULL || temp2 == NULL) {
157    fprintf(stderr,"lookup_strings: malloc fail !\n");
158    exit(1);
159  }
160
161  *sbuffer[0]='\0';
162
163  pstrcpy(temp2,"[Strings]");
164
165  rewind(fichier);
166#ifdef DEBUGIT
167  fprintf(stderr,"\tLooking for Strings\n");
168#endif
169
170  while (!feof(fichier) && found==0) {
171  	*temp='\0';
172  	fgets(temp,255,fichier);
173	if (strncmp(temp,temp2,strlen(temp2))==0) found=1;
174  }
175
176
177  while (!feof(fichier) && found==1) {
178  	*temp='\0';
179  	fgets(temp,255,fichier);
180	if (*temp=='[') {
181		found=2;
182		*sbuffer[pointeur]='\0';
183	}
184	else {
185		pstrcpy(sbuffer[pointeur],temp);
186		i=strlen(sbuffer[pointeur])-1;
187		while (sbuffer[pointeur][i]=='\r' || sbuffer[pointeur][i]=='\n')
188			sbuffer[pointeur][i--]='\0';
189		pointeur++;
190	}
191  }
192
193  /* CCMRCF Mod, seg fault or worse if not found */
194  if (pointeur == 0) {
195     fprintf(stderr,"Printer not found\tNo [Strings] block in inf file\n");
196     exit(2);
197  }
198
199#ifdef DEBUGIT
200  fprintf(stderr,"\t\tFound %d entries\n",pointeur-1);
201#endif
202}
203
204
205/*
206   Lockup an entry in a file
207   Return all the lines between the entry and the next one or the end of file
208   An entry is something between braces.
209*/
210static void lookup_entry(FILE *fichier,char *chaine)
211{
212  int found=0,pointeur=0,i=0;
213  char *temp,*temp2;
214
215  temp=(char *)malloc(sizeof(pstring));
216  temp2=(char *)malloc(sizeof(pstring));
217
218  if(temp == NULL || temp2 == NULL) {
219    fprintf(stderr,"lookup_entry: malloc fail !\n");
220    exit(1);
221  }
222
223  *buffer[0]='\0';
224
225  pstrcpy(temp2,"[");
226  pstrcat(temp2,chaine);
227  pstrcat(temp2,"]");
228
229  rewind(fichier);
230#ifdef DEBUGIT
231  fprintf(stderr,"\tLooking for %s\n",chaine);
232#endif
233
234  while (!feof(fichier) && found==0) {
235  	*temp='\0';
236  	myfgets(temp,255,fichier);
237	if (strncmp(temp,temp2,strlen(temp2))==0) found=1;
238  }
239
240
241  while (!feof(fichier) && found==1) {
242  	*temp='\0';
243  	myfgets(temp,255,fichier);
244	if (*temp=='[') {
245		found=2;
246		*buffer[pointeur]='\0';
247	}
248	else {
249		pstrcpy(buffer[pointeur],temp);
250		i=strlen(buffer[pointeur])-1;
251		while (buffer[pointeur][i]=='\r' || buffer[pointeur][i]=='\n')
252			buffer[pointeur][i--]='\0';
253		pointeur++;
254	}
255  }
256#ifdef DEBUGIT
257  fprintf(stderr,"\t\tFound %d entries\n",pointeur-1);
258#endif
259}
260
261static char *find_desc(FILE *fichier,char *text)
262{
263  char *chaine;
264  char *long_desc;
265  char *short_desc;
266  char *crap = NULL;
267  char *p;
268
269  int found=0;
270
271  chaine=(char *)malloc(sizeof(pstring));
272  long_desc=(char *)malloc(sizeof(pstring));
273  short_desc=(char *)malloc(sizeof(pstring));
274  if (!chaine || !long_desc || !short_desc) {
275    fprintf(stderr,"find_desc: Unable to malloc memory\n");
276    exit(1);
277  }
278
279  rewind(fichier);
280  while (!feof(fichier) && found==0)
281  {
282    myfgets(chaine,255,fichier);
283
284    long_desc=strtok(chaine,"=");
285    crap=strtok(NULL,",\r");
286
287    p=long_desc;
288    while(*p!='"' && *p!='\0')
289     p++;
290    if (*p=='"' && *(p+1)!='\0') p++;
291    long_desc=p;
292
293    if (*p!='\0')
294    {
295      p++;
296      while(*p!='\"')
297       p++;
298      *p='\0';
299    }
300    if (!strcmp(text,long_desc))
301	found=1;
302  }
303  free(chaine);
304  if (!found || !crap) return(NULL);
305  while(*crap==' ') crap++;
306  pstrcpy(short_desc,crap);
307  return(short_desc);
308}
309
310static void scan_copyfiles(FILE *fichier, char *chaine)
311{
312  char *part;
313  char *mpart;
314  int i;
315  pstring direc;
316#ifdef DEBUGIT
317  fprintf(stderr,"In scan_copyfiles Lookup up of %s\n",chaine);
318#endif
319  fprintf(stderr,"\nCopy the following files to your printer$ share location:\n");
320  part=strtok(chaine,",");
321  do {
322     /* If the entry start with a @ then it's a file to copy
323     else it's an entry refering to files to copy
324     the main difference is when it's an entry
325     you can have a directory to append before the file name
326    */
327    if (*part=='@') {
328      if (strlen(files_to_copy) != 0)
329        pstrcat(files_to_copy,",");
330      pstrcat(files_to_copy,&part[1]);
331      fprintf(stderr,"%s\n",&part[1]);
332    } else {
333      lookup_entry(fichier,part);
334      i=0;
335      pstrcpy(direc,"");
336      while (*sub_dir[i][0]!='\0') {
337#ifdef DEBUGIT
338 	fprintf(stderr,"\tsubdir %s:%s\n",sub_dir[i][0],sub_dir[i][1]);
339#endif
340      	if (strcmp(sub_dir[i][0],part)==0)
341          pstrcpy(direc,sub_dir[i][1]);
342        i++;
343      }
344      i=0;
345      while (*buffer[i]!='\0') {
346/*
347 * HP inf files have strange entries that this attempts to address
348 * Entries in the Copy sections normally have only a single file name
349 * on each line. I have seen the following format in various HP inf files:
350 *
351 * pscript.hlp =  pscript.hl_
352 * hpdcmon.dll,hpdcmon.dl_
353 * MSVCRT.DLL,MSVCRT.DL_,,32
354 * ctl3dv2.dll,ctl3dv2.dl_,ctl3dv2.tmp
355 *
356 * In the first 2 cases you want the first file name - in the last case
357 * you only want the last file name (at least that is what a Win95
358 * machine sent). In the third case you also want the first file name
359 * (detect by the last component being just a number ?).
360 * This may still be wrong but at least I get the same list
361 * of files as seen on a printer test page.
362 */
363        part = strchr(buffer[i],'=');
364        if (part) {
365          /*
366           * Case (1) eg. pscript.hlp =  pscript.hl_ - chop after the first name.
367           */
368
369          *part = '\0';
370
371          /*
372           * Now move back to the start and print that.
373           */
374
375          while (--part > buffer[i]) {
376            if ((*part == ' ') || (*part =='\t'))
377              *part = '\0';
378            else
379              break;
380          }
381        } else {
382          part = strchr(buffer[i],',');
383          if (part) {
384            /*
385             * Cases (2-4)
386             */
387
388            if ((mpart = strrchr(part+1,','))!=NULL) {
389              /*
390               * Second ',' - case 3 or 4.
391               * Check if the last part is just a number,
392               * if so we need the first part.
393               */
394
395              char *endptr = NULL;
396              BOOL isnumber = False;
397
398              mpart++;
399              (void)strtol(mpart, &endptr, 10);
400
401              isnumber = ((endptr > mpart) && isdigit(*mpart));
402              if(!isnumber)
403                pstrcpy(buffer[i],mpart+1);
404              else
405                *part = '\0';
406            } else {
407              *part = '\0';
408            }
409            while (--part > buffer[i])
410              if ((*part == ' ') || (*part =='\t')) *part = '\0';
411              else break;
412          }
413	    }
414        if (*buffer[i] != ';') {
415          if (strlen(files_to_copy) != 0)
416            pstrcat(files_to_copy,",");
417          pstrcat(files_to_copy,direc);
418          pstrcat(files_to_copy,buffer[i]);
419          fprintf(stderr,"%s%s\n",direc,buffer[i]);
420        }
421        i++;
422      } /* end while */
423    }
424    part=strtok(NULL,",");
425    if (part) {
426      while( *part ==' ' && *part != '\0') {
427        part++;
428      }
429    }
430  } while (part!=NULL);
431  fprintf(stderr,"\n");
432}
433
434
435static void scan_short_desc(FILE *fichier, char *short_desc)
436{
437  int i=0;
438  char *temp;
439  char *copyfiles=0,*datasection=0;
440
441  helpfile=0;
442  languagemonitor=0;
443  vendorsetup=0;
444  datatype="RAW";
445  if((temp=(char *)malloc(sizeof(pstring))) == NULL) {
446    fprintf(stderr, "scan_short_desc: malloc fail !\n");
447    exit(1);
448  }
449
450  driverfile=short_desc;
451  datafile=short_desc;
452
453  lookup_entry(fichier,short_desc);
454
455  while(*buffer[i]!='\0') {
456#ifdef DEBUGIT
457    fprintf(stderr,"\tLookup up of %s\n",buffer[i]);
458#endif
459    if (strncasecmp(buffer[i],"CopyFiles",9)==0)
460	copyfiles=scan(buffer[i],&temp);
461    else if (strncasecmp(buffer[i],"DataSection",11)==0)
462	datasection=scan(buffer[i],&temp);
463    else if (strncasecmp(buffer[i],"DataFile",8)==0)
464	datafile=scan(buffer[i],&temp);
465    else if (strncasecmp(buffer[i],"DriverFile",10)==0)
466	driverfile=scan(buffer[i],&temp);
467    else if (strncasecmp(buffer[i],"HelpFile",8)==0)
468	helpfile=scan(buffer[i],&temp);
469    else if (strncasecmp(buffer[i],"LanguageMonitor",15)==0)
470	languagemonitor=scan(buffer[i],&temp);
471    else if (strncasecmp(buffer[i],"DefaultDataType",15)==0)
472	datatype=scan(buffer[i],&temp);
473    else if (strncasecmp(buffer[i],"VendorSetup",11)==0)
474	vendorsetup=scan(buffer[i],&temp);
475    i++;
476  }
477
478  if (datasection) {
479    lookup_entry(fichier,datasection);
480
481    i = 0;
482    while(*buffer[i]!='\0') {
483#ifdef DEBUGIT
484      fprintf(stderr,"\tLookup up of %s\n",buffer[i]);
485#endif
486      if (strncasecmp(buffer[i],"CopyFiles",9)==0)
487	  copyfiles=scan(buffer[i],&temp);
488      else if (strncasecmp(buffer[i],"DataSection",11)==0)
489	  datasection=scan(buffer[i],&temp);
490      else if (strncasecmp(buffer[i],"DataFile",8)==0)
491	  datafile=scan(buffer[i],&temp);
492      else if (strncasecmp(buffer[i],"DriverFile",10)==0)
493	  driverfile=scan(buffer[i],&temp);
494      else if (strncasecmp(buffer[i],"HelpFile",8)==0)
495	  helpfile=scan(buffer[i],&temp);
496      else if (strncasecmp(buffer[i],"LanguageMonitor",15)==0)
497	  languagemonitor=scan(buffer[i],&temp);
498      else if (strncasecmp(buffer[i],"DefaultDataType",15)==0)
499	  datatype=scan(buffer[i],&temp);
500      else if (strncasecmp(buffer[i],"VendorSetup",11)==0)
501	  vendorsetup=scan(buffer[i],&temp);
502      i++;
503    }
504  }
505
506  if (languagemonitor) {
507	temp = strtok(languagemonitor,",");
508	if (*temp == '"') ++temp;
509	pstrcpy(languagemonitor,temp);
510	if ((temp = strchr(languagemonitor,'"'))!=NULL) *temp = '\0';
511  }
512
513  if (i) fprintf(stderr,"End of section found\n");
514
515  fprintf(stderr,"CopyFiles: %s\n",
516	copyfiles?copyfiles:"(null)");
517  fprintf(stderr,"Datasection: %s\n",
518	datasection?datasection:"(null)");
519  fprintf(stderr,"Datafile: %s\n",
520	datafile?datafile:"(null)");
521  fprintf(stderr,"Driverfile: %s\n",
522	driverfile?driverfile:"(null)");
523  fprintf(stderr,"Helpfile: %s\n",
524	helpfile?helpfile:"(null)");
525  fprintf(stderr,"LanguageMonitor: %s\n",
526	languagemonitor?languagemonitor:"(null)");
527  fprintf(stderr,"VendorSetup: %s\n",
528	vendorsetup?vendorsetup:"(null)");
529  if (copyfiles) scan_copyfiles(fichier,copyfiles);
530}
531
532int main(int argc, char *argv[])
533{
534  char *short_desc;
535  FILE *inf_file;
536
537  if (argc!=3)
538  {
539    usage(argv[0]);
540    return(-1);
541  }
542
543  inf_file=sys_fopen(argv[1],"r");
544  if (!inf_file)
545  {
546    fprintf(stderr,"Description file not found, bye\n");
547    return(-1);
548  }
549
550  lookup_strings(inf_file);
551
552  short_desc=find_desc(inf_file,argv[2]);
553  if (short_desc==NULL)
554  {
555    fprintf(stderr,"Printer not found\n");
556    return(-1);
557  }
558  else fprintf(stderr,"Found:%s\n",short_desc);
559
560  lookup_entry(inf_file,"DestinationDirs");
561  build_subdir();
562
563  if((files_to_copy=(char *)malloc(2048*sizeof(char))) == NULL) {
564    fprintf(stderr, "%s: malloc fail.\n", argv[0] );
565    exit(1);
566  }
567  *files_to_copy='\0';
568  scan_short_desc(inf_file,short_desc);
569  fprintf(stdout,"%s:%s:%s:",
570    argv[2],driverfile,datafile);
571  fprintf(stdout,"%s:",
572    helpfile?helpfile:"");
573  fprintf(stdout,"%s:",
574    languagemonitor?languagemonitor:"");
575  fprintf(stdout,"%s:",datatype);
576  fprintf(stdout,"%s\n",files_to_copy);
577  return 0;
578}
579
580