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