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