update lintian overrides
[alioth/cvs.git] / src / subr.c
1 /*
2  * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
3  *
4  * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
5  *                                  and others.
6  *
7  * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
8  * Portions Copyright (C) 1989-1992, Brian Berliner
9  * 
10  * You may distribute under the terms of the GNU General Public License as
11  * specified in the README file that comes with the CVS source distribution.
12  * 
13  * Various useful functions for the CVS support code.
14  */
15
16 #include "cvs.h"
17
18 #include "canonicalize.h"
19 #include "canon-host.h"
20 #include "getline.h"
21 #include "vasprintf.h"
22 #include "vasnprintf.h"
23
24 /* Get wint_t.  */
25 #ifdef HAVE_WINT_T
26 # include <wchar.h>
27 #endif
28
29
30
31 extern char *getlogin (void);
32
33
34
35 /* *STRPTR is a pointer returned from malloc (or NULL), pointing to *N
36    characters of space.  Reallocate it so that points to at least
37    NEWSIZE bytes of space.  Gives a fatal error if out of memory;
38    if it returns it was successful.  */
39 void
40 expand_string (char **strptr, size_t *n, size_t newsize)
41 {
42     while (*n < newsize)
43         *strptr = x2realloc (*strptr, n);
44 }
45
46
47
48 /* char *
49  * Xreadlink (const char *link, size_t size)
50  *
51  * INPUTS
52  *  link        The original path.
53  *  size        A guess as to the size needed for the path. It need
54  *              not be right.
55  * RETURNS
56  *  The resolution of the final symbolic link in the path.
57  *
58  * ERRORS
59  *  This function exits with a fatal error if it fails to read the
60  *  link for any reason.
61  */
62 char *
63 Xreadlink (const char *link, size_t size)
64 {
65     char *file = xreadlink (link, size);
66
67     if (file == NULL)
68         error (1, errno, "cannot readlink %s", link);
69
70     return file;
71 }
72
73
74
75 /* *STR is a pointer to a malloc'd string or NULL.  *LENP is its allocated
76  * length.  If *STR is NULL then *LENP must be 0 and visa-versa.
77  * Add SRC to the end of *STR, reallocating *STR if necessary.  */
78 void
79 xrealloc_and_strcat (char **str, size_t *lenp, const char *src)
80 {
81     bool newstr = !*lenp;
82     expand_string (str, lenp, (newstr ? 0 : strlen (*str)) + strlen (src) + 1);
83     if (newstr)
84         strcpy (*str, src);
85     else
86         strcat (*str, src);
87 }
88
89
90
91 /* Remove trailing newlines from STRING, destructively.
92  *
93  * RETURNS
94  *
95  *   True if any newlines were removed, false otherwise.
96  */
97 int
98 strip_trailing_newlines (char *str)
99 {
100     size_t index, origlen;
101     index = origlen = strlen (str);
102
103     while (index > 0 && str[index-1] == '\n')
104         str[--index] = '\0';
105
106     return index != origlen;
107 }
108
109
110
111 /* Return the number of levels that PATH ascends above where it starts.
112  * For example:
113  *
114  *   "../../foo" -> 2
115  *   "foo/../../bar" -> 1
116  */
117 int
118 pathname_levels (const char *p)
119 {
120     int level;
121     int max_level;
122
123     if (p == NULL) return 0;
124
125     max_level = 0;
126     level = 0;
127     do
128     {
129         /* Now look for pathname level-ups.  */
130         if (p[0] == '.' && p[1] == '.' && (p[2] == '\0' || ISSLASH (p[2])))
131         {
132             --level;
133             if (-level > max_level)
134                 max_level = -level;
135         }
136         else if (p[0] == '\0' || ISSLASH (p[0]) ||
137                  (p[0] == '.' && (p[1] == '\0' || ISSLASH (p[1]))))
138             ;
139         else
140             ++level;
141
142         /* q = strchr (p, '/'); but sub ISSLASH() for '/': */
143         while (*p != '\0' && !ISSLASH (*p)) p++;
144         if (*p != '\0') p++;
145     } while (*p != '\0');
146     return max_level;
147 }
148
149
150
151 /* Free a vector, where (*ARGV)[0], (*ARGV)[1], ... (*ARGV)[*PARGC - 1]
152    are malloc'd and so is *ARGV itself.  Such a vector is allocated by
153    line2argv or expand_wild, for example.  */
154 void
155 free_names (int *pargc, char **argv)
156 {
157     register int i;
158
159     for (i = 0; i < *pargc; i++)
160     {                                   /* only do through *pargc */
161         free (argv[i]);
162     }
163     free (argv);
164     *pargc = 0;                         /* and set it to zero when done */
165 }
166
167
168
169 /* Convert LINE into arguments separated by SEPCHARS.  Set *ARGC
170    to the number of arguments found, and (*ARGV)[0] to the first argument,
171    (*ARGV)[1] to the second, etc.  *ARGV is malloc'd and so are each of
172    (*ARGV)[0], (*ARGV)[1], ...  Use free_names() to return the memory
173    allocated here back to the free pool.  */
174 void
175 line2argv (int *pargc, char ***argv, char *line, char *sepchars)
176 {
177     char *cp;
178     /* Could make a case for size_t or some other unsigned type, but
179        we'll stick with int to avoid signed/unsigned warnings when
180        comparing with *pargc.  */
181     int argv_allocated;
182
183     /* Small for testing.  */
184     argv_allocated = 1;
185     *argv = xnmalloc (argv_allocated, sizeof (**argv));
186
187     *pargc = 0;
188     for (cp = strtok (line, sepchars); cp; cp = strtok (NULL, sepchars))
189     {
190         if (*pargc == argv_allocated)
191         {
192             argv_allocated *= 2;
193             *argv = xnrealloc (*argv, argv_allocated, sizeof (**argv));
194         }
195         (*argv)[*pargc] = xstrdup (cp);
196         (*pargc)++;
197     }
198 }
199
200
201
202 /*
203  * Returns the number of dots ('.') found in an RCS revision number
204  */
205 int
206 numdots (const char *s)
207 {
208     int dots = 0;
209
210     for (; *s; s++)
211     {
212         if (*s == '.')
213             dots++;
214     }
215     return (dots);
216 }
217
218
219
220 /* Compare revision numbers REV1 and REV2 by consecutive fields.
221    Return negative, zero, or positive in the manner of strcmp.  The
222    two revision numbers must have the same number of fields, or else
223    compare_revnums will return an inaccurate result. */
224 int
225 compare_revnums (const char *rev1, const char *rev2)
226 {
227     const char *sp, *tp;
228     char *snext, *tnext;
229     int result = 0;
230
231     sp = rev1;
232     tp = rev2;
233     while (result == 0)
234     {
235         result = strtoul (sp, &snext, 10) - strtoul (tp, &tnext, 10);
236         if (*snext == '\0' || *tnext == '\0')
237             break;
238         sp = snext + 1;
239         tp = tnext + 1;
240     }
241
242     return result;
243 }
244
245
246
247 /* Increment a revision number.  Working on the string is a bit awkward,
248    but it avoid problems with integer overflow should the revision numbers
249    get really big.  */
250 char *
251 increment_revnum (const char *rev)
252 {
253     char *newrev, *p;
254     size_t len = strlen (rev);
255
256     newrev = xmalloc (len + 2);
257     memcpy (newrev, rev, len + 1);
258     for (p = newrev + len; p != newrev; )
259     {
260         --p;
261         if (!isdigit(*p))
262         {
263             ++p;
264             break;
265         }
266         if (*p != '9')
267         {
268             ++*p;
269             return newrev;
270         }
271         *p = '0';
272     }
273     /* The number was all 9s, so change the first character to 1 and add
274        a 0 to the end.  */
275     *p = '1';
276     p = newrev + len;
277     *p++ = '0';
278     *p = '\0';
279     return newrev;
280 }
281
282
283
284 /* Return the username by which the caller should be identified in
285    CVS, in contexts such as the author field of RCS files, various
286    logs, etc.  */
287 char *
288 getcaller (void)
289 {
290 #ifndef SYSTEM_GETCALLER
291     static char *cache;
292     struct passwd *pw;
293     uid_t uid;
294 #endif
295
296     /* If there is a CVS username, return it.  */
297 #ifdef AUTH_SERVER_SUPPORT
298     if (CVS_Username != NULL)
299         return CVS_Username;
300 #endif
301
302 #ifdef SYSTEM_GETCALLER
303     return SYSTEM_GETCALLER ();
304 #else
305     /* Get the caller's login from his uid.  If the real uid is "root"
306        try LOGNAME USER or getlogin(). If getlogin() and getpwuid()
307        both fail, return the uid as a string.  */
308
309     if (cache != NULL)
310         return cache;
311
312     uid = getuid ();
313     if (uid == (uid_t) 0)
314     {
315         char *name;
316
317         /* super-user; try getlogin() to distinguish */
318         name = getlogin();
319         if (!name || !*name)
320                 name = getenv("LOGNAME");
321         if (!name || !*name)
322                 name = getenv("USER");
323         if (name && *name)
324         {
325             cache = xstrdup (name);
326             return cache;
327         }
328     }
329     if ((pw = (struct passwd *) getpwuid (uid)) == NULL)
330     {
331         cache = Xasprintf ("uid%lu", (unsigned long) uid);
332         return cache;
333     }
334     cache = xstrdup (pw->pw_name);
335     return cache;
336 #endif
337 }
338
339
340
341 #ifdef lint
342 # ifndef __GNUC__
343 /* ARGSUSED */
344 bool
345 get_date (struct timespec *result, char const *p, struct timespec const *now)
346 {
347     result->tv_sec = 0;
348     result->tv_nsec = 0;
349
350     return false;
351 }
352 # endif
353 #endif
354
355
356
357 /* Given some revision, REV, return the first prior revision that exists in the
358  * RCS file, RCS.
359  *
360  * ASSUMPTIONS
361  *   REV exists.
362  *
363  * INPUTS
364  *   RCS        The RCS node pointer.
365  *   REV        An existing revision in the RCS file referred to by RCS.
366  *
367  * RETURNS
368  *   The first prior revision that exists in the RCS file, or NULL if no prior
369  *   revision exists.  The caller is responsible for disposing of this string.
370  *
371  * NOTES
372  *   This function currently neglects the case where we are on the trunk with
373  *   rev = X.1, where X != 1.  If rev = X.Y, where X != 1 and Y > 1, then this
374  *   function should work fine, as revision X.1 must exist, due to RCS rules.
375  */
376 char *
377 previous_rev (RCSNode *rcs, const char *rev)
378 {
379     char *p;
380     char *tmp = xstrdup (rev);
381     long r1;
382     char *retval;
383
384     /* Our retval can have no more digits and dots than our input revision.  */
385     retval = xmalloc (strlen (rev) + 1);
386     p = strrchr (tmp, '.');
387     *p = '\0';
388     r1 = strtol (p+1, NULL, 10);
389     do {
390         if (--r1 == 0)
391         {
392                 /* If r1 == 0, then we must be on a branch and our parent must
393                  * exist, or we must be on the trunk with a REV like X.1.
394                  * We are neglecting the X.1 with X != 1 case by assuming that
395                  * there is no previous revision when we discover we were on
396                  * the trunk.
397                  */
398                 p = strrchr (tmp, '.');
399                 if (p == NULL)
400                     /* We are on the trunk.  */
401                     retval = NULL;
402                 else
403                 {
404                     *p = '\0';
405                     sprintf (retval, "%s", tmp);
406                 }
407                 break;
408         }
409         sprintf (retval, "%s.%ld", tmp, r1);
410     } while (!RCS_exist_rev (rcs, retval));
411
412     free (tmp);
413     return retval;
414 }
415
416
417
418 /* Given two revisions, find their greatest common ancestor.  If the
419    two input revisions exist, then rcs guarantees that the gca will
420    exist.  */
421 char *
422 gca (const char *rev1, const char *rev2)
423 {
424     int dots;
425     char *gca, *g;
426     const char *p1, *p2;
427     int r1, r2;
428     char *retval;
429
430     if (rev1 == NULL || rev2 == NULL)
431     {
432         error (0, 0, "sanity failure in gca");
433         abort();
434     }
435
436     /* The greatest common ancestor will have no more dots, and numbers
437        of digits for each component no greater than the arguments.  Therefore
438        this string will be big enough.  */
439     g = gca = xmalloc (strlen (rev1) + strlen (rev2) + 100);
440
441     /* walk the strings, reading the common parts. */
442     p1 = rev1;
443     p2 = rev2;
444     do
445     {
446         r1 = strtol (p1, (char **) &p1, 10);
447         r2 = strtol (p2, (char **) &p2, 10);
448         
449         /* use the lowest. */
450         (void) sprintf (g, "%d.", r1 < r2 ? r1 : r2);
451         g += strlen (g);
452         if (*p1 == '.') ++p1;
453         else break;
454         if (*p2 == '.') ++p2;
455         else break;
456     } while (r1 == r2);
457
458     /* erase that last dot. */
459     *--g = '\0';
460
461     /* numbers differ, or we ran out of strings.  we're done with the
462        common parts.  */
463
464     dots = numdots (gca);
465     if (dots == 0)
466     {
467         /* revisions differ in trunk major number.  */
468
469         if (r2 < r1) p1 = p2;
470         if (*p1 == '\0')
471         {
472             /* we only got one number.  this is strange.  */
473             error (0, 0, "bad revisions %s or %s", rev1, rev2);
474             abort();
475         }
476         else
477         {
478             /* we have a minor number.  use it.  */
479             *g++ = '.';
480             while (*p1 != '.' && *p1 != '\0')
481                 *g++ = *p1++;
482             *g = '\0';
483         }
484     }
485     else if ((dots & 1) == 0)
486     {
487         /* if we have an even number of dots, then we have a branch.
488            remove the last number in order to make it a revision.  */
489         
490         g = strrchr (gca, '.');
491         *g = '\0';
492     }
493
494     retval = xstrdup (gca);
495     free (gca);
496     return retval;
497 }
498
499
500
501 /* Give fatal error if REV is numeric and ARGC,ARGV imply we are
502    planning to operate on more than one file.  The current directory
503    should be the working directory.  Note that callers assume that we
504    will only be checking the first character of REV; it need not have
505    '\0' at the end of the tag name and other niceties.  Right now this
506    is only called from admin.c, but if people like the concept it probably
507    should also be called from diff -r, update -r, get -r, and log -r.  */
508 void
509 check_numeric (const char *rev, int argc, char **argv)
510 {
511     if (rev == NULL || !isdigit ((unsigned char) *rev))
512         return;
513
514     /* Note that the check for whether we are processing more than one
515        file is (basically) syntactic; that is, we don't behave differently
516        depending on whether a directory happens to contain only a single
517        file or whether it contains more than one.  I strongly suspect this
518        is the least confusing behavior.  */
519     if (argc != 1
520         || (!wrap_name_has (argv[0], WRAP_TOCVS) && isdir (argv[0])))
521     {
522         error (0, 0, "while processing more than one file:");
523         error (1, 0, "attempt to specify a numeric revision");
524     }
525 }
526
527
528
529 /*
530  *  Sanity checks and any required fix-up on message passed to RCS via '-m'.
531  *  RCS 5.7 requires that a non-total-whitespace, non-null message be provided
532  *  with '-m'.  Returns a newly allocated, non-empty buffer with whitespace
533  *  stripped from end of lines and end of buffer.
534  *
535  *  TODO: We no longer use RCS to manage repository files, so maybe this
536  *  nonsense about non-empty log fields can be dropped.
537  */
538 char *
539 make_message_rcsvalid (const char *message)
540 {
541     char *dst, *dp;
542     const char *mp;
543
544     if (message == NULL) message = "";
545
546     /* Strip whitespace from end of lines and end of string. */
547     dp = dst = (char *) xmalloc (strlen (message) + 1);
548     for (mp = message; *mp != '\0'; ++mp)
549     {
550         if (*mp == '\n')
551         {
552             /* At end-of-line; backtrack to last non-space. */
553             while (dp > dst && (dp[-1] == ' ' || dp[-1] == '\t'))
554                 --dp;
555         }
556         *dp++ = *mp;
557     }
558
559     /* Backtrack to last non-space at end of string, and truncate. */
560     while (dp > dst && isspace ((unsigned char) dp[-1]))
561         --dp;
562     *dp = '\0';
563
564     /* After all that, if there was no non-space in the string,
565        substitute a non-empty message. */
566     if (*dst == '\0')
567     {
568         free (dst);
569         dst = xstrdup ("*** empty log message ***");
570     }
571
572     return dst;
573 }
574
575
576
577 /* Does the file FINFO contain conflict markers?  The whole concept
578    of looking at the contents of the file to figure out whether there are
579    unresolved conflicts is kind of bogus (people do want to manage files
580    which contain those patterns not as conflict markers), but for now it
581    is what we do.  */
582 int
583 file_has_markers (const struct file_info *finfo)
584 {
585     FILE *fp;
586     char *line = NULL;
587     size_t line_allocated = 0;
588     int result;
589
590     result = 0;
591     fp = CVS_FOPEN (finfo->file, "r");
592     if (fp == NULL)
593         error (1, errno, "cannot open %s", finfo->fullname);
594     while (getline (&line, &line_allocated, fp) > 0)
595     {
596         if (strncmp (line, RCS_MERGE_PAT_1, sizeof RCS_MERGE_PAT_1 - 1) == 0 ||
597             strncmp (line, RCS_MERGE_PAT_2, sizeof RCS_MERGE_PAT_2 - 1) == 0 ||
598             strncmp (line, RCS_MERGE_PAT_3, sizeof RCS_MERGE_PAT_3 - 1) == 0)
599         {
600             result = 1;
601             goto out;
602         }
603     }
604     if (ferror (fp))
605         error (0, errno, "cannot read %s", finfo->fullname);
606 out:
607     if (fclose (fp) < 0)
608         error (0, errno, "cannot close %s", finfo->fullname);
609     if (line != NULL)
610         free (line);
611     return result;
612 }
613
614
615
616 /* Read the entire contents of the file NAME into *BUF.
617    If NAME is NULL, read from stdin.  *BUF
618    is a pointer returned from malloc (or NULL), pointing to *BUFSIZE
619    bytes of space.  The actual size is returned in *LEN.  On error,
620    give a fatal error.  The name of the file to use in error messages
621    (typically will include a directory if we have changed directory)
622    is FULLNAME.  MODE is "r" for text or "rb" for binary.  */
623 void
624 get_file (const char *name, const char *fullname, const char *mode, char **buf,
625           size_t *bufsize, size_t *len)
626 {
627     struct stat s;
628     size_t nread;
629     char *tobuf;
630     FILE *e;
631     size_t filesize;
632
633     if (name == NULL)
634     {
635         e = stdin;
636         filesize = 100; /* force allocation of minimum buffer */
637     }
638     else
639     {
640         /* Although it would be cleaner in some ways to just read
641            until end of file, reallocating the buffer, this function
642            does get called on files in the working directory which can
643            be of arbitrary size, so I think we better do all that
644            extra allocation.  */
645
646         if (stat (name, &s) < 0)
647             error (1, errno, "can't stat %s", fullname);
648
649         /* Convert from signed to unsigned.  */
650         filesize = s.st_size;
651
652         e = xfopen (name, mode);
653     }
654
655     if (*buf == NULL || *bufsize <= filesize)
656     {
657         *bufsize = filesize + 1;
658         *buf = xrealloc (*buf, *bufsize);
659     }
660
661     tobuf = *buf;
662     nread = 0;
663     while (1)
664     {
665         size_t got;
666
667         got = fread (tobuf, 1, *bufsize - (tobuf - *buf), e);
668         if (ferror (e))
669             error (1, errno, "can't read %s", fullname);
670         nread += got;
671         tobuf += got;
672
673         if (feof (e))
674             break;
675
676         /* Allocate more space if needed.  */
677         if (tobuf == *buf + *bufsize)
678         {
679             int c;
680             long off;
681
682             c = getc (e);
683             if (c == EOF)
684                 break;
685             off = tobuf - *buf;
686             expand_string (buf, bufsize, *bufsize + 100);
687             tobuf = *buf + off;
688             *tobuf++ = c;
689             ++nread;
690         }
691     }
692
693     if (e != stdin && fclose (e) < 0)
694         error (0, errno, "cannot close %s", fullname);
695
696     *len = nread;
697
698     /* Force *BUF to be large enough to hold a null terminator. */
699     if (nread == *bufsize)
700         expand_string (buf, bufsize, *bufsize + 1);
701     (*buf)[nread] = '\0';
702 }
703
704
705
706 /* Follow a chain of symbolic links to its destination.  FILENAME
707    should be a handle to a malloc'd block of memory which contains the
708    beginning of the chain.  This routine will replace the contents of
709    FILENAME with the destination (a real file).  */
710 void
711 resolve_symlink (char **filename)
712 {
713     ssize_t rsize;
714
715     if (filename == NULL || *filename == NULL)
716         return;
717
718     while ((rsize = islink (*filename)) > 0)
719     {
720 #ifdef HAVE_READLINK
721         /* The clean thing to do is probably to have each filesubr.c
722            implement this (with an error if not supported by the
723            platform, in which case islink would presumably return 0).
724            But that would require editing each filesubr.c and so the
725            expedient hack seems to be looking at HAVE_READLINK.  */
726         char *newname = Xreadlink (*filename, rsize);
727         
728         if (ISABSOLUTE (newname))
729         {
730             free (*filename);
731             *filename = newname;
732         }
733         else
734         {
735             const char *oldname = last_component (*filename);
736             int dirlen = oldname - *filename;
737             char *fullnewname = xmalloc (dirlen + strlen (newname) + 1);
738             strncpy (fullnewname, *filename, dirlen);
739             strcpy (fullnewname + dirlen, newname);
740             free (newname);
741             free (*filename);
742             *filename = fullnewname;
743         }
744 #else
745         error (1, 0, "internal error: islink doesn't like readlink");
746 #endif
747     }
748 }
749
750
751
752 /*
753  * Rename a file to an appropriate backup name based on BAKPREFIX.
754  * If suffix non-null, then ".<suffix>" is appended to the new name.
755  *
756  * Returns the new name, which caller may free() if desired.
757  */
758 char *
759 backup_file (const char *filename, const char *suffix)
760 {
761     char *backup_name = Xasprintf ("%s%s%s%s", BAKPREFIX, filename,
762                                    suffix ? "." : "", suffix ? suffix : "");
763
764     if (isfile (filename))
765         copy_file (filename, backup_name);
766
767     return backup_name;
768 }
769
770
771
772 /*
773  * Copy a string into a buffer escaping any shell metacharacters.  The
774  * buffer should be at least twice as long as the string.
775  *
776  * Returns a pointer to the terminating NUL byte in buffer.
777  */
778 char *
779 shell_escape(char *buf, const char *str)
780 {
781     static const char meta[] = "$`\\\"";
782     const char *p;
783
784     for (;;)
785     {
786         p = strpbrk(str, meta);
787         if (!p) p = str + strlen(str);
788         if (p > str)
789         {
790             memcpy(buf, str, p - str);
791             buf += p - str;
792         }
793         if (!*p) break;
794         *buf++ = '\\';
795         *buf++ = *p++;
796         str = p;
797     }
798     *buf = '\0';
799     return buf;
800 }
801
802
803
804 /*
805  * We can only travel forwards in time, not backwards.  :)
806  */
807 void
808 sleep_past (time_t desttime)
809 {
810     time_t t;
811     long s;
812     long us;
813
814     if (time (&t) > desttime) return;
815
816     while (time (&t) <= desttime)
817     {
818 #ifdef HAVE_GETTIMEOFDAY
819         struct timeval tv;
820         gettimeofday (&tv, NULL);
821         if (tv.tv_sec > desttime)
822             break;
823         s = desttime - tv.tv_sec;
824         if (tv.tv_usec > 0)
825             us = 1000000 - tv.tv_usec;
826         else
827         {
828             s++;
829             us = 0;
830         }
831 #else
832         /* default to 20 ms increments */
833         s = desttime - t;
834         us = 20000;
835 #endif
836
837         {
838             struct timespec ts;
839             ts.tv_sec = s;
840             ts.tv_nsec = us * 1000;
841             (void)nanosleep (&ts, NULL);
842         }
843     }
844
845     /* sleep another 20 ms (2 HZ) to avoid races */
846     {
847         struct timespec ts;
848         ts.tv_sec = 0;
849         ts.tv_nsec = 20 * 1000 * 1000;
850         (void)nanosleep (&ts, NULL);
851     }
852 }
853
854
855
856 /* used to store callback data in a list indexed by the user format string
857  */
858 typedef int (*CONVPROC_t) (Node *, void *);
859 struct cmdline_bindings
860 {
861     char conversion;
862     void *data;
863     CONVPROC_t convproc;
864     void *closure;
865 };
866 /* since we store the above in a list, we need to dispose of the data field.
867  * we don't have to worry about convproc or closure since pointers are stuck
868  * in there directly and format_cmdline's caller is responsible for disposing
869  * of those if necessary.
870  */
871 static void
872 cmdline_bindings_hash_node_delete (Node *p)
873 {
874     struct cmdline_bindings *b = p->data;
875
876     if (b->conversion != ',')
877     {
878         free (b->data);
879     }
880     free (b);
881 }
882
883
884
885 /*
886  * assume s is a literal argument and put it between quotes,
887  * escaping as appropriate for a shell command line
888  *
889  * the caller is responsible for disposing of the new string
890  */
891 char *
892 cmdlinequote (char quotes, char *s)
893 {
894     char *quoted = cmdlineescape (quotes, s);
895     char *buf = Xasprintf ("%c%s%c", quotes, quoted, quotes);
896
897     free (quoted);
898     return buf;
899 }
900
901
902
903 /* read quotes as the type of quotes we are between (if any) and then make our
904  * argument so it could make it past a cmdline parser (using sh as a model)
905  * inside the quotes (if any).
906  *
907  * if you were planning on expanding any paths, it should be done before
908  * calling this function, as it escapes shell metacharacters.
909  *
910  * the caller is responsible for disposing of the new string
911  *
912  * FIXME: See about removing/combining this functionality with shell_escape()
913  * in subr.c.
914  */
915 char *
916 cmdlineescape (char quotes, char *s)
917 {
918     char *buf = NULL;
919     size_t length = 0;
920     char *d = NULL;
921     size_t doff;
922     char *lastspace;
923
924     lastspace = s - 1;
925     do
926     {
927         /* FIXME: Single quotes only require other single quotes to be escaped
928          * for Bourne Shell.
929          */
930         if ( isspace( *s ) ) lastspace = s;
931         if( quotes
932             ? ( *s == quotes
933                 || ( quotes == '"'
934                      && ( *s == '$' || *s == '`' || *s == '\\' ) ) )
935             : ( strchr( "\\$`'\"*?", *s )
936                 || isspace( *s )
937                 || ( lastspace == ( s - 1 )
938                      && *s == '~' ) ) )
939         {
940             doff = d - buf;
941             expand_string (&buf, &length, doff + 1);
942             d = buf + doff;
943             *d++ = '\\';
944         }       
945         doff = d - buf;
946         expand_string (&buf, &length, doff + 1);
947         d = buf + doff;
948     } while ((*d++ = *s++) != '\0');
949     return (buf);
950 }
951
952
953
954 /* expand format strings in a command line.  modeled roughly after printf
955  *
956  * this function's arg list must be NULL terminated
957  *
958  * assume a space delimited list of args is the desired final output,
959  * but args can be quoted (" or ').
960  *
961  * the best usage examples are in tag.c & logmsg.c, but here goes:
962  *
963  * INPUTS
964  *    int oldway        to support old format strings
965  *    char *srepos      you guessed it
966  *    char *format      the format string to parse
967  *    ...               NULL terminated data list in the following format:
968  *                      char *userformat, char *printfformat, <type> data
969  *                          where
970  *                              char *userformat        a list of possible
971  *                                                      format characters the
972  *                                                      end user might pass us
973  *                                                      in the format string
974  *                                                      (e.g. those found in
975  *                                                      taginfo or loginfo)
976  *                                                      multiple characters in
977  *                                                      this strings will be
978  *                                                      aliases for each other
979  *                              char *printfformat      the same list of args
980  *                                                      printf uses to
981  *                                                      determine what kind of
982  *                                                      data the next arg will
983  *                                                      be
984  *                              <type> data             a piece of data to be
985  *                                                      formatted into the user
986  *                                                      string, <type>
987  *                                                      determined by the
988  *                                                      printfformat string.
989  *              or      
990  *                      char *userformat, char *printfformat, List *data,
991  *                              int (*convproc) (Node *, void *), void *closure
992  *                          where
993  *                              char *userformat        same as above, except
994  *                                                      multiple characters in
995  *                                                      this string represent
996  *                                                      different node
997  *                                                      attributes which can be
998  *                                                      retrieved from data by
999  *                                                      convproc
1000  *                              char *printfformat      = ","
1001  *                              List *data              the list to be walked
1002  *                                                      with walklist &
1003  *                                                      convproc to retrieve
1004  *                                                      data for each of the
1005  *                                                      possible format
1006  *                                                      characters in
1007  *                                                      userformat
1008  *                              int (*convproc)()       see data
1009  *                              void *closure           arg to be passed into
1010  *                                                      walklist as closure
1011  *                                                      data for convproc
1012  *
1013  * EXAMPLE
1014  *    (ignoring oldway variable and srepos since those are only around while we
1015  *    SUPPORT_OLD_INFO_FMT_STRINGS)
1016  *    format_cmdline ("/cvsroot/CVSROOT/mytaginfoproc %t %o %{sVv}",
1017  *                    "t", "s", "newtag",
1018  *                    "o", "s", "mov",
1019  *                    "xG", "ld", longintwhichwontbeusedthispass,
1020  *                    "sVv", ",", tlist, pretag_list_to_args_proc,
1021  *                    (void *) mydata,
1022  *                    (char *) NULL);
1023  *
1024  *    would generate the following command line, assuming two files in tlist,
1025  *    file1 & file2, each with old versions 1.1 and new version 1.1.2.3:
1026  *
1027  *        /cvsroot/CVSROOT/mytaginfoproc "newtag" "mov" "file1" "1.1" "1.1.2.3" "file2" "1.1" "1.1.2.3"
1028  *
1029  * RETURNS
1030  *    pointer to newly allocated string.  the caller is responsible for
1031  *    disposing of this string.
1032  */
1033 char *
1034 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1035 format_cmdline (bool oldway, const char *srepos, const char *format, ...)
1036 #else /* SUPPORT_OLD_INFO_FMT_STRINGS */
1037 format_cmdline (const char *format, ...)
1038 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1039 {
1040     va_list args;       /* our input function args */
1041     char *buf;          /* where we store our output string */
1042     size_t length;      /* the allocated length of our output string in bytes.
1043                          * used as a temporary storage for the length of the
1044                          * next function argument during function
1045                          * initialization
1046                          */
1047     char *pfmt;         /* initially the list of fmt keys passed in,
1048                          * but used as a temporary key buffer later
1049                          */
1050     char *fmt;          /* buffer for format string which we are processing */
1051     size_t flen;        /* length of fmt buffer */
1052     char *d, *q, *r;    /* for walking strings */
1053     const char *s;
1054     size_t doff, qoff;
1055     char inquotes;
1056
1057     List *pflist = getlist();   /* our list of input data indexed by format
1058                                  * "strings"
1059                                  */
1060     Node *p;
1061     struct cmdline_bindings *b;
1062     static int warned_of_deprecation = 0;
1063     char key[] = "?";           /* Used as temporary storage for a single
1064                                  * character search string used to locate a
1065                                  * hash key.
1066                                  */
1067 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1068     /* state varialbes in the while loop which parses the actual
1069      * format string in the final parsing pass*/
1070     int onearg;
1071     int subbedsomething;
1072 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1073
1074 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1075     if (oldway && !warned_of_deprecation)
1076     {
1077         /* warn the user that we don't like his kind 'round these parts */
1078         warned_of_deprecation = 1;
1079         error (0, 0,
1080 "warning:  Set to use deprecated info format strings.  Establish\n"
1081 "compatibility with the new info file format strings (add a temporary '1' in\n"
1082 "all info files after each '%%' which doesn't represent a literal percent)\n"
1083 "and set UseNewInfoFmtStrings=yes in CVSROOT/config.  After that, convert\n"
1084 "individual command lines and scripts to handle the new format at your\n"
1085 "leisure.");
1086     }
1087 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1088
1089     va_start (args, format);
1090
1091     /* read our possible format strings
1092      * expect a certain number of arguments by type and a NULL format
1093      * string to terminate the list.
1094      */
1095     while ((pfmt = va_arg (args, char *)) != NULL)
1096     {
1097         char *conversion = va_arg (args, char *);
1098
1099         char conversion_error = 0;
1100         char char_conversion = 0;
1101         char decimal_conversion = 0;
1102         char integer_conversion = 0;
1103         char string_conversion = 0;
1104
1105         /* allocate space to save our data */
1106         b = xmalloc(sizeof(struct cmdline_bindings));
1107
1108         /* where did you think we were going to store all this data??? */
1109         b->convproc = NULL;
1110         b->closure = NULL;
1111
1112         /* read a length from the conversion string */
1113         s = conversion;
1114         length = 0;
1115         while (!length && *s)
1116         {
1117             switch (*s)
1118             {
1119                 case 'h':
1120                     integer_conversion = 1;
1121                     if (s[1] == 'h')
1122                     {
1123                         length = sizeof (char);
1124                         s += 2;
1125                     }
1126                     else
1127                     {
1128                         char_conversion = 1;
1129                         length = sizeof (short);
1130                         s++;
1131                     }
1132                     break;
1133 #ifdef HAVE_INTMAX_T
1134                 case 'j':
1135                     integer_conversion = 1;
1136                     length = sizeof (intmax_t);
1137                     s++;
1138                     break;
1139 #endif /* HAVE_INTMAX_T */
1140                 case 'l':
1141                     integer_conversion = 1;
1142                     if (s[1] == 'l')
1143                     {
1144 #ifdef HAVE_LONG_LONG
1145                         length = sizeof (long long);
1146 #endif
1147                         s += 2;
1148                     }
1149                     else
1150                     {
1151                         char_conversion = 2;
1152                         string_conversion = 2;
1153                         length = sizeof (long);
1154                         s++;
1155                     }
1156                     break;
1157                 case 't':
1158                     integer_conversion = 1;
1159                     length = sizeof (ptrdiff_t);
1160                     s++;
1161                     break;
1162                 case 'z':
1163                     integer_conversion = 1;
1164                     length = sizeof (size_t);
1165                     s++;
1166                     break;
1167 #ifdef HAVE_LONG_DOUBLE
1168                 case 'L':
1169                     decimal_conversion = 1;
1170                     length = sizeof (long double);
1171                     s++;
1172                     break;
1173 #endif
1174                 default:
1175                     char_conversion = 1;
1176                     decimal_conversion = 1;
1177                     integer_conversion = 1;
1178                     string_conversion = 1;
1179                     /* take care of it when we find out what we're looking for */
1180                     length = -1;
1181                     break;
1182             }
1183         }
1184         /* if we don't have a valid conversion left, that is an error */
1185         /* read an argument conversion */
1186         buf = xmalloc (strlen(conversion) + 2);
1187         *buf = '%';
1188         strcpy (buf+1, conversion);
1189         switch (*s)
1190         {
1191             case 'c':
1192                 /* chars (an integer conversion) */
1193                 if (!char_conversion)
1194                 {
1195                     conversion_error = 1;
1196                     break;
1197                 }
1198                 if (char_conversion == 2)
1199                 {
1200 #ifdef HAVE_WINT_T
1201                     length = sizeof (wint_t);
1202 #else
1203                     conversion_error = 1;
1204                     break;
1205 #endif
1206                 }
1207                 else
1208                     length = sizeof (char);
1209                 /* fall through... */
1210             case 'd':
1211             case 'i':
1212             case 'o':
1213             case 'u':
1214             case 'x':
1215             case 'X':
1216                 /* integer conversions */
1217                 if (!integer_conversion)
1218                 {
1219                     conversion_error = 1;
1220                     break;
1221                 }
1222                 if (length == -1)
1223                 {
1224                     length = sizeof (int);
1225                 }
1226                 switch (length)
1227                 {
1228                     case sizeof(char):
1229                     {
1230                         char arg_char = (char) va_arg (args, int);
1231                         b->data = Xasprintf (buf, arg_char);
1232                         break;
1233                     }
1234 #ifdef UNIQUE_INT_TYPE_WINT_T           /* implies HAVE_WINT_T */
1235                     case sizeof(wint_t):
1236                     {
1237                         wint_t arg_wint_t = va_arg (args, wint_t);
1238                         b->data = Xasprintf (buf, arg_wint_t);
1239                         break;
1240                     }
1241 #endif /* UNIQUE_INT_TYPE_WINT_T */
1242 #ifdef UNIQUE_INT_TYPE_SHORT
1243                     case sizeof(short):
1244                     {
1245                         short arg_short = (short) va_arg (args, int);
1246                         b->data = Xasprintf (buf, arg_short);
1247                         break;
1248                     }
1249 #endif /* UNIQUE_INT_TYPE_SHORT */
1250 #ifdef UNIQUE_INT_TYPE_INT
1251                     case sizeof(int):
1252                     {
1253                         int arg_int = va_arg (args, int);
1254                         b->data = Xasprintf(buf, arg_int);
1255                         break;
1256                     }
1257 #endif /* UNIQUE_INT_TYPE_INT */
1258 #ifdef UNIQUE_INT_TYPE_LONG
1259                     case sizeof(long):
1260                     {
1261                         long arg_long = va_arg (args, long);
1262                         b->data = Xasprintf (buf, arg_long);
1263                         break;
1264                     }
1265 #endif /* UNIQUE_INT_TYPE_LONG */
1266 #ifdef UNIQUE_INT_TYPE_LONG_LONG        /* implies HAVE_LONG_LONG */
1267                     case sizeof(long long):
1268                     {
1269                         long long arg_long_long = va_arg (args, long long);
1270                         b->data = Xasprintf (buf, arg_long_long);
1271                         break;
1272                     }
1273 #endif /* UNIQUE_INT_TYPE_LONG_LONG */
1274 #ifdef UNIQUE_INT_TYPE_INTMAX_T         /* implies HAVE_INTMAX_T */
1275                     case sizeof(intmax_t):
1276                     {
1277                         intmax_t arg_intmax_t = va_arg (args, intmax_t);
1278                         b->data = Xasprintf (buf, arg_intmax_t);
1279                         break;
1280                     }
1281 #endif /* UNIQUE_INT_TYPE_INTMAX_T */
1282 #ifdef UNIQUE_INT_TYPE_SIZE_T
1283                     case sizeof(size_t):
1284                     {
1285                         size_t arg_size_t = va_arg (args, size_t);
1286                         b->data = Xasprintf (buf, arg_size_t);
1287                         break;
1288                     }
1289 #endif /* UNIQUE_INT_TYPE_SIZE_T */
1290 #ifdef UNIQUE_INT_TYPE_PTRDIFF_T
1291                     case sizeof(ptrdiff_t):
1292                     {
1293                         ptrdiff_t arg_ptrdiff_t = va_arg (args, ptrdiff_t);
1294                         b->data = Xasprintf (buf, arg_ptrdiff_t);
1295                         break;
1296                     }
1297 #endif /* UNIQUE_INT_TYPE_PTRDIFF_T */
1298                     default:
1299                         dellist(&pflist);
1300                         free(b);
1301                         error (1, 0,
1302 "internal error:  unknown integer arg size (%zd)",
1303                                length);
1304                         break;
1305                 }
1306                 break;
1307             case 'a':
1308             case 'A':
1309             case 'e':
1310             case 'E':
1311             case 'f':
1312             case 'F':
1313             case 'g':
1314             case 'G':
1315                 /* decimal conversions */
1316                 if (!decimal_conversion)
1317                 {
1318                     conversion_error = 1;
1319                     break;
1320                 }
1321                 if (length == -1)
1322                 {
1323                     length = sizeof (double);
1324                 }
1325                 switch (length)
1326                 {
1327                     case sizeof(double):
1328                     {
1329                         double arg_double = va_arg (args, double);
1330                         b->data = Xasprintf (buf, arg_double);
1331                         break;
1332                     }
1333 #ifdef UNIQUE_FLOAT_TYPE_LONG_DOUBLE    /* implies HAVE_LONG_DOUBLE */
1334                     case sizeof(long double):
1335                     {
1336                         long double arg_long_double = va_arg (args, long double);
1337                         b->data = Xasprintf (buf, arg_long_double);
1338                         break;
1339                     }
1340 #endif /* UNIQUE_FLOAT_TYPE_LONG_DOUBLE */
1341                     default:
1342                         dellist(&pflist);
1343                         free(b);
1344                         error (1, 0,
1345 "internal error:  unknown floating point arg size (%zd)",
1346                                length);
1347                         break;
1348                 }
1349                 break;
1350             case 's':
1351                 switch (string_conversion)
1352                 {
1353                     case 1:
1354                         b->data = xstrdup (va_arg (args, char *));
1355                         break;
1356 #ifdef HAVE_WCHAR_T
1357                     case 2:
1358                     {
1359                         wchar_t *arg_wchar_t_string = va_arg (args, wchar_t *);
1360                         b->data = Xasprintf (buf, arg_wchar_t_string);
1361                         break;
1362                     }
1363 #endif /* HAVE_WCHAR_T */
1364                     default:
1365                         conversion_error = 1;
1366                         break;
1367                 }
1368                 break;
1369             case ',':
1370                 if (length != -1)
1371                 {
1372                     conversion_error = 1;
1373                     break;
1374                 }
1375                 b->data = va_arg (args, List *);
1376                 b->convproc = va_arg (args, CONVPROC_t);
1377                 b->closure = va_arg (args, void *);
1378                 break;
1379             default:
1380                 conversion_error = 1;
1381                 break;
1382         }
1383         free (buf);
1384         /* fail if we found an error or haven't found the end of the string */
1385         if (conversion_error || s[1])
1386         {
1387             error (1, 0,
1388 "internal error (format_cmdline): '%s' is not a valid conversion!!!",
1389                    conversion);
1390         }
1391
1392
1393         /* save our type  - we really only care wheter it's a list type (',')
1394          * or not from now on, but what the hell...
1395          */
1396         b->conversion = *s;
1397
1398         /* separate the user format string into parts and stuff our data into
1399          * the pflist (once for each possible string - diverse keys can have
1400          * duplicate data).
1401          */
1402         q = pfmt;
1403         while (*q)
1404         {
1405             struct cmdline_bindings *tb;
1406             if (*q == '{')
1407             {
1408                 s = q + 1;
1409                 while (*++q && *q != '}');
1410                 r = q + 1;
1411             }
1412             else
1413             {
1414                 s = q++;
1415                 r = q;
1416             }
1417             if (*r)
1418             {
1419                 /* copy the data since we'll need it again */
1420                 tb = xmalloc(sizeof(struct cmdline_bindings));
1421                 if (b->conversion == ',')
1422                 {
1423                     tb->data = b->data;
1424                 }
1425                 else
1426                 {
1427                     tb->data = xstrdup(b->data);
1428                 }
1429                 tb->conversion = b->conversion;
1430                 tb->convproc = b->convproc;
1431                 tb->closure = b->closure;
1432             }
1433             else
1434             {
1435                 /* we're done after this, so we don't need to copy the data */
1436                 tb = b;
1437             }
1438             p = getnode();
1439             p->key = xmalloc((q - s) + 1);
1440             strncpy (p->key, s, q - s);
1441             p->key[q-s] = '\0';
1442             p->data = tb;
1443             p->delproc = cmdline_bindings_hash_node_delete;
1444             addnode(pflist,p);
1445         }
1446     }
1447
1448     /* we're done with va_list */
1449     va_end(args);
1450
1451     /* All formatted strings include a format character that resolves to the
1452      * empty string by default, so put it in pflist.
1453      */
1454     /* allocate space to save our data */
1455     b = xmalloc(sizeof(struct cmdline_bindings));
1456     b->conversion = 's';
1457     b->convproc = NULL;
1458     b->closure = NULL;
1459     b->data = xstrdup( "" );
1460     p = getnode();
1461     p->key = xstrdup( "n" );
1462     p->data = b;
1463     p->delproc = cmdline_bindings_hash_node_delete;
1464     addnode( pflist,p );
1465
1466     /* finally, read the user string and copy it into rargv as appropriate */
1467     /* user format strings look as follows:
1468      *
1469      * %% is a literal %
1470      * \X, where X is any character = \X, (this is the escape you'd expect, but
1471      *        we are leaving the \ for an expected final pass which splits our
1472      *        output string into separate arguments
1473      *
1474      * %X means sub var "X" into location
1475      * %{VWXYZ} means sub V,W,X,Y,Z into location as a single arg.  The shell
1476      *        || would be to quote the comma separated arguments.  Each list
1477      *        that V, W, X, Y, and Z represent attributes of will cause a new
1478      *        tuple to be inserted for each list item with a space between
1479      *        items.
1480      *        e.g."V W1,X1,Z1 W2,X2,Z2 W3,X3,Z3 Y1 Y2" where V is not a list
1481      *        variable, W,X,&Z are attributes of a list with 3 items and Y is an
1482      *        attribute of a second list with 2 items.
1483      * %,{VWXYZ} means to separate the args.  The previous example would produce
1484      *        V W1 X1 Z1 W2 X2 Z2 W3 X3 Z3 Y1 Y2, where each variable is now a
1485      *        separate, space delimited, arguments within a single argument.
1486      * a%{XY}, where 'a' is a literal, still produces a single arg (a"X Y", in
1487      *        shell)
1488      * a%1{XY}, where 'a' is a literal, splits the literal as it produces
1489      *        multiple args (a X Y).  The rule is that each sub will produce a
1490      *        separate arg.  Without a comma, attributes will still be grouped
1491      *        together & comma separated in what could be a single argument,
1492      *        but internal quotes, commas, and spaces are not excaped.
1493      *
1494      * clearing the variable oldway, passed into this function, causes the
1495      * behavior of '1' and "," in the format string to reverse.
1496      */
1497
1498     /* for convenience, use fmt as a temporary key buffer.
1499      * for speed, attempt to realloc it as little as possible
1500      */
1501     fmt = NULL;
1502     flen = 0;
1503     
1504     /* buf = current argv entry being built
1505      * length = current length of buf
1506      * s = next char in source buffer to read
1507      * d = next char location to write (in buf)
1508      * inquotes = current quote char or NUL
1509      */
1510     s = format;
1511     d = buf = NULL;
1512     length = 0;
1513     doff = d - buf;
1514     expand_string (&buf, &length, doff + 1);
1515     d = buf + doff;
1516
1517     inquotes = '\0';
1518 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1519     subbedsomething = 0;
1520 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1521     while ((*d++ = *s) != '\0')
1522     {
1523         int list = 0;
1524         switch (*s++)
1525         {
1526             case '\\':
1527                 /* the character after a \ goes unprocessed but leave the \ in
1528                  * the string so the function that splits this string into a
1529                  * command line later can deal with quotes properly
1530                  *
1531                  * ignore a NUL
1532                  */
1533                 if (*s)
1534                 {
1535                     doff = d - buf;
1536                     expand_string (&buf, &length, doff + 1);
1537                     d = buf + doff;
1538                     *d++ = *s++;
1539                 }
1540                 break;
1541             case '\'':
1542             case '"':
1543                 /* keep track of quotes so we can escape quote chars we sub in
1544                  * - the API is that a quoted format string will guarantee that
1545                  * it gets passed into the command as a single arg
1546                  */
1547                 if (!inquotes) inquotes = s[-1];
1548                 else if (s[-1] == inquotes) inquotes = '\0';
1549                 break;
1550             case '%':
1551                 if (*s == '%')
1552                 {
1553                     /* "%%" is a literal "%" */
1554                     s++;
1555                     break;
1556                 }
1557 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1558                 if (oldway && subbedsomething)
1559                 {
1560                     /* the old method was to sub only the first format string */
1561                     break;
1562                 }
1563                 /* initialize onearg each time we get a new format string */
1564                 onearg = oldway ? 1 : 0;
1565                 subbedsomething = 1;
1566 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1567                 d--;    /* we're going to overwrite the '%' regardless
1568                          * of other factors... */
1569 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1570                 /* detect '1' && ',' in the fmt string. */
1571                 if (*s == '1')
1572                 {
1573                     onearg = 1;
1574                     s++;
1575                     if (!oldway)
1576                     {
1577                         /* FIXME - add FILE && LINE */
1578                         error (0, 0,
1579 "Using deprecated info format strings.  Convert your scripts to use\n"
1580 "the new argument format and remove '1's from your info file format strings.");
1581                     }
1582                 }
1583 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1584                     
1585                 /* parse the format string and sub in... */
1586                 if (*s == '{')
1587                 {
1588                     list = 1;
1589                     s++;
1590                 }
1591                 /* q = fmt start
1592                  * r = fmt end + 1
1593                  */
1594                 q = fmt;
1595                 do
1596                 {
1597                     qoff = q - fmt;
1598                     expand_string (&fmt, &flen, qoff + 1);
1599                     q = fmt + qoff;
1600                 } while ((*q = *s++) && list && *q++ != '}');
1601                 /* we will always copy one character, so, whether in list mode
1602                  * or not, if we just copied a '\0', then we hit the end of the
1603                  * string before we should have
1604                  */
1605                 if (!s[-1])
1606                 {
1607                     /* if we copied a NUL while processing a list, fail
1608                      * - we had an empty fmt string or didn't find a list
1609                      * terminator ('}')
1610                      */
1611                     /* FIXME - this wants a file name and line number in a bad
1612                      * way.
1613                      */
1614                     error(1, 0,
1615 "unterminated format string encountered in command spec.\n"
1616 "This error is likely to have been caused by an invalid line in a hook script\n"
1617 "spec (see taginfo, loginfo, verifymsginfo, etc. in the Cederqvist).  Most\n"
1618 "likely the offending line would end with a '%%' character or contain a string\n"
1619 "beginning \"%%{\" and no closing '}' before the end of the line.");
1620                 }
1621                 if (list)
1622                 {
1623                     q[-1] = '\0';
1624                 }
1625                 else
1626                 {
1627                     /* We're not in a list, so we must have just copied a
1628                      * single character.  Terminate the string.
1629                      */
1630                     q++;
1631                     qoff = q - fmt;
1632                     expand_string (&fmt, &flen, qoff + 1);
1633                     q = fmt + qoff;
1634                     *q = '\0';
1635                 }
1636                 /* fmt is now a pointer to a list of fmt chars, though the list
1637                  * could be a single element one
1638                  */
1639                 q = fmt;
1640 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1641                 /* always add quotes in the deprecated onearg case - for
1642                  * backwards compatibility
1643                  */
1644                 if (onearg)
1645                 {
1646                     doff = d - buf;
1647                     expand_string (&buf, &length, doff + 1);
1648                     d = buf + doff;
1649                     *d++ = '"';
1650                 }
1651 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1652                 /*
1653                  * for each character in the fmt string,
1654                  *
1655                  * all output will be separate quoted arguments (with
1656                  * internal quotes escaped) if the argument is in quotes
1657                  * unless the oldway variable is set, in which case the fmt
1658                  * statment will correspond to a single argument with
1659                  * internal space or comma delimited arguments
1660                  *
1661                  * see the "user format strings" section above for more info
1662                  */
1663                 key[0] = *q;
1664                 if ((p = findnode (pflist, key)) != NULL)
1665                 {
1666                     b = p->data;
1667                     if (b->conversion == ',')
1668                     {
1669                         /* process the rest of the format string as a list */
1670                         struct format_cmdline_walklist_closure c;
1671                         c.format = q;
1672                         c.buf = &buf;
1673                         c.length = &length;
1674                         c.d = &d;
1675                         c.quotes = inquotes;
1676                         c.closure = b->closure;
1677 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1678                         c.onearg = onearg;
1679                         c.firstpass = 1;
1680                         c.srepos = srepos;
1681 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1682                         walklist(b->data, b->convproc, &c);
1683                         d--;    /* back up one space.  we know that ^
1684                                    always adds 1 extra */
1685                         q += strlen(q);
1686                     }
1687                     else
1688                     {
1689                         /* got a flat item */
1690                         char *outstr;
1691                         if (strlen(q) > 1)
1692                         {
1693                             error (1, 0,
1694 "Multiple non-list variables are not allowed in a single format string.");
1695                         }
1696 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1697                         if (onearg)
1698                         {
1699                             outstr = b->data;
1700                         }
1701                         else /* !onearg */
1702                         {
1703 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1704                             /* the *only* case possible without
1705                              * SUPPORT_OLD_INFO_FORMAT_STRINGS
1706                              * - !onearg */
1707                             if (!inquotes)
1708                             {
1709                                 doff = d - buf;
1710                                 expand_string (&buf, &length, doff + 1);
1711                                 d = buf + doff;
1712                                 *d++ = '"';
1713                             }
1714                             outstr = cmdlineescape (inquotes ? inquotes : '"', b->data);
1715 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1716                         } /* onearg */
1717 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1718                         doff = d - buf;
1719                         expand_string (&buf, &length, doff + strlen(outstr));
1720                         d = buf + doff;
1721                         strncpy(d, outstr, strlen(outstr));
1722                         d += strlen(outstr);
1723 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1724                         if (!onearg)
1725                         {
1726                             free(outstr);
1727 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1728                             if (!inquotes)
1729                             {
1730                                 doff = d - buf;
1731                                 expand_string (&buf, &length, doff + 1);
1732                                 d = buf + doff;
1733                                 *d++ = '"';
1734                             }
1735 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1736                         }
1737 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1738                         q++;
1739                     }
1740                 }
1741 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1742                 else if (onearg)
1743                 {
1744                     /* the old standard was to ignore unknown format
1745                      * characters (print the empty string), but also that
1746                      * any format character meant print srepos first
1747                      */
1748                     q++;
1749                     doff = d - buf;
1750                     expand_string (&buf, &length, doff + strlen(srepos));
1751                     d = buf + doff;
1752                     strncpy(d, srepos, strlen(srepos));
1753                     d += strlen(srepos);
1754                 }
1755 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1756                 else /* no key */
1757                 {
1758                     /* print an error message to the user
1759                      * FIXME - this should have a file and line number!!! */
1760                     error (1, 0,
1761 "Unknown format character in info file ('%s').\n"
1762 "Info files are the hook files, verifymsg, taginfo, commitinfo, etc.",
1763                            q);
1764                 }
1765 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1766                 /* always add quotes in the deprecated onearg case - for
1767                  * backwards compatibility
1768                  */
1769                 if (onearg)
1770                 {
1771                     doff = d - buf;
1772                     expand_string (&buf, &length, doff + 1);
1773                     d = buf + doff;
1774                     *d++ = '"';
1775                 }
1776 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1777                 break;
1778         }
1779         doff = d - buf;
1780         expand_string (&buf, &length, doff + 1);
1781         d = buf + doff;
1782     } /* while (*d++ = *s) */
1783     if (fmt) free (fmt);
1784     if (inquotes)
1785     {
1786         /* FIXME - we shouldn't need this - Parse_Info should be handling
1787          * multiple lines...
1788          */
1789         error (1, 0, "unterminated quote in format string: %s", format);
1790     }
1791
1792     dellist (&pflist);
1793     return buf;
1794 }
1795
1796
1797
1798 /* Like xstrdup (), but can handle a NULL argument.
1799  */
1800 char *
1801 Xstrdup (const char *string)
1802 {
1803   if (string == NULL) return NULL;
1804   return xmemdup (string, strlen (string) + 1);
1805 }
1806
1807
1808
1809 /* Like xasprintf(), but consider all errors fatal (may never return NULL).
1810  */
1811 char *
1812 Xasprintf (const char *format, ...)
1813 {
1814     va_list args;
1815     char *result;
1816
1817     va_start (args, format);
1818     if (vasprintf (&result, format, args) < 0)
1819         error (1, errno, "Failed to write to string.");
1820     va_end (args);
1821
1822     return result;
1823 }
1824
1825
1826
1827 /* Like xasnprintf(), but consider all errors fatal (may never return NULL).
1828  */
1829 char *
1830 Xasnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
1831 {
1832     va_list args;
1833     char *result;
1834
1835     va_start (args, format);
1836     result = vasnprintf (resultbuf, lengthp, format, args);
1837     if (result == NULL)
1838         error (1, errno, "Failed to write to string.");
1839     va_end (args);
1840
1841     return result;
1842 }
1843
1844
1845
1846 /* Print a warning and return false if P doesn't look like a string specifying
1847  * a boolean value.
1848  *
1849  * Sets *VAL to the parsed value when it is found to be valid.  *VAL will not
1850  * be altered when false is returned.
1851  *
1852  * INPUTS
1853  *   infopath   Where the error is reported to be from on error.  This could
1854  *              be, for example, the name of the file the boolean is being read
1855  *              from.
1856  *   option     An option name being parsed, reported in traces and any error
1857  *              message.
1858  *   p          The string to actually read the option from.
1859  *   val        Pointer to where to store the boolean read from P.
1860  *
1861  * OUTPUTS
1862  *   val        TRUE/FALSE stored, as read, when there are no errors.
1863  *
1864  * RETURNS
1865  *   true       If VAL was read.
1866  *   false      On error.
1867  */
1868 bool
1869 readBool (const char *infopath, const char *option, const char *p, bool *val)
1870 {
1871     TRACE (TRACE_FLOW, "readBool (%s, %s, %s)", infopath, option, p);
1872     if (!strcasecmp (p, "no") || !strcasecmp (p, "false")
1873         || !strcasecmp (p, "off") || !strcmp (p, "0"))
1874     {
1875         TRACE (TRACE_DATA, "Read %d for %s", *val, option);
1876         *val = false;
1877         return true;
1878     }
1879     else if (!strcasecmp (p, "yes") || !strcasecmp (p, "true")
1880              || !strcasecmp (p, "on") || !strcmp (p, "1"))
1881     {
1882         TRACE (TRACE_DATA, "Read %d for %s", *val, option);
1883         *val = true;
1884         return true;
1885     }
1886
1887     error (0, 0, "%s: unrecognized value `%s' for `%s'",
1888            infopath, p, option);
1889     return false;
1890 }
1891
1892
1893
1894 /*
1895  * Open a file, exiting with a message on error.
1896  *
1897  * INPUTS
1898  *   name       The name of the file to open.
1899  *   mode       Mode to open file in, as POSIX fopen().
1900  *
1901  * NOTES
1902  *   If you want to handle errors, just call fopen (NAME, MODE).
1903  *
1904  * RETURNS
1905  *   The new FILE pointer.
1906  */
1907 FILE *
1908 xfopen (const char *name, const char *mode)
1909 {
1910     FILE *fp;
1911
1912     if (!(fp = fopen (name, mode)))
1913         error (1, errno, "cannot open %s", name);
1914     return fp;
1915 }
1916
1917
1918
1919 /* char *
1920  * xcanonicalize_file_name (const char *path)
1921  *
1922  * Like canonicalize_file_name(), but exit on error.
1923  *
1924  * INPUTS
1925  *  path        The original path.
1926  *
1927  * RETURNS
1928  *  The path with any symbolic links, `.'s, or `..'s, expanded.
1929  *
1930  * ERRORS
1931  *  This function exits with a fatal error if it fails to read the link for
1932  *  any reason.
1933  */
1934 char *
1935 xcanonicalize_file_name (const char *path)
1936 {
1937     char *hardpath = canonicalize_file_name (path);
1938     if (!hardpath)
1939         error (1, errno, "Failed to resolve path: `%s'", path);
1940     return hardpath;
1941 }
1942
1943
1944
1945 /* Declared in main.c.  */
1946 extern char *server_hostname;
1947
1948 /* Return true if OTHERHOST resolves to this host in the DNS.
1949  *
1950  * GLOBALS
1951  *   server_hostname    The name of this host, as determined by the call to
1952  *                      xgethostname() in main().
1953  *
1954  * RETURNS
1955  *   true       If OTHERHOST equals or resolves to HOSTNAME.
1956  *   false      Otherwise.
1957  */
1958 bool
1959 isThisHost (const char *otherhost)
1960 {
1961     char *fqdno;
1962     char *fqdns;
1963     bool retval;
1964
1965     /* As an optimization, check the literal strings before looking up
1966      * OTHERHOST in the DNS.
1967      */
1968     if (!strcasecmp (server_hostname, otherhost))
1969         return true;
1970
1971     fqdno = canon_host (otherhost);
1972     if (!fqdno)
1973         error (1, 0, "Name lookup failed for `%s': %s",
1974                otherhost, ch_strerror ());
1975     fqdns = canon_host (server_hostname);
1976     if (!fqdns)
1977         error (1, 0, "Name lookup failed for `%s': %s",
1978                server_hostname, ch_strerror ());
1979
1980     retval = !strcasecmp (fqdns, fqdno);
1981
1982     free (fqdno);
1983     free (fqdns);
1984     return retval;
1985 }
1986
1987
1988
1989 /* Return true if two paths match, resolving symlinks.
1990  */
1991 bool
1992 isSamePath (const char *path1_in, const char *path2_in)
1993 {
1994     char *p1, *p2;
1995     bool same;
1996
1997     if (!strcmp (path1_in, path2_in))
1998         return true;
1999
2000     /* Path didn't match, but try to resolve any links that may be
2001      * present.
2002      */
2003     if (!isdir (path1_in) || !isdir (path2_in))
2004         /* To be resolvable, paths must exist on this server.  */
2005         return false;
2006
2007     p1 = xcanonicalize_file_name (path1_in);
2008     p2 = xcanonicalize_file_name (path2_in);
2009     if (strcmp (p1, p2))
2010         same = false;
2011     else
2012         same = true;
2013
2014     free (p1);
2015     free (p2);
2016     return same;
2017 }