]> granicus.if.org Git - imagemagick/blob - magick/utility.c
(no commit message)
[imagemagick] / magick / utility.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %             U   U  TTTTT  IIIII  L      IIIII  TTTTT  Y   Y                 %
7 %             U   U    T      I    L        I      T     Y Y                  %
8 %             U   U    T      I    L        I      T      Y                   %
9 %             U   U    T      I    L        I      T      Y                   %
10 %              UUU     T    IIIII  LLLLL  IIIII    T      Y                   %
11 %                                                                             %
12 %                                                                             %
13 %                       MagickCore Utility Methods                            %
14 %                                                                             %
15 %                             Software Design                                 %
16 %                               John Cristy                                   %
17 %                              January 1993                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    http://www.imagemagick.org/script/license.php                            %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 \f
39 /*
40   Include declarations.
41 */
42 #include "magick/studio.h"
43 #include "magick/property.h"
44 #include "magick/blob.h"
45 #include "magick/color.h"
46 #include "magick/exception.h"
47 #include "magick/exception-private.h"
48 #include "magick/geometry.h"
49 #include "magick/list.h"
50 #include "magick/log.h"
51 #include "magick/memory_.h"
52 #include "magick/option.h"
53 #include "magick/policy.h"
54 #include "magick/resource_.h"
55 #include "magick/semaphore.h"
56 #include "magick/signature-private.h"
57 #include "magick/statistic.h"
58 #include "magick/string_.h"
59 #include "magick/token.h"
60 #include "magick/utility.h"
61 #if defined(MAGICKCORE_HAVE_MACH_O_DYLD_H)
62 #include <mach-o/dyld.h>
63 #endif
64 \f
65 /*
66   Static declarations.
67 */
68 static const char
69   Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
70 \f
71 /*
72   Forward declaration.
73 */
74 static int
75   IsPathDirectory(const char *);
76 \f
77 /*
78 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79 %                                                                             %
80 %                                                                             %
81 %                                                                             %
82 %   A c q u i r e U n i q u e F i l e n a m e                                 %
83 %                                                                             %
84 %                                                                             %
85 %                                                                             %
86 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
87 %
88 %  AcquireUniqueFilename() replaces the contents of path by a unique path name.
89 %
90 %  The format of the AcquireUniqueFilename method is:
91 %
92 %      MagickBooleanType AcquireUniqueFilename(char *path)
93 %
94 %  A description of each parameter follows.
95 %
96 %   o  path:  Specifies a pointer to an array of characters.  The unique path
97 %      name is returned in this array.
98 %
99 */
100 MagickExport MagickBooleanType AcquireUniqueFilename(char *path)
101 {
102   int
103     file;
104
105   file=AcquireUniqueFileResource(path);
106   if (file == -1)
107     return(MagickFalse);
108   file=close(file)-1;
109   return(MagickTrue);
110 }
111 \f
112 /*
113 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
114 %                                                                             %
115 %                                                                             %
116 %                                                                             %
117 %   A c q u i r e U n i q u e S ym b o l i c L i n k                          %
118 %                                                                             %
119 %                                                                             %
120 %                                                                             %
121 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
122 %
123 %  AcquireUniqueSymbolicLink() creates a unique symbolic link to the specified
124 %  source path and returns MagickTrue on success otherwise MagickFalse.  If the
125 %  symlink() method fails or is not available, a unique file name is generated
126 %  and the source file copied to it.  When you are finished with the file, use
127 %  RelinquishUniqueFilename() to destroy it.
128 %
129 %  The format of the AcquireUniqueSymbolicLink method is:
130 %
131 %      MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
132 %        char destination)
133 %
134 %  A description of each parameter follows.
135 %
136 %   o  source:  the source path.
137 %
138 %   o  destination:  the destination path.
139 %
140 */
141
142 static inline size_t MagickMin(const size_t x,const size_t y)
143 {
144   if (x < y)
145     return(x);
146   return(y);
147 }
148
149 MagickExport MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
150   char *destination)
151 {
152   int
153     destination_file,
154     source_file;
155
156   size_t
157     length,
158     quantum;
159
160   ssize_t
161     count;
162
163   struct stat
164     attributes;
165
166   unsigned char
167     *buffer;
168
169   assert(source != (const char *) NULL);
170   assert(destination != (char *) NULL);
171 #if defined(MAGICKCORE_HAVE_SYMLINK)
172   (void) AcquireUniqueFilename(destination);
173   (void) RelinquishUniqueFileResource(destination);
174   if (*source == *DirectorySeparator)
175     {
176       if (symlink(source,destination) == 0)
177         return(MagickTrue);
178     }
179   else
180     {
181       char
182         path[MaxTextExtent];
183
184       *path='\0';
185       if (getcwd(path,MaxTextExtent) == (char *) NULL)
186         return(MagickFalse);
187       (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
188       (void) ConcatenateMagickString(path,source,MaxTextExtent);
189       if (symlink(path,destination) == 0)
190         return(MagickTrue);
191     }
192 #endif
193   destination_file=AcquireUniqueFileResource(destination);
194   if (destination_file == -1)
195     return(MagickFalse);
196   source_file=open(source,O_RDONLY | O_BINARY);
197   if (source_file == -1)
198     {
199       (void) close(destination_file);
200       (void) RelinquishUniqueFileResource(destination);
201       return(MagickFalse);
202     }
203   quantum=(size_t) MagickMaxBufferExtent;
204   if ((fstat(source_file,&attributes) == 0) && (attributes.st_size != 0))
205     quantum=MagickMin((size_t) attributes.st_size,MagickMaxBufferExtent);
206   buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
207   if (buffer == (unsigned char *) NULL)
208     {
209       (void) close(source_file);
210       (void) close(destination_file);
211       (void) RelinquishUniqueFileResource(destination);
212       return(MagickFalse);
213     }
214   for (length=0; ; )
215   {
216     count=(ssize_t) read(source_file,buffer,quantum);
217     if (count <= 0)
218       break;
219     length=(size_t) count;
220     count=(ssize_t) write(destination_file,buffer,length);
221     if ((size_t) count != length)
222       {
223         (void) close(destination_file);
224         (void) close(source_file);
225         buffer=(unsigned char *) RelinquishMagickMemory(buffer);
226         (void) RelinquishUniqueFileResource(destination);
227         return(MagickFalse);
228       }
229   }
230   (void) close(destination_file);
231   (void) close(source_file);
232   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
233   return(MagickTrue);
234 }
235 \f
236 /*
237 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238 %                                                                             %
239 %                                                                             %
240 %                                                                             %
241 %  A p p e n d I m a g e F o r m a t                                          %
242 %                                                                             %
243 %                                                                             %
244 %                                                                             %
245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246 %
247 %  AppendImageFormat() appends the image format type to the filename.  If an
248 %  extension to the file already exists, it is first removed.
249 %
250 %  The format of the AppendImageFormat method is:
251 %
252 %      void AppendImageFormat(const char *format,char *filename)
253 %
254 %  A description of each parameter follows.
255 %
256 %   o  format:  Specifies a pointer to an array of characters.  This the
257 %      format of the image.
258 %
259 %   o  filename:  Specifies a pointer to an array of characters.  The unique
260 %      file name is returned in this array.
261 %
262 */
263 MagickExport void AppendImageFormat(const char *format,char *filename)
264 {
265   char
266     root[MaxTextExtent];
267
268   assert(format != (char *) NULL);
269   assert(filename != (char *) NULL);
270   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
271   if ((*format == '\0') || (*filename == '\0'))
272     return;
273   if (LocaleCompare(filename,"-") == 0)
274     {
275       char
276         message[MaxTextExtent];
277
278       (void) FormatMagickString(message,MaxTextExtent,"%s:%s",format,filename);
279       (void) CopyMagickString(filename,message,MaxTextExtent);
280       return;
281     }
282   GetPathComponent(filename,RootPath,root);
283   (void) FormatMagickString(filename,MaxTextExtent,"%s.%s",root,format);
284 }
285 \f
286 /*
287 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288 %                                                                             %
289 %                                                                             %
290 %                                                                             %
291 %   B a s e 6 4 D e c o d e                                                   %
292 %                                                                             %
293 %                                                                             %
294 %                                                                             %
295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296 %
297 %  Base64Decode() decodes Base64-encoded text and returns its binary
298 %  equivalent.  NULL is returned if the text is not valid Base64 data, or a
299 %  memory allocation failure occurs.
300 %
301 %  The format of the Base64Decode method is:
302 %
303 %      unsigned char *Base64Decode(const char *source,length_t *length)
304 %
305 %  A description of each parameter follows:
306 %
307 %    o source:  A pointer to a Base64-encoded string.
308 %
309 %    o length: the number of bytes decoded.
310 %
311 */
312 MagickExport unsigned char *Base64Decode(const char *source,size_t *length)
313 {
314   int
315     state;
316
317   register const char
318     *p,
319     *q;
320
321   register size_t
322     i;
323
324   unsigned char
325     *decode;
326
327   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
328   assert(source != (char *) NULL);
329   assert(length != (size_t *) NULL);
330   *length=0;
331   decode=(unsigned char *) AcquireQuantumMemory(strlen(source)/4+4,
332     3*sizeof(*decode));
333   if (decode == (unsigned char *) NULL)
334     return((unsigned char *) NULL);
335   i=0;
336   state=0;
337   for (p=source; *p != '\0'; p++)
338   {
339     if (isspace((int) ((unsigned char) *p)) != 0)
340       continue;
341     if (*p == '=')
342       break;
343     q=strchr(Base64,*p);
344     if (q == (char *) NULL)
345       {
346         decode=(unsigned char *) RelinquishMagickMemory(decode);
347         return((unsigned char *) NULL);  /* non-Base64 character */
348       }
349     switch (state)
350     {
351       case 0:
352       {
353         decode[i]=(q-Base64) << 2;
354         state++;
355         break;
356       }
357       case 1:
358       {
359         decode[i++]|=(q-Base64) >> 4;
360         decode[i]=((q-Base64) & 0x0f) << 4;
361         state++;
362         break;
363       }
364       case 2:
365       {
366         decode[i++]|=(q-Base64) >> 2;
367         decode[i]=((q-Base64) & 0x03) << 6;
368         state++;
369         break;
370       }
371       case 3:
372       {
373         decode[i++]|=(q-Base64);
374         state=0;
375         break;
376       }
377     }
378   }
379   /*
380     Verify Base-64 string has proper terminal characters.
381   */
382   if (*p != '=')
383     {
384       if (state != 0)
385         {
386           decode=(unsigned char *) RelinquishMagickMemory(decode);
387           return((unsigned char *) NULL);
388         }
389     }
390   else
391     {
392       p++;
393       switch (state)
394       {
395         case 0:
396         case 1:
397         {
398           /*
399             Unrecognized '=' character.
400           */
401           decode=(unsigned char *) RelinquishMagickMemory(decode);
402           return((unsigned char *) NULL);
403         }
404         case 2:
405         {
406           for ( ; *p != '\0'; p++)
407             if (isspace((int) ((unsigned char) *p)) == 0)
408               break;
409           if (*p != '=')
410             {
411               decode=(unsigned char *) RelinquishMagickMemory(decode);
412               return((unsigned char *) NULL);
413             }
414           p++;
415         }
416         case 3:
417         {
418           for ( ; *p != '\0'; p++)
419             if (isspace((int) ((unsigned char) *p)) == 0)
420               {
421                 decode=(unsigned char *) RelinquishMagickMemory(decode);
422                 return((unsigned char *) NULL);
423               }
424           if ((int) decode[i] != 0)
425             {
426               decode=(unsigned char *) RelinquishMagickMemory(decode);
427               return((unsigned char *) NULL);
428             }
429         }
430       }
431     }
432   *length=i;
433   return(decode);
434 }
435 \f
436 /*
437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
438 %                                                                             %
439 %                                                                             %
440 %                                                                             %
441 %   B a s e 6 4 E n c o d e                                                   %
442 %                                                                             %
443 %                                                                             %
444 %                                                                             %
445 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
446 %
447 %  Base64Encode() encodes arbitrary binary data to Base64 encoded format as
448 %  described by the "Base64 Content-Transfer-Encoding" section of RFC 2045 and
449 %  returns the result as a null-terminated ASCII string.  NULL is returned if
450 %  a memory allocation failure occurs.
451 %
452 %  The format of the Base64Encode method is:
453 %
454 %      char *Base64Encode(const unsigned char *blob,const size_t blob_length,
455 %        size_t *encode_length)
456 %
457 %  A description of each parameter follows:
458 %
459 %    o blob:  A pointer to binary data to encode.
460 %
461 %    o blob_length: the number of bytes to encode.
462 %
463 %    o encode_length:  The number of bytes encoded.
464 %
465 */
466 MagickExport char *Base64Encode(const unsigned char *blob,
467   const size_t blob_length,size_t *encode_length)
468 {
469   char
470     *encode;
471
472   register const unsigned char
473     *p;
474
475   register size_t
476     i;
477
478   size_t
479     remainder;
480
481   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
482   assert(blob != (const unsigned char *) NULL);
483   assert(blob_length != 0);
484   assert(encode_length != (size_t *) NULL);
485   *encode_length=0;
486   encode=(char *) AcquireQuantumMemory(blob_length/3+4,4*sizeof(*encode));
487   if (encode == (char *) NULL)
488     return((char *) NULL);
489   i=0;
490   for (p=blob; p < (blob+blob_length-2); p+=3)
491   {
492     encode[i++]=Base64[(int) (*p >> 2)];
493     encode[i++]=Base64[(int) (((*p & 0x03) << 4)+(*(p+1) >> 4))];
494     encode[i++]=Base64[(int) (((*(p+1) & 0x0f) << 2)+(*(p+2) >> 6))];
495     encode[i++]=Base64[(int) (*(p+2) & 0x3f)];
496   }
497   remainder=blob_length % 3;
498   if (remainder != 0)
499     {
500       long
501         j;
502
503       unsigned char
504         code[3];
505
506       code[0]='\0';
507       code[1]='\0';
508       code[2]='\0';
509       for (j=0; j < (long) remainder; j++)
510         code[j]=(*p++);
511       encode[i++]=Base64[(int) (code[0] >> 2)];
512       encode[i++]=Base64[(int) (((code[0] & 0x03) << 4)+(code[1] >> 4))];
513       if (remainder == 1)
514         encode[i++]='=';
515       else
516         encode[i++]=Base64[(int) (((code[1] & 0x0f) << 2)+(code[2] >> 6))];
517       encode[i++]='=';
518     }
519   *encode_length=i;
520   encode[i++]='\0';
521   return(encode);
522 }
523 \f
524 /*
525 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
526 %                                                                             %
527 %                                                                             %
528 %                                                                             %
529 %   C h o p P a t h C o m p o n e n t s                                       %
530 %                                                                             %
531 %                                                                             %
532 %                                                                             %
533 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
534 %
535 %  ChopPathComponents() removes the number of specified file components from a
536 %  path.
537 %
538 %  The format of the ChopPathComponents method is:
539 %
540 %      ChopPathComponents(char *path,unsigned long components)
541 %
542 %  A description of each parameter follows:
543 %
544 %    o path:  The path.
545 %
546 %    o components:  The number of components to chop.
547 %
548 */
549 MagickExport void ChopPathComponents(char *path,const unsigned long components)
550 {
551   register long
552     i;
553
554   for (i=0; i < (long) components; i++)
555     GetPathComponent(path,HeadPath,path);
556 }
557 \f
558 /*
559 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
560 %                                                                             %
561 %                                                                             %
562 %                                                                             %
563 %   E x p a n d F i l e n a m e                                               %
564 %                                                                             %
565 %                                                                             %
566 %                                                                             %
567 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
568 %
569 %  ExpandFilename() expands '~' in a path.
570 %
571 %  The format of the ExpandFilename function is:
572 %
573 %      ExpandFilename(char *path)
574 %
575 %  A description of each parameter follows:
576 %
577 %    o path: Specifies a pointer to a character array that contains the
578 %      path.
579 %
580 */
581 MagickExport void ExpandFilename(char *path)
582 {
583   char
584     expand_path[MaxTextExtent];
585
586   if (path == (char *) NULL)
587     return;
588   if (*path != '~')
589     return;
590   (void) CopyMagickString(expand_path,path,MaxTextExtent);
591   if ((*(path+1) == *DirectorySeparator) || (*(path+1) == '\0'))
592     {
593       char
594         *home;
595
596       /*
597         Substitute ~ with $HOME.
598       */
599       (void) CopyMagickString(expand_path,".",MaxTextExtent);
600       (void) ConcatenateMagickString(expand_path,path+1,MaxTextExtent);
601       home=GetEnvironmentValue("HOME");
602       if (home == (char *) NULL)
603         home=GetEnvironmentValue("USERPROFILE");
604       if (home != (char *) NULL)
605         {
606           (void) CopyMagickString(expand_path,home,MaxTextExtent);
607           (void) ConcatenateMagickString(expand_path,path+1,MaxTextExtent);
608           home=DestroyString(home);
609         }
610     }
611   else
612     {
613 #if defined(MAGICKCORE_POSIX_SUPPORT) && !defined(__OS2__)
614       char
615         username[MaxTextExtent];
616
617       register char
618         *p;
619
620       struct passwd
621         *entry;
622
623       /*
624         Substitute ~ with home directory from password file.
625       */
626       (void) CopyMagickString(username,path+1,MaxTextExtent);
627       p=strchr(username,'/');
628       if (p != (char *) NULL)
629         *p='\0';
630       entry=getpwnam(username);
631       if (entry == (struct passwd *) NULL)
632         return;
633       (void) CopyMagickString(expand_path,entry->pw_dir,MaxTextExtent);
634       if (p != (char *) NULL)
635         {
636           (void) ConcatenateMagickString(expand_path,"/",MaxTextExtent);
637           (void) ConcatenateMagickString(expand_path,p+1,MaxTextExtent);
638         }
639 #endif
640     }
641   (void) CopyMagickString(path,expand_path,MaxTextExtent);
642 }
643 \f
644 /*
645 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
646 %                                                                             %
647 %                                                                             %
648 %                                                                             %
649 %   E x p a n d F i l e n a m e s                                             %
650 %                                                                             %
651 %                                                                             %
652 %                                                                             %
653 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
654 %
655 %  ExpandFilenames() checks each argument of the command line vector and
656 %  expands it if they have a wildcard character.  For example, *.jpg might
657 %  expand to:  bird.jpg rose.jpg tiki.jpg.
658 %
659 %  The format of the ExpandFilenames function is:
660 %
661 %      status=ExpandFilenames(int *number_arguments,char ***arguments)
662 %
663 %  A description of each parameter follows:
664 %
665 %    o number_arguments: Specifies a pointer to an integer describing the
666 %      number of elements in the argument vector.
667 %
668 %    o arguments: Specifies a pointer to a text array containing the command
669 %      line arguments.
670 %
671 */
672 MagickExport MagickBooleanType ExpandFilenames(int *number_arguments,
673   char ***arguments)
674 {
675   char
676     *cwd,
677     home_directory[MaxTextExtent],
678     **vector;
679
680   long
681     count,
682     parameters;
683
684   register long
685     i,
686     j;
687
688   unsigned long
689     number_files;
690
691   /*
692     Allocate argument vector.
693   */
694   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
695   assert(number_arguments != (int *) NULL);
696   assert(arguments != (char ***) NULL);
697   vector=(char **) AcquireQuantumMemory((size_t) (*number_arguments+1),
698     sizeof(*vector));
699   if (vector == (char **) NULL)
700     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
701   /*
702     Expand any wildcard filenames.
703   */
704   *home_directory='\0';
705   cwd=getcwd(home_directory,MaxTextExtent);
706   count=0;
707   for (i=0; i < (long) *number_arguments; i++)
708   {
709     char
710       **filelist,
711       filename[MaxTextExtent],
712       magick[MaxTextExtent],
713       *option,
714       path[MaxTextExtent],
715       subimage[MaxTextExtent];
716
717     MagickBooleanType
718       destroy;
719
720     option=(*arguments)[i];
721     *magick='\0';
722     *path='\0';
723     *filename='\0';
724     *subimage='\0';
725     vector[count++]=ConstantString(option);
726     destroy=MagickTrue;
727     parameters=ParseMagickOption(MagickCommandOptions,MagickFalse,option);
728     if (parameters > 0)
729       {
730         /*
731           Do not expand command option parameters.
732         */
733         for (j=0; j < parameters; j++)
734         {
735           i++;
736           if (i == (long) *number_arguments)
737             break;
738           option=(*arguments)[i];
739           vector[count++]=ConstantString(option);
740         }
741         continue;
742       }
743     if ((*option == '"') || (*option == '\''))
744       continue;
745     GetPathComponent(option,TailPath,filename);
746     GetPathComponent(option,MagickPath,magick);
747     if ((LocaleCompare(magick,"CAPTION") == 0) ||
748         (LocaleCompare(magick,"LABEL") == 0) ||
749         (LocaleCompare(magick,"VID") == 0))
750       continue;
751     if ((IsGlob(filename) == MagickFalse) && (*filename != '@'))
752       continue;
753     if (*filename != '@')
754       {
755         /*
756           Generate file list from wildcard filename (e.g. *.jpg).
757         */
758         GetPathComponent(option,HeadPath,path);
759         GetPathComponent(option,SubimagePath,subimage);
760         ExpandFilename(path);
761         filelist=ListFiles(*path == '\0' ? home_directory : path,filename,
762           &number_files);
763       }
764     else
765       {
766         char
767           *files;
768
769         ExceptionInfo
770           *exception;
771
772         int
773           number_images;
774
775         /*
776           Generate file list from file list (e.g. @filelist.txt).
777         */
778         exception=AcquireExceptionInfo();
779         files=FileToString(filename+1,~0,exception);
780         exception=DestroyExceptionInfo(exception);
781         if (files == (char *) NULL)
782           continue;
783         StripString(files);
784         filelist=StringToArgv(files,&number_images);
785         files=DestroyString(files);
786         number_files=(unsigned long) number_images;
787         if (filelist != (char **) NULL)
788           {
789             number_files--;
790             for (j=0; j < (long) number_files; j++)
791               filelist[j]=filelist[j+1];
792           }
793       }
794     if (filelist == (char **) NULL)
795       continue;
796     for (j=0; j < (long) number_files; j++)
797       if (IsPathDirectory(filelist[j]) <= 0)
798         break;
799     if (j == (long) number_files)
800       {
801         for (j=0; j < (long) number_files; j++)
802           filelist[j]=DestroyString(filelist[j]);
803         filelist=(char **) RelinquishMagickMemory(filelist);
804         continue;
805       }
806     /*
807       Transfer file list to argument vector.
808     */
809     vector=(char **) ResizeQuantumMemory(vector,(size_t) *number_arguments+
810       count+number_files+1,sizeof(*vector));
811     if (vector == (char **) NULL)
812       return(MagickFalse);
813     for (j=0; j < (long) number_files; j++)
814     {
815       (void) CopyMagickString(filename,path,MaxTextExtent);
816       if (*path != '\0')
817         (void) ConcatenateMagickString(filename,DirectorySeparator,
818           MaxTextExtent);
819       (void) ConcatenateMagickString(filename,filelist[j],MaxTextExtent);
820       filelist[j]=DestroyString(filelist[j]);
821       if (strlen(filename) >= MaxTextExtent)
822         ThrowFatalException(OptionFatalError,"FilenameTruncated");
823       if (IsPathDirectory(filename) == 0)
824         {
825           char
826             path[MaxTextExtent];
827
828           *path='\0';
829           if (*magick != '\0')
830             {
831               (void) ConcatenateMagickString(path,magick,MaxTextExtent);
832               (void) ConcatenateMagickString(path,":",MaxTextExtent);
833             }
834           (void) ConcatenateMagickString(path,filename,MaxTextExtent);
835           if (*subimage != '\0')
836             {
837               (void) ConcatenateMagickString(path,"[",MaxTextExtent);
838               (void) ConcatenateMagickString(path,subimage,MaxTextExtent);
839               (void) ConcatenateMagickString(path,"]",MaxTextExtent);
840             }
841           if (strlen(path) >= MaxTextExtent)
842             ThrowFatalException(OptionFatalError,"FilenameTruncated");
843           if (destroy != MagickFalse)
844             {
845               count--;
846               vector[count]=DestroyString(vector[count]);
847               destroy=MagickFalse;
848             }
849           vector[count++]=ConstantString(path);
850         }
851     }
852     filelist=(char **) RelinquishMagickMemory(filelist);
853   }
854   vector[count]=(char *) NULL;
855   if (IsEventLogging() != MagickFalse)
856     {
857       char
858         *command_line;
859
860       command_line=AcquireString(vector[0]);
861       for (i=1; i < count; i++)
862       {
863         (void) ConcatenateString(&command_line," {");
864         (void) ConcatenateString(&command_line,vector[i]);
865         (void) ConcatenateString(&command_line,"}");
866       }
867       (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
868         "Command line: %s",command_line);
869       command_line=DestroyString(command_line);
870     }
871   *number_arguments=(int) count;
872   *arguments=vector;
873   return(MagickTrue);
874 }
875 \f
876 /*
877 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
878 %                                                                             %
879 %                                                                             %
880 %                                                                             %
881 %   G e t E x e c u t i o n P a t h                                           %
882 %                                                                             %
883 %                                                                             %
884 %                                                                             %
885 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
886 %
887 %  GetExecutionPath() returns the pathname of the executable that started
888 %  the process.  On success MagickTrue is returned, otherwise MagickFalse.
889 %
890 %  The format of the GetExecutionPath method is:
891 %
892 %      MagickBooleanType GetExecutionPath(char *path,const size_t extent)
893 %
894 %  A description of each parameter follows:
895 %
896 %    o path: the pathname of the executable that started the process.
897 %
898 %    o extent: the maximum extent of the path.
899 %
900 */
901 MagickExport MagickBooleanType GetExecutionPath(char *path,const size_t extent)
902 {
903   char
904     *cwd;
905
906   *path='\0';
907   cwd=getcwd(path,(unsigned long) extent);
908 #if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK)
909   {
910     char
911       link_path[MaxTextExtent],
912       real_path[PATH_MAX+1];
913
914     ssize_t
915       count;
916
917     (void) FormatMagickString(link_path,MaxTextExtent,"/proc/%ld/exe",
918       (long) getpid());
919     count=readlink(link_path,real_path,PATH_MAX);
920     if (count == -1)
921       {
922         (void) FormatMagickString(link_path,MaxTextExtent,"/proc/%ld/file",
923           (long) getpid());
924         count=readlink(link_path,real_path,PATH_MAX);
925       }
926     if ((count > 0) && (count <= (ssize_t) PATH_MAX))
927       {
928         real_path[count]='\0';
929         (void) CopyMagickString(path,real_path,extent);
930       }
931   }
932 #endif
933 #if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH)
934   {
935     char
936       executable_path[PATH_MAX << 1],
937       real_path[PATH_MAX+1];
938
939     uint32_t
940       length;
941
942     length=sizeof(executable_path);
943     if ((_NSGetExecutablePath(executable_path,&length) == 0) &&
944         (realpath(executable_path,real_path) != (char *) NULL))
945       (void) CopyMagickString(path,real_path,extent);
946   }
947 #endif
948 #if defined(MAGICKCORE_HAVE_GETEXECNAME)
949   {
950     const char
951       *execution_path;
952
953     execution_path=(const char *) getexecname();
954     if (execution_path != (const char *) NULL)
955       {
956         if (*execution_path != *DirectorySeparator)
957           (void) ConcatenateMagickString(path,DirectorySeparator,extent);
958         (void) ConcatenateMagickString(path,execution_path,extent);
959       }
960   }
961 #endif
962 #if defined(__WINDOWS__)
963   NTGetExecutionPath(path,extent);
964 #endif
965   return(IsPathAccessible(path));
966 }
967 \f
968 /*
969 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
970 %                                                                             %
971 %                                                                             %
972 %                                                                             %
973 %   G e t P a t h A t t r i b u t e s                                         %
974 %                                                                             %
975 %                                                                             %
976 %                                                                             %
977 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
978 %
979 %  GetPathAttributes() returns attributes (e.g. size of file) about a path.
980 %
981 %  The path of the GetPathAttributes method is:
982 %
983 %      MagickBooleanType GetPathAttributes(const char *path,void *attributes)
984 %
985 %  A description of each parameter follows.
986 %
987 %   o  path: the file path.
988 %
989 %   o  attributes: the path attributes are returned here.
990 %
991 */
992
993 #if defined(MAGICKCORE_HAVE__WFOPEN)
994 static size_t UTF8ToUTF16(const unsigned char *utf8,wchar_t *utf16)
995 {
996   register const unsigned char
997     *p;
998
999   if (utf16 != (wchar_t *) NULL)
1000     {
1001       register wchar_t
1002         *q;
1003
1004       wchar_t
1005         c;
1006
1007       /*
1008         Convert UTF-8 to UTF-16.
1009       */
1010       q=utf16;
1011       for (p=utf8; *p != '\0'; p++)
1012       {
1013         if ((*p & 0x80) == 0)
1014           *q=(*p);
1015         else
1016           if ((*p & 0xE0) == 0xC0)
1017             {
1018               c=(*p);
1019               *q=(c & 0x1F) << 6;
1020               p++;
1021               if ((*p & 0xC0) != 0x80)
1022                 return(0);
1023               *q|=(*p & 0x3F);
1024             }
1025           else
1026             if ((*p & 0xF0) == 0xE0)
1027               {
1028                 c=(*p);
1029                 *q=c << 12;
1030                 p++;
1031                 if ((*p & 0xC0) != 0x80)
1032                   return(0);
1033                 c=(*p);
1034                 *q|=(c & 0x3F) << 6;
1035                 p++;
1036                 if ((*p & 0xC0) != 0x80)
1037                   return(0);
1038                 *q|=(*p & 0x3F);
1039               }
1040             else
1041               return(0);
1042         q++;
1043       }
1044       *q++='\0';
1045       return(q-utf16);
1046     }
1047   /*
1048     Compute UTF-16 string length.
1049   */
1050   for (p=utf8; *p != '\0'; p++)
1051   {
1052     if ((*p & 0x80) == 0)
1053       ;
1054     else
1055       if ((*p & 0xE0) == 0xC0)
1056         {
1057           p++;
1058           if ((*p & 0xC0) != 0x80)
1059             return(0);
1060         }
1061       else
1062         if ((*p & 0xF0) == 0xE0)
1063           {
1064             p++;
1065             if ((*p & 0xC0) != 0x80)
1066               return(0);
1067             p++;
1068             if ((*p & 0xC0) != 0x80)
1069               return(0);
1070          }
1071        else
1072          return(0);
1073   }
1074   return(p-utf8);
1075 }
1076
1077 static wchar_t *ConvertUTF8ToUTF16(const unsigned char *source)
1078 {
1079   size_t
1080     length;
1081
1082   wchar_t
1083     *utf16;
1084
1085   length=UTF8ToUTF16(source,(wchar_t *) NULL);
1086   if (length == 0)
1087     {
1088       register long
1089         i;
1090
1091       /*
1092         Not UTF-8, just copy.
1093       */
1094       length=strlen(source);
1095       utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
1096       if (utf16 == (wchar_t *) NULL)
1097         return((wchar_t *) NULL);
1098       for (i=0; i <= (long) length; i++)
1099         utf16[i]=source[i];
1100       return(utf16);
1101     }
1102   utf16=(wchar_t *) AcquireQuantumMemory(length+1,sizeof(*utf16));
1103   if (utf16 == (wchar_t *) NULL)
1104     return((wchar_t *) NULL);
1105   length=UTF8ToUTF16(source,utf16);
1106   return(utf16);
1107 }
1108 #endif
1109
1110 MagickExport MagickBooleanType GetPathAttributes(const char *path,
1111   void *attributes)
1112 {
1113   MagickBooleanType
1114     status;
1115
1116   if (path == (const char *) NULL)
1117     {
1118       errno=EINVAL;
1119       return(MagickFalse);
1120     }
1121 #if !defined(MAGICKCORE_HAVE__WSTAT)
1122   status=stat(path,(struct stat *) attributes) == 0 ? MagickTrue : MagickFalse;
1123 #else
1124   {
1125     wchar_t
1126       *unicode_path;
1127
1128     unicode_path=ConvertUTF8ToUTF16(path);
1129     if (unicode_path == (wchar_t *) NULL)
1130       return(MagickFalse);
1131     status=wstat(unicode_path,(struct stat *) attributes) == 0 ? MagickTrue :
1132       MagickFalse;
1133     unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
1134   }
1135 #endif
1136   return(status);
1137 }
1138 \f
1139 /*
1140 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1141 %                                                                             %
1142 %                                                                             %
1143 %                                                                             %
1144 %   G e t P a t h C o m p o n e n t                                           %
1145 %                                                                             %
1146 %                                                                             %
1147 %                                                                             %
1148 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1149 %
1150 %  GetPathComponent() returns the parent directory name, filename, basename, or
1151 %  extension of a file path.
1152 %
1153 %  The format of the GetPathComponent function is:
1154 %
1155 %      GetPathComponent(const char *path,PathType type,char *component)
1156 %
1157 %  A description of each parameter follows:
1158 %
1159 %    o path: Specifies a pointer to a character array that contains the
1160 %      file path.
1161 %
1162 %    o type: Specififies which file path component to return.
1163 %
1164 %    o component: the selected file path component is returned here.
1165 %
1166 */
1167 MagickExport void GetPathComponent(const char *path,PathType type,
1168   char *component)
1169 {
1170   char
1171     magick[MaxTextExtent],
1172     *q,
1173     subimage[MaxTextExtent];
1174
1175   register char
1176     *p;
1177
1178   assert(path != (const char *) NULL);
1179   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
1180   assert(component != (char *) NULL);
1181   if (*path == '\0')
1182     {
1183       *component='\0';
1184       return;
1185     }
1186   (void) CopyMagickString(component,path,MaxTextExtent);
1187   *magick='\0';
1188 #if defined(__OS2__)
1189   if (path[1] != ":")
1190 #endif
1191   for (p=component; *p != '\0'; p++)
1192     if ((*p == ':') && (IsPathDirectory(path) < 0) &&
1193         (IsPathAccessible(path) == MagickFalse))
1194       {
1195         /*
1196           Look for image format specification (e.g. ps3:image).
1197         */
1198         (void) CopyMagickString(magick,component,(size_t) (p-component+1));
1199         if (IsMagickConflict(magick) != MagickFalse)
1200           *magick='\0';
1201         else
1202           for (q=component; *q != '\0'; q++)
1203             *q=(*++p);
1204         break;
1205       }
1206   *subimage='\0';
1207   p=component;
1208   if (*p != '\0')
1209     p=component+strlen(component)-1;
1210   if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
1211       (IsPathAccessible(path) == MagickFalse))
1212     {
1213       /*
1214         Look for scene specification (e.g. img0001.pcd[4]).
1215       */
1216       for (q=p-1; q > component; q--)
1217         if (*q == '[')
1218           break;
1219       if (*q == '[')
1220         {
1221           (void) CopyMagickString(subimage,q+1,MaxTextExtent);
1222           subimage[p-q-1]='\0';
1223           if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) &&
1224               (IsGeometry(subimage) == MagickFalse))
1225             *subimage='\0';
1226           else
1227             *q='\0';
1228         }
1229     }
1230   p=component;
1231   if (*p != '\0')
1232     for (p=component+strlen(component)-1; p > component; p--)
1233       if (IsBasenameSeparator(*p) != MagickFalse)
1234         break;
1235   switch (type)
1236   {
1237     case MagickPath:
1238     {
1239       (void) CopyMagickString(component,magick,MaxTextExtent);
1240       break;
1241     }
1242     case RootPath:
1243     {
1244       for (p=component+(strlen(component)-1); p > component; p--)
1245       {
1246         if (IsBasenameSeparator(*p) != MagickFalse)
1247           break;
1248         if (*p == '.')
1249           break;
1250       }
1251       if (*p == '.')
1252         *p='\0';
1253       break;
1254     }
1255     case HeadPath:
1256     {
1257       *p='\0';
1258       break;
1259     }
1260     case TailPath:
1261     {
1262       if (IsBasenameSeparator(*p) != MagickFalse)
1263         (void) CopyMagickMemory((unsigned char *) component,
1264           (const unsigned char *) (p+1),strlen(p+1)+1);
1265       break;
1266     }
1267     case BasePath:
1268     {
1269       if (IsBasenameSeparator(*p) != MagickFalse)
1270         (void) CopyMagickString(component,p+1,MaxTextExtent);
1271       for (p=component+(strlen(component)-1); p > component; p--)
1272         if (*p == '.')
1273           {
1274             *p='\0';
1275             break;
1276           }
1277       break;
1278     }
1279     case ExtensionPath:
1280     {
1281       if (IsBasenameSeparator(*p) != MagickFalse)
1282         (void) CopyMagickString(component,p+1,MaxTextExtent);
1283       p=component;
1284       if (*p != '\0')
1285         for (p=component+strlen(component)-1; p > component; p--)
1286           if (*p == '.')
1287             break;
1288       *component='\0';
1289       if (*p == '.')
1290         (void) CopyMagickString(component,p+1,MaxTextExtent);
1291       break;
1292     }
1293     case SubimagePath:
1294     {
1295       (void) CopyMagickString(component,subimage,MaxTextExtent);
1296       break;
1297     }
1298     case CanonicalPath:
1299     case UndefinedPath:
1300       break;
1301   }
1302 }
1303 \f
1304 /*
1305 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1306 %                                                                             %
1307 %                                                                             %
1308 %                                                                             %
1309 %  G e t P a t h C o m p o n e n t s                                          %
1310 %                                                                             %
1311 %                                                                             %
1312 %                                                                             %
1313 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1314 %
1315 %  GetPathComponents() returns a list of path components.
1316 %
1317 %  The format of the GetPathComponents method is:
1318 %
1319 %      char **GetPathComponents(const char *path,
1320 %        unsigned long *number_componenets)
1321 %
1322 %  A description of each parameter follows:
1323 %
1324 %    o path:  Specifies the string to segment into a list.
1325 %
1326 %    o number_components:  return the number of components in the list
1327 %
1328 */
1329 MagickExport char **GetPathComponents(const char *path,
1330   unsigned long *number_components)
1331 {
1332   char
1333     **components;
1334
1335   register const char
1336     *p,
1337     *q;
1338
1339   register long
1340     i;
1341
1342   if (path == (char *) NULL)
1343     return((char **) NULL);
1344   *number_components=1;
1345   for (p=path; *p != '\0'; p++)
1346     if (IsBasenameSeparator(*p))
1347       (*number_components)++;
1348   components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
1349     sizeof(*components));
1350   if (components == (char **) NULL)
1351     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1352   p=path;
1353   for (i=0; i < (long) *number_components; i++)
1354   {
1355     for (q=p; *q != '\0'; q++)
1356       if (IsBasenameSeparator(*q))
1357         break;
1358     components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
1359       sizeof(*components));
1360     if (components[i] == (char *) NULL)
1361       ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1362     (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
1363     p=q+1;
1364   }
1365   components[i]=(char *) NULL;
1366   return(components);
1367 }
1368 \f
1369 /*
1370 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1371 %                                                                             %
1372 %                                                                             %
1373 %                                                                             %
1374 %  I s P a t h A c c e s s i b l e                                            %
1375 %                                                                             %
1376 %                                                                             %
1377 %                                                                             %
1378 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1379 %
1380 %  IsPathAccessible() returns MagickTrue if the file as defined by the path is
1381 %  accessible.
1382 %
1383 %  The format of the IsPathAccessible method is:
1384 %
1385 %      MagickBooleanType IsPathAccessible(const char *filename)
1386 %
1387 %  A description of each parameter follows.
1388 %
1389 %    o path:  Specifies a path to a file.
1390 %
1391 */
1392 MagickExport MagickBooleanType IsPathAccessible(const char *path)
1393 {
1394   MagickBooleanType
1395     status;
1396
1397   struct stat
1398     attributes;
1399
1400   if ((path == (const char *) NULL) || (*path == '\0'))
1401     return(MagickFalse);
1402   status=GetPathAttributes(path,&attributes);
1403   if (status == MagickFalse)
1404     return(status);
1405   if (S_ISREG(attributes.st_mode) == 0)
1406     return(MagickFalse);
1407   if (access(path,F_OK) != 0)
1408     return(MagickFalse);
1409   return(MagickTrue);
1410 }
1411 \f
1412 /*
1413 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1414 %                                                                             %
1415 %                                                                             %
1416 %                                                                             %
1417 +  I s P a t h D i r e c t o r y                                              %
1418 %                                                                             %
1419 %                                                                             %
1420 %                                                                             %
1421 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1422 %
1423 %  IsPathDirectory() returns -1 if the directory does not exist,  1 is returned
1424 %  if the path represents a directory otherwise 0.
1425 %
1426 %  The format of the IsPathDirectory method is:
1427 %
1428 %      int IsPathDirectory(const char *path)
1429 %
1430 %  A description of each parameter follows.
1431 %
1432 %   o  path:  The directory path.
1433 %
1434 */
1435 static int IsPathDirectory(const char *path)
1436 {
1437   MagickBooleanType
1438     status;
1439
1440   struct stat
1441     attributes;
1442
1443   if ((path == (const char *) NULL) || (*path == '\0'))
1444     return(MagickFalse);
1445   status=GetPathAttributes(path,&attributes);
1446   if (status == MagickFalse)
1447     return(-1);
1448   if (S_ISDIR(attributes.st_mode) == 0)
1449     return(0);
1450   return(1);
1451 }
1452 \f
1453 /*
1454 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1455 %                                                                             %
1456 %                                                                             %
1457 %                                                                             %
1458 %   I s M a g i c k T r u e                                                   %
1459 %                                                                             %
1460 %                                                                             %
1461 %                                                                             %
1462 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1463 %
1464 %  IsMagickTrue() returns MagickTrue if the value is "true", "on", "yes" or
1465 %  "1".
1466 %
1467 %  The format of the IsMagickTrue method is:
1468 %
1469 %      MagickBooleanType IsMagickTrue(const char *value)
1470 %
1471 %  A description of each parameter follows:
1472 %
1473 %    o option: either MagickTrue or MagickFalse depending on the value
1474 %      parameter.
1475 %
1476 %    o value: Specifies a pointer to a character array.
1477 %
1478 */
1479 MagickExport MagickBooleanType IsMagickTrue(const char *value)
1480 {
1481   if (value == (const char *) NULL)
1482     return(MagickFalse);
1483   if (LocaleCompare(value,"true") == 0)
1484     return(MagickTrue);
1485   if (LocaleCompare(value,"on") == 0)
1486     return(MagickTrue);
1487   if (LocaleCompare(value,"yes") == 0)
1488     return(MagickTrue);
1489   if (LocaleCompare(value,"1") == 0)
1490     return(MagickTrue);
1491   return(MagickFalse);
1492 }
1493 \f
1494 /*
1495 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1496 %                                                                             %
1497 %                                                                             %
1498 %                                                                             %
1499 %   L i s t F i l e s                                                         %
1500 %                                                                             %
1501 %                                                                             %
1502 %                                                                             %
1503 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1504 %
1505 %  ListFiles() reads the directory specified and returns a list of filenames
1506 %  contained in the directory sorted in ascending alphabetic order.
1507 %
1508 %  The format of the ListFiles function is:
1509 %
1510 %      char **ListFiles(const char *directory,const char *pattern,
1511 %        long *number_entries)
1512 %
1513 %  A description of each parameter follows:
1514 %
1515 %    o filelist: Method ListFiles returns a list of filenames contained
1516 %      in the directory.  If the directory specified cannot be read or it is
1517 %      a file a NULL list is returned.
1518 %
1519 %    o directory: Specifies a pointer to a text string containing a directory
1520 %      name.
1521 %
1522 %    o pattern: Specifies a pointer to a text string containing a pattern.
1523 %
1524 %    o number_entries:  This integer returns the number of filenames in the
1525 %      list.
1526 %
1527 */
1528
1529 #if defined(__cplusplus) || defined(c_plusplus)
1530 extern "C" {
1531 #endif
1532
1533 static int FileCompare(const void *x,const void *y)
1534 {
1535   register const char
1536     **p,
1537     **q;
1538
1539   p=(const char **) x;
1540   q=(const char **) y;
1541   return(LocaleCompare(*p,*q));
1542 }
1543
1544 #if defined(__cplusplus) || defined(c_plusplus)
1545 }
1546 #endif
1547
1548 static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
1549   struct dirent **result)
1550 {
1551 #if defined(MAGICKCORE_HAVE_READDIR_R)
1552   return(readdir_r(directory,entry,result));
1553 #else
1554   (void) entry;
1555   errno=0;
1556   *result=readdir(directory);
1557   return(errno);
1558 #endif
1559 }
1560
1561 MagickExport char **ListFiles(const char *directory,const char *pattern,
1562   unsigned long *number_entries)
1563 {
1564   char
1565     **filelist;
1566
1567   DIR
1568     *current_directory;
1569
1570   struct dirent
1571     *buffer,
1572     *entry;
1573
1574   unsigned long
1575     max_entries;
1576
1577   /*
1578     Open directory.
1579   */
1580   assert(directory != (const char *) NULL);
1581   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
1582   assert(pattern != (const char *) NULL);
1583   assert(number_entries != (unsigned long *) NULL);
1584   *number_entries=0;
1585   current_directory=opendir(directory);
1586   if (current_directory == (DIR *) NULL)
1587     return((char **) NULL);
1588   /*
1589     Allocate filelist.
1590   */
1591   max_entries=2048;
1592   filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
1593     sizeof(*filelist));
1594   if (filelist == (char **) NULL)
1595     {
1596       (void) closedir(current_directory);
1597       return((char **) NULL);
1598     }
1599   /*
1600     Save the current and change to the new directory.
1601   */
1602   buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+FILENAME_MAX+1);
1603   if (buffer == (struct dirent *) NULL)
1604     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1605   while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
1606          (entry != (struct dirent *) NULL))
1607   {
1608     if (*entry->d_name == '.')
1609       continue;
1610     if ((IsPathDirectory(entry->d_name) > 0) ||
1611 #if defined(__WINDOWS__)
1612         (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
1613 #else
1614         (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
1615 #endif
1616       {
1617         if (*number_entries >= max_entries)
1618           {
1619             /*
1620               Extend the file list.
1621             */
1622             max_entries<<=1;
1623             filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
1624               max_entries,sizeof(*filelist));
1625             if (filelist == (char **) NULL)
1626               break;
1627           }
1628 #if defined(vms)
1629         {
1630           register char
1631             *p;
1632
1633           p=strchr(entry->d_name,';');
1634           if (p)
1635             *p='\0';
1636           if (*number_entries > 0)
1637             if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
1638               continue;
1639         }
1640 #endif
1641         filelist[*number_entries]=(char *) AcquireString(entry->d_name);
1642         if (IsPathDirectory(entry->d_name) > 0)
1643           (void) ConcatenateMagickString(filelist[*number_entries],
1644             DirectorySeparator,MaxTextExtent);
1645         (*number_entries)++;
1646       }
1647   }
1648   buffer=(struct dirent *) RelinquishMagickMemory(buffer);
1649   (void) closedir(current_directory);
1650   if (filelist == (char **) NULL)
1651     return((char **) NULL);
1652   /*
1653     Sort filelist in ascending order.
1654   */
1655   qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
1656     FileCompare);
1657   return(filelist);
1658 }
1659 \f
1660 /*
1661 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1662 %                                                                             %
1663 %                                                                             %
1664 %                                                                             %
1665 %  M u l t i l i n e C e n s u s                                              %
1666 %                                                                             %
1667 %                                                                             %
1668 %                                                                             %
1669 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1670 %
1671 %  MultilineCensus() returns the number of lines within a label.  A line is
1672 %  represented by a \n character.
1673 %
1674 %  The format of the MultilineCenus method is:
1675 %
1676 %      unsigned long MultilineCensus(const char *label)
1677 %
1678 %  A description of each parameter follows.
1679 %
1680 %   o  label:  This character string is the label.
1681 %
1682 %
1683 */
1684 MagickExport unsigned long MultilineCensus(const char *label)
1685 {
1686   unsigned long
1687     number_lines;
1688
1689   /*
1690     Determine the number of lines within this label.
1691   */
1692   if (label == (char *) NULL)
1693     return(0);
1694   for (number_lines=1; *label != '\0'; label++)
1695     if (*label == '\n')
1696       number_lines++;
1697   return(number_lines);
1698 }
1699 \f
1700 /*
1701 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1702 %                                                                             %
1703 %                                                                             %
1704 %                                                                             %
1705 %   O p e n M a g i c k S t r e a m                                           %
1706 %                                                                             %
1707 %                                                                             %
1708 %                                                                             %
1709 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1710 %
1711 %  OpenMagickStream() opens the file at the specified path and return the
1712 %  associated stream.
1713 %
1714 %  The path of the OpenMagickStream method is:
1715 %
1716 %      FILE *OpenMagickStream(const char *path,const char *mode)
1717 %
1718 %  A description of each parameter follows.
1719 %
1720 %   o  path: the file path.
1721 %
1722 %   o  mode: the file mode.
1723 %
1724 */
1725 MagickExport FILE *OpenMagickStream(const char *path,const char *mode)
1726 {
1727   FILE
1728     *file;
1729
1730   if ((path == (const char *) NULL) || (mode == (const char *) NULL))
1731     {
1732       errno=EINVAL;
1733       return((FILE *) NULL);
1734     }
1735   file=(FILE *) NULL;
1736 #if defined(MAGICKCORE_HAVE__WFOPEN)
1737   {
1738     wchar_t
1739       *unicode_mode,
1740       *unicode_path;
1741
1742     unicode_path=ConvertUTF8ToUTF16(path);
1743     if (unicode_path == (wchar_t *) NULL)
1744       return((FILE *) NULL);
1745     unicode_mode=ConvertUTF8ToUTF16(mode);
1746     if (unicode_mode == (wchar_t *) NULL)
1747       {
1748         unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
1749         return((FILE *) NULL);
1750       }
1751     file=_wfopen(unicode_path,unicode_mode);
1752     unicode_mode=(wchar_t *) RelinquishMagickMemory(unicode_mode);
1753     unicode_path=(wchar_t *) RelinquishMagickMemory(unicode_path);
1754   }
1755 #endif
1756   if (file == (FILE *) NULL)
1757     file=fopen(path,mode);
1758   return(file);
1759 }
1760 \f
1761 /*
1762 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1763 %                                                                             %
1764 %                                                                             %
1765 %                                                                             %
1766 %   S y s t e m C o m m a n d                                                 %
1767 %                                                                             %
1768 %                                                                             %
1769 %                                                                             %
1770 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1771 %
1772 %  SystemCommand() executes the specified command and waits until it
1773 %  terminates.  The returned value is the exit status of the command.
1774 %
1775 %  The format of the SystemCommand method is:
1776 %
1777 %      int SystemCommand(const MagickBooleanType verbose,const char *command,
1778 %        ExceptionInfo *exception)
1779 %
1780 %  A description of each parameter follows:
1781 %
1782 %    o verbose: a value other than 0 prints the executed command before it is
1783 %      invoked.
1784 %
1785 %    o command: this string is the command to execute.
1786 %
1787 %    o exception: return any errors here.
1788 %
1789 */
1790 MagickExport int SystemCommand(const MagickBooleanType verbose,
1791   const char *command,ExceptionInfo *exception)
1792 {
1793   char
1794     **arguments;
1795
1796   int
1797     number_arguments,
1798     status;
1799
1800   PolicyDomain
1801     domain;
1802
1803   PolicyRights
1804     rights;
1805
1806   register long
1807     i;
1808
1809   status=(-1);
1810   arguments=StringToArgv(command,&number_arguments);
1811   if (arguments == (char **) NULL)
1812     return(status);
1813   domain=DelegatePolicyDomain;
1814   rights=ExecutePolicyRights;
1815   if (IsRightsAuthorized(domain,rights,arguments[1]) == MagickFalse)
1816     {
1817       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1818         "NotAuthorized","`%s'",arguments[1]);
1819       for (i=0; i < number_arguments; i++)
1820         arguments[i]=DestroyString(arguments[i]);
1821       arguments=(char **) RelinquishMagickMemory(arguments);
1822       return(-1);
1823     }
1824   if (verbose != MagickFalse)
1825     {
1826       (void) fprintf(stderr,"%s\n",command);
1827       (void) fflush(stderr);
1828     }
1829 #if defined(MAGICKCORE_POSIX_SUPPORT)
1830 #if !defined(MAGICKCORE_HAVE_EXECVP)
1831   status=system(command);
1832 #else
1833   if (strspn(command,"&;<>|") == 0)
1834     status=system(command);
1835   else
1836     {
1837       pid_t
1838         child_pid;
1839
1840       /*
1841         Call application directly rather than from a shell.
1842       */
1843       child_pid=fork();
1844       if (child_pid == (pid_t) -1)
1845         status=system(command);
1846       else
1847         if (child_pid == 0)
1848           {
1849             status=execvp(arguments[1],arguments+1);
1850             _exit(1);
1851           }
1852         else
1853           {
1854             int
1855               child_status;
1856
1857             pid_t
1858               pid;
1859
1860             child_status=0;
1861             pid=waitpid(child_pid,&child_status,0);
1862             if (pid == -1)
1863               status=(-1);
1864             else
1865               {
1866                 if (WIFEXITED(child_status) != 0)
1867                   status=WEXITSTATUS(child_status);
1868                 else
1869                   if (WIFSIGNALED(child_status))
1870                     status=(-1);
1871               }
1872           }
1873     }
1874 #endif
1875 #elif defined(__WINDOWS__)
1876   status=NTSystemCommand(command);
1877 #elif defined(macintosh)
1878   status=MACSystemCommand(command);
1879 #elif defined(vms)
1880   status=system(command);
1881 #else
1882 #  error No suitable system() method.
1883 #endif
1884   if (status < 0)
1885     {
1886       char
1887         *message;
1888
1889       message=GetExceptionMessage(errno);
1890       (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
1891         "`%s': %s",command,message);
1892       message=DestroyString(message);
1893     }
1894   for (i=0; i < number_arguments; i++)
1895     arguments[i]=DestroyString(arguments[i]);
1896   arguments=(char **) RelinquishMagickMemory(arguments);
1897   return(status);
1898 }