* misc.c (print_digest_algo_note): The latest 2440bis drafts deprecates
[gnupg.git] / g10 / misc.c
1 /* misc.c -  miscellaneous functions
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
3  *               2004 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
29 #include <asm/sysinfo.h>
30 #include <asm/unistd.h>
31 #endif
32 #ifdef HAVE_SETRLIMIT
33 #include <time.h>
34 #include <sys/time.h>
35 #include <sys/resource.h>
36 #endif
37 #ifdef ENABLE_SELINUX_HACKS
38 #include <sys/stat.h>
39 #endif
40 #ifdef _WIN32
41 #include <time.h>
42 #include <process.h>
43 #endif
44 #include "util.h"
45 #include "main.h"
46 #include "photoid.h"
47 #include "options.h"
48 #include "i18n.h"
49 #include "cardglue.h"
50
51
52 #ifdef ENABLE_SELINUX_HACKS
53 /* A object and a global variable to keep track of files marked as
54    secured. */
55 struct secured_file_item 
56 {
57   struct secured_file_item *next;
58   ino_t ino;
59   dev_t dev;
60 };
61 static struct secured_file_item *secured_files;
62 #endif /*ENABLE_SELINUX_HACKS*/
63
64
65
66 #if defined(__linux__) && defined(__alpha__) && __GLIBC__ < 2
67 static int
68 setsysinfo(unsigned long op, void *buffer, unsigned long size,
69                      int *start, void *arg, unsigned long flag)
70 {
71     return syscall(__NR_osf_setsysinfo, op, buffer, size, start, arg, flag);
72 }
73
74 void
75 trap_unaligned(void)
76 {
77     unsigned int buf[2];
78
79     buf[0] = SSIN_UACPROC;
80     buf[1] = UAC_SIGBUS | UAC_NOPRINT;
81     setsysinfo(SSI_NVPAIRS, buf, 1, 0, 0, 0);
82 }
83 #else
84 void
85 trap_unaligned(void)
86 {  /* dummy */
87 }
88 #endif
89
90
91 int
92 disable_core_dumps()
93 {
94 #ifdef HAVE_DOSISH_SYSTEM
95     return 0;
96 #else
97 #ifdef HAVE_SETRLIMIT
98     struct rlimit limit;
99
100     limit.rlim_cur = 0;
101     limit.rlim_max = 0;
102     if( !setrlimit( RLIMIT_CORE, &limit ) )
103         return 0;
104     if( errno != EINVAL && errno != ENOSYS )
105         log_fatal(_("can't disable core dumps: %s\n"), strerror(errno) );
106 #endif
107     return 1;
108 #endif
109 }
110
111
112 /* For the sake of SELinux we want to restrict access through gpg to
113    certain files we keep under our own control.  This function
114    registers such a file and is_secured_file may then be used to
115    check whether a file has ben registered as secured. */
116 void
117 register_secured_file (const char *fname)
118 {
119 #ifdef ENABLE_SELINUX_HACKS
120   struct stat buf;
121   struct secured_file_item *sf;
122
123   /* Note that we stop immediatley if something goes wrong here. */
124   if (stat (fname, &buf))
125     log_fatal (_("fstat of `%s' failed in %s: %s\n"), fname, 
126                "register_secured_file", strerror (errno));
127 /*   log_debug ("registering `%s' i=%lu.%lu\n", fname, */
128 /*              (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */
129   for (sf=secured_files; sf; sf = sf->next)
130     {
131       if (sf->ino == buf.st_ino && sf->dev == buf.st_dev)
132         return; /* Already registered.  */
133     }
134
135   sf = xmalloc (sizeof *sf);
136   sf->ino = buf.st_ino;
137   sf->dev = buf.st_dev;
138   sf->next = secured_files;
139   secured_files = sf;
140 #endif /*ENABLE_SELINUX_HACKS*/
141 }
142
143 /* Remove a file registerd as secure. */
144 void
145 unregister_secured_file (const char *fname)
146 {
147 #ifdef ENABLE_SELINUX_HACKS
148   struct stat buf;
149   struct secured_file_item *sf, *sfprev;
150
151   if (stat (fname, &buf))
152     {
153       log_error (_("fstat of `%s' failed in %s: %s\n"), fname,
154                  "unregister_secured_file", strerror (errno));
155       return;
156     }
157 /*   log_debug ("unregistering `%s' i=%lu.%lu\n", fname,  */
158 /*              (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */
159   for (sfprev=NULL,sf=secured_files; sf; sfprev=sf, sf = sf->next)
160     {
161       if (sf->ino == buf.st_ino && sf->dev == buf.st_dev)
162         {
163           if (sfprev)
164             sfprev->next = sf->next;
165           else
166             secured_files = sf->next;
167           xfree (sf);
168           return;
169         }
170     }
171 #endif /*ENABLE_SELINUX_HACKS*/
172 }
173
174 /* Return true if FD is corresponds to a secured file.  Using -1 for
175    FS is allowed and will return false. */ 
176 int 
177 is_secured_file (int fd)
178 {
179 #ifdef ENABLE_SELINUX_HACKS
180   struct stat buf;
181   struct secured_file_item *sf;
182
183   if (fd == -1)
184     return 0; /* No file descriptor so it can't be secured either.  */
185
186   /* Note that we print out a error here and claim that a file is
187      secure if something went wrong. */
188   if (fstat (fd, &buf))
189     {
190       log_error (_("fstat(%d) failed in %s: %s\n"), fd, 
191                  "is_secured_file", strerror (errno));
192       return 1;
193     }
194 /*   log_debug ("is_secured_file (%d) i=%lu.%lu\n", fd, */
195 /*              (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */
196   for (sf=secured_files; sf; sf = sf->next)
197     {
198       if (sf->ino == buf.st_ino && sf->dev == buf.st_dev)
199         return 1; /* Yes.  */
200     }
201 #endif /*ENABLE_SELINUX_HACKS*/
202   return 0; /* No. */
203 }
204
205 /* Return true if FNAME is corresponds to a secured file.  Using NULL,
206    "" or "-" for FS is allowed and will return false. This function is
207    used before creating a file, thus it won't fail if the file does
208    not exist. */ 
209 int 
210 is_secured_filename (const char *fname)
211 {
212 #ifdef ENABLE_SELINUX_HACKS
213   struct stat buf;
214   struct secured_file_item *sf;
215
216   if (iobuf_is_pipe_filename (fname) || !*fname)
217     return 0; 
218
219   /* Note that we print out a error here and claim that a file is
220      secure if something went wrong. */
221   if (stat (fname, &buf))
222     {
223       if (errno == ENOENT || errno == EPERM || errno == EACCES)
224         return 0;
225       log_error (_("fstat of `%s' failed in %s: %s\n"), fname,
226                  "is_secured_filename", strerror (errno));
227       return 1;
228     }
229 /*   log_debug ("is_secured_filename (%s) i=%lu.%lu\n", fname, */
230 /*              (unsigned long)buf.st_dev, (unsigned long)buf.st_ino); */
231   for (sf=secured_files; sf; sf = sf->next)
232     {
233       if (sf->ino == buf.st_ino && sf->dev == buf.st_dev)
234         return 1; /* Yes.  */
235     }
236 #endif /*ENABLE_SELINUX_HACKS*/
237   return 0; /* No. */
238 }
239
240
241
242 u16
243 checksum_u16( unsigned n )
244 {
245     u16 a;
246
247     a  = (n >> 8) & 0xff;
248     a += n & 0xff;
249     return a;
250 }
251
252
253 u16
254 checksum( byte *p, unsigned n )
255 {
256     u16 a;
257
258     for(a=0; n; n-- )
259         a += *p++;
260     return a;
261 }
262
263 u16
264 checksum_mpi( MPI a )
265 {
266     u16 csum;
267     byte *buffer;
268     unsigned nbytes;
269     unsigned nbits;
270
271     buffer = mpi_get_buffer( a, &nbytes, NULL );
272     nbits = mpi_get_nbits(a);
273     csum = checksum_u16( nbits );
274     csum += checksum( buffer, nbytes );
275     m_free( buffer );
276     return csum;
277 }
278
279 u32
280 buffer_to_u32( const byte *buffer )
281 {
282     unsigned long a;
283     a =  *buffer << 24;
284     a |= buffer[1] << 16;
285     a |= buffer[2] << 8;
286     a |= buffer[3];
287     return a;
288 }
289
290 void
291 print_pubkey_algo_note( int algo )
292 {
293   if(algo >= 100 && algo <= 110)
294     {
295       static int warn=0;
296       if(!warn)
297         {
298           warn=1;
299           log_info(_("WARNING: using experimental public key algorithm %s\n"),
300                    pubkey_algo_to_string(algo));
301         }
302     }
303 }
304
305 void
306 print_cipher_algo_note( int algo )
307 {
308   if(algo >= 100 && algo <= 110)
309     {
310       static int warn=0;
311       if(!warn)
312         {
313           warn=1;
314           log_info(_("WARNING: using experimental cipher algorithm %s\n"),
315                    cipher_algo_to_string(algo));
316         }
317     }
318 }
319
320 void
321 print_digest_algo_note( int algo )
322 {
323   if(algo >= 100 && algo <= 110)
324     {
325       static int warn=0;
326       if(!warn)
327         {
328           warn=1;
329           log_info(_("WARNING: using experimental digest algorithm %s\n"),
330                    digest_algo_to_string(algo));
331         }
332     }
333   else if(algo==DIGEST_ALGO_MD5)
334     log_info(_("WARNING: digest algorithm %s is deprecated\n"),
335              digest_algo_to_string(algo));
336 }
337
338 /* Return a string which is used as a kind of process ID */
339 const byte *
340 get_session_marker( size_t *rlen )
341 {
342     static byte marker[SIZEOF_UNSIGNED_LONG*2];
343     static int initialized;
344
345     if ( !initialized ) {
346         volatile ulong aa, bb; /* we really want the uninitialized value */
347         ulong a, b;
348
349         initialized = 1;
350         /* also this marker is guessable it is not easy to use this 
351          * for a faked control packet because an attacker does not
352          * have enough control about the time the verification does 
353          * take place.  Of course, we can add just more random but 
354          * than we need the random generator even for verification
355          * tasks - which does not make sense. */
356         a = aa ^ (ulong)getpid();
357         b = bb ^ (ulong)time(NULL);
358         memcpy( marker, &a, SIZEOF_UNSIGNED_LONG );
359         memcpy( marker+SIZEOF_UNSIGNED_LONG, &b, SIZEOF_UNSIGNED_LONG );
360     }
361     *rlen = sizeof(marker);
362     return marker;
363 }
364
365 /****************
366  * Wrapper around the libgcrypt function with addional checks on
367  * openPGP contraints for the algo ID.
368  */
369 int
370 openpgp_cipher_test_algo( int algo )
371 {
372     if( algo < 0 || algo > 110 )
373         return G10ERR_CIPHER_ALGO;
374     return check_cipher_algo(algo);
375 }
376
377 int
378 openpgp_pk_test_algo( int algo, unsigned int usage_flags )
379 {
380     if( algo < 0 || algo > 110 )
381         return G10ERR_PUBKEY_ALGO;
382     return check_pubkey_algo2( algo, usage_flags );
383 }
384
385 int 
386 openpgp_pk_algo_usage ( int algo )
387 {
388     int use = 0; 
389     
390     /* they are hardwired in gpg 1.0 */
391     switch ( algo ) {    
392       case PUBKEY_ALGO_RSA:
393           use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_ENC | PUBKEY_USAGE_AUTH;
394           break;
395       case PUBKEY_ALGO_RSA_E:
396           use = PUBKEY_USAGE_ENC;
397           break;
398       case PUBKEY_ALGO_RSA_S:
399           use = PUBKEY_USAGE_SIG;
400           break;
401       case PUBKEY_ALGO_ELGAMAL_E:
402           use = PUBKEY_USAGE_ENC;
403           break;
404       case PUBKEY_ALGO_DSA:  
405           use = PUBKEY_USAGE_SIG | PUBKEY_USAGE_AUTH;
406           break;
407       default:
408           break;
409     }
410     return use;
411 }
412
413 int
414 openpgp_md_test_algo( int algo )
415 {
416     if( algo < 0 || algo > 110 )
417         return G10ERR_DIGEST_ALGO;
418     return check_digest_algo(algo);
419 }
420
421 #ifdef USE_IDEA
422 /* Special warning for the IDEA cipher */
423 void
424 idea_cipher_warn(int show)
425 {
426   static int warned=0;
427
428   if(!warned || show)
429     {
430       log_info(_("the IDEA cipher plugin is not present\n"));
431       log_info(_("please see http://www.gnupg.org/why-not-idea.html "
432                  "for more information\n"));
433       warned=1;
434     }
435 }
436 #endif
437
438 static unsigned long get_signature_count(PKT_secret_key *sk)
439 {
440 #ifdef ENABLE_CARD_SUPPORT
441   if(sk && sk->is_protected && sk->protect.s2k.mode==1002)
442     {
443       struct agent_card_info_s info;
444       if(agent_scd_getattr("SIG-COUNTER",&info)==0)
445         return info.sig_counter;
446     }  
447 #endif
448
449   /* How to do this without a card? */
450
451   return 0;
452 }
453
454 /* Expand %-strings.  Returns a string which must be m_freed.  Returns
455    NULL if the string cannot be expanded (too large). */
456 char *
457 pct_expando(const char *string,struct expando_args *args)
458 {
459   const char *ch=string;
460   int idx=0,maxlen=0,done=0;
461   u32 pk_keyid[2]={0,0},sk_keyid[2]={0,0};
462   char *ret=NULL;
463
464   if(args->pk)
465     keyid_from_pk(args->pk,pk_keyid);
466
467   if(args->sk)
468     keyid_from_sk(args->sk,sk_keyid);
469
470   /* This is used so that %k works in photoid command strings in
471      --list-secret-keys (which of course has a sk, but no pk). */
472   if(!args->pk && args->sk)
473     keyid_from_sk(args->sk,pk_keyid);
474
475   while(*ch!='\0')
476     {
477       char *str=NULL;
478
479       if(!done)
480         {
481           /* 8192 is way bigger than we'll need here */
482           if(maxlen>=8192)
483             goto fail;
484
485           maxlen+=1024;
486           ret=m_realloc(ret,maxlen);
487         }
488
489       done=0;
490
491       if(*ch=='%')
492         {
493           switch(*(ch+1))
494             {
495             case 's': /* short key id */
496               if(idx+8<maxlen)
497                 {
498                   sprintf(&ret[idx],"%08lX",(ulong)sk_keyid[1]);
499                   idx+=8;
500                   done=1;
501                 }
502               break;
503
504             case 'S': /* long key id */
505               if(idx+16<maxlen)
506                 {
507                   sprintf(&ret[idx],"%08lX%08lX",
508                           (ulong)sk_keyid[0],(ulong)sk_keyid[1]);
509                   idx+=16;
510                   done=1;
511                 }
512               break;
513
514             case 'k': /* short key id */
515               if(idx+8<maxlen)
516                 {
517                   sprintf(&ret[idx],"%08lX",(ulong)pk_keyid[1]);
518                   idx+=8;
519                   done=1;
520                 }
521               break;
522
523             case 'K': /* long key id */
524               if(idx+16<maxlen)
525                 {
526                   sprintf(&ret[idx],"%08lX%08lX",
527                           (ulong)pk_keyid[0],(ulong)pk_keyid[1]);
528                   idx+=16;
529                   done=1;
530                 }
531               break;
532
533             case 'c': /* signature count from card, if any. */
534               if(idx+10<maxlen)
535                 {
536                   sprintf(&ret[idx],"%lu",get_signature_count(args->sk));
537                   idx+=strlen(&ret[idx]);
538                   done=1;
539                 }             
540               break;
541
542             case 'p': /* primary pk fingerprint of a sk */
543             case 'f': /* pk fingerprint */
544             case 'g': /* sk fingerprint */
545               {
546                 byte array[MAX_FINGERPRINT_LEN];
547                 size_t len;
548                 int i;
549
550                 if((*(ch+1))=='p' && args->sk)
551                   {
552                     if(args->sk->is_primary)
553                       fingerprint_from_sk(args->sk,array,&len);
554                     else if(args->sk->main_keyid[0] || args->sk->main_keyid[1])
555                       {
556                         PKT_public_key *pk=
557                           m_alloc_clear(sizeof(PKT_public_key));
558
559                         if(get_pubkey_fast(pk,args->sk->main_keyid)==0)
560                           fingerprint_from_pk(pk,array,&len);
561                         else
562                           memset(array,0,(len=MAX_FINGERPRINT_LEN));
563                         free_public_key(pk);
564                       }
565                     else
566                       memset(array,0,(len=MAX_FINGERPRINT_LEN));
567                   }
568                 else if((*(ch+1))=='f' && args->pk)
569                   fingerprint_from_pk(args->pk,array,&len);
570                 else if((*(ch+1))=='g' && args->sk)
571                   fingerprint_from_sk(args->sk,array,&len);
572                 else
573                   memset(array,0,(len=MAX_FINGERPRINT_LEN));
574
575                 if(idx+(len*2)<maxlen)
576                   {
577                     for(i=0;i<len;i++)
578                       {
579                         sprintf(&ret[idx],"%02X",array[i]);
580                         idx+=2;
581                       }
582                     done=1;
583                   }
584               }
585               break;
586
587             case 't': /* e.g. "jpg" */
588               str=image_type_to_string(args->imagetype,0);
589               /* fall through */
590
591             case 'T': /* e.g. "image/jpeg" */
592               if(str==NULL)
593                 str=image_type_to_string(args->imagetype,2);
594
595               if(idx+strlen(str)<maxlen)
596                 {
597                   strcpy(&ret[idx],str);
598                   idx+=strlen(str);
599                   done=1;
600                 }
601               break;
602
603             case '%':
604               if(idx+1<maxlen)
605                 {
606                   ret[idx++]='%';
607                   ret[idx]='\0';
608                   done=1;
609                 }
610               break;
611
612               /* Any unknown %-keys (like %i, %o, %I, and %O) are
613                  passed through for later expansion.  Note this also
614                  handles the case where the last character in the
615                  string is a '%' - the terminating \0 will end up here
616                  and properly terminate the string. */
617             default:
618               if(idx+2<maxlen)
619                 {
620                   ret[idx++]='%';
621                   ret[idx++]=*(ch+1);
622                   ret[idx]='\0';
623                   done=1;
624                 }
625               break;
626               }
627
628           if(done)
629             ch++;
630         }
631       else
632         {
633           if(idx+1<maxlen)
634             {
635               ret[idx++]=*ch;
636               ret[idx]='\0';
637               done=1;
638             }
639         }
640
641       if(done)
642         ch++;
643     }
644
645   return ret;
646
647  fail:
648   m_free(ret);
649   return NULL;
650 }
651
652 void
653 deprecated_warning(const char *configname,unsigned int configlineno,
654                    const char *option,const char *repl1,const char *repl2)
655 {
656   if(configname)
657     {
658       if(strncmp("--",option,2)==0)
659         option+=2;
660
661       if(strncmp("--",repl1,2)==0)
662         repl1+=2;
663
664       log_info(_("%s:%d: deprecated option \"%s\"\n"),
665                configname,configlineno,option);
666     }
667   else
668     log_info(_("WARNING: \"%s\" is a deprecated option\n"),option);
669
670   log_info(_("please use \"%s%s\" instead\n"),repl1,repl2);
671 }
672
673 const char *
674 compress_algo_to_string(int algo)
675 {
676   const char *s=NULL;
677
678   switch(algo)
679     {
680     case COMPRESS_ALGO_NONE:
681       s=_("Uncompressed");
682       break;
683
684     case COMPRESS_ALGO_ZIP:
685       s="ZIP";
686       break;
687
688     case COMPRESS_ALGO_ZLIB:
689       s="ZLIB";
690       break;
691
692 #ifdef HAVE_BZIP2
693     case COMPRESS_ALGO_BZIP2:
694       s="BZIP2";
695       break;
696 #endif
697     }
698
699   return s;
700 }
701
702 int
703 string_to_compress_algo(const char *string)
704 {
705   /* NOTE TO TRANSLATOR: See doc/TRANSLATE about this string. */
706   if(match_multistr(_("uncompressed|none"),string))
707     return 0;
708   else if(ascii_strcasecmp(string,"uncompressed")==0)
709     return 0;
710   else if(ascii_strcasecmp(string,"none")==0)
711     return 0;
712   else if(ascii_strcasecmp(string,"zip")==0)
713     return 1;
714   else if(ascii_strcasecmp(string,"zlib")==0)
715     return 2;
716 #ifdef HAVE_BZIP2
717   else if(ascii_strcasecmp(string,"bzip2")==0)
718     return 3;
719 #endif
720   else if(ascii_strcasecmp(string,"z0")==0)
721     return 0;
722   else if(ascii_strcasecmp(string,"z1")==0)
723     return 1;
724   else if(ascii_strcasecmp(string,"z2")==0)
725     return 2;
726 #ifdef HAVE_BZIP2
727   else if(ascii_strcasecmp(string,"z3")==0)
728     return 3;
729 #endif
730   else
731     return -1;
732 }
733
734 int
735 check_compress_algo(int algo)
736 {
737 #ifdef HAVE_BZIP2
738   if(algo>=0 && algo<=3)
739     return 0;
740 #else
741   if(algo>=0 && algo<=2)
742     return 0;
743 #endif
744
745   return G10ERR_COMPR_ALGO;
746 }
747
748 int
749 default_cipher_algo(void)
750 {
751   if(opt.def_cipher_algo)
752     return opt.def_cipher_algo;
753   else if(opt.personal_cipher_prefs)
754     return opt.personal_cipher_prefs[0].value;
755   else
756     return opt.s2k_cipher_algo;
757 }
758
759 /* There is no default_digest_algo function, but see
760    sign.c:hash_for() */
761
762 int
763 default_compress_algo(void)
764 {
765   if(opt.compress_algo!=-1)
766     return opt.compress_algo;
767   else if(opt.personal_compress_prefs)
768     return opt.personal_compress_prefs[0].value;
769   else
770     return DEFAULT_COMPRESS_ALGO;
771 }
772
773 const char *
774 compliance_option_string(void)
775 {
776   switch(opt.compliance)
777     {
778     case CO_RFC2440:
779       return "--openpgp";
780     case CO_PGP2:
781       return "--pgp2";
782     case CO_PGP6:
783       return "--pgp6";
784     case CO_PGP7:
785       return "--pgp7";
786     case CO_PGP8:
787       return "--pgp8";
788     default:
789       return "???";
790     }
791 }
792
793 static const char *
794 compliance_string(void)
795 {
796   switch(opt.compliance)
797     {
798     case CO_RFC2440:
799       return "OpenPGP";
800     case CO_PGP2:
801       return "PGP 2.x";
802     case CO_PGP6:
803       return "PGP 6.x";
804     case CO_PGP7:
805       return "PGP 7.x";
806     case CO_PGP8:
807       return "PGP 8.x";
808     default:
809       return "???";
810     }
811 }
812
813 void
814 compliance_failure(void)
815 {
816   log_info(_("this message may not be usable by %s\n"),compliance_string());
817   opt.compliance=CO_GNUPG;
818 }
819
820 /* Break a string into successive option pieces.  Accepts single word
821    options and key=value argument options. */
822 char *
823 optsep(char **stringp)
824 {
825   char *tok,*end;
826
827   tok=*stringp;
828   if(tok)
829     {
830       end=strpbrk(tok," ,=");
831       if(end)
832         {
833           int sawequals=0;
834           char *ptr=end;
835
836           /* what we need to do now is scan along starting with *end,
837              If the next character we see (ignoring spaces) is an =
838              sign, then there is an argument. */
839
840           while(*ptr)
841             {
842               if(*ptr=='=')
843                 sawequals=1;
844               else if(*ptr!=' ')
845                 break;
846               ptr++;
847             }
848
849           /* There is an argument, so grab that too.  At this point,
850              ptr points to the first character of the argument. */
851           if(sawequals)
852             {
853               /* Is it a quoted argument? */
854               if(*ptr=='"')
855                 {
856                   ptr++;
857                   end=strchr(ptr,'"');
858                   if(end)
859                     end++;
860                 }
861               else
862                 end=strpbrk(ptr," ,");
863             }
864
865           if(end && *end)
866             {
867               *end='\0';
868               *stringp=end+1;
869             }
870           else
871             *stringp=NULL;
872         }
873       else
874         *stringp=NULL;
875     }
876
877   return tok;
878 }
879
880 /* Breaks an option value into key and value.  Returns NULL if there
881    is no value.  Note that "string" is modified to remove the =value
882    part. */
883 char *
884 argsplit(char *string)
885 {
886   char *equals,*arg=NULL;
887
888   equals=strchr(string,'=');
889   if(equals)
890     {
891       char *quote,*space;
892
893       *equals='\0';
894       arg=equals+1;
895
896       /* Quoted arg? */
897       quote=strchr(arg,'"');
898       if(quote)
899         {
900           arg=quote+1;
901
902           quote=strchr(arg,'"');
903           if(quote)
904             *quote='\0';
905         }
906       else
907         {
908           size_t spaces;
909
910           /* Trim leading spaces off of the arg */
911           spaces=strspn(arg," ");
912           arg+=spaces;
913         }
914
915       /* Trim tailing spaces off of the tag */
916       space=strchr(string,' ');
917       if(space)
918         *space='\0';
919     }
920
921   return arg;
922 }
923
924 /* Return the length of the initial token, leaving off any
925    argument. */
926 static size_t
927 optlen(const char *s)
928 {
929   char *end=strpbrk(s," =");
930
931   if(end)
932     return end-s;
933   else
934     return strlen(s);
935 }
936
937 int
938 parse_options(char *str,unsigned int *options,
939               struct parse_options *opts,int noisy)
940 {
941   char *tok;
942
943   while((tok=optsep(&str)))
944     {
945       int i,rev=0;
946       char *otok=tok;
947
948       if(tok[0]=='\0')
949         continue;
950
951       if(ascii_strncasecmp("no-",tok,3)==0)
952         {
953           rev=1;
954           tok+=3;
955         }
956
957       for(i=0;opts[i].name;i++)
958         {
959           size_t toklen=optlen(tok);
960
961           if(ascii_strncasecmp(opts[i].name,tok,toklen)==0)
962             {
963               /* We have a match, but it might be incomplete */
964               if(toklen!=strlen(opts[i].name))
965                 {
966                   int j;
967
968                   for(j=i+1;opts[j].name;j++)
969                     {
970                       if(ascii_strncasecmp(opts[j].name,tok,toklen)==0)
971                         {
972                           if(noisy)
973                             log_info(_("ambiguous option `%s'\n"),otok);
974                           return 0;
975                         }
976                     }
977                 }
978
979               if(rev)
980                 {
981                   *options&=~opts[i].bit;
982                   if(opts[i].value)
983                     *opts[i].value=NULL;
984                 }
985               else
986                 {
987                   *options|=opts[i].bit;
988                   if(opts[i].value)
989                     *opts[i].value=argsplit(tok);
990                 }
991               break;
992             }
993         }
994
995       if(!opts[i].name)
996         {
997           if(noisy)
998             log_info(_("unknown option `%s'\n"),otok);
999           return 0;
1000         }
1001     }
1002
1003   return 1;
1004 }