xref: /dragonfly/contrib/cvs-1.12/src/subr.c (revision 9348a738)
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     while (time (&t) <= desttime)
811     {
812 #ifdef HAVE_GETTIMEOFDAY
813 	struct timeval tv;
814 	gettimeofday (&tv, NULL);
815 	if (tv.tv_sec > desttime)
816 	    break;
817 	s = desttime - tv.tv_sec;
818 	if (tv.tv_usec > 0)
819 	    us = 1000000 - tv.tv_usec;
820 	else
821 	{
822 	    s++;
823 	    us = 0;
824 	}
825 #else
826 	/* default to 20 ms increments */
827 	s = desttime - t;
828 	us = 20000;
829 #endif
830 
831 	{
832 	    struct timespec ts;
833 	    ts.tv_sec = s;
834 	    ts.tv_nsec = us * 1000;
835 	    (void)nanosleep (&ts, NULL);
836 	}
837     }
838 }
839 
840 
841 
842 /* used to store callback data in a list indexed by the user format string
843  */
844 typedef int (*CONVPROC_t) (Node *, void *);
845 struct cmdline_bindings
846 {
847     char conversion;
848     void *data;
849     CONVPROC_t convproc;
850     void *closure;
851 };
852 /* since we store the above in a list, we need to dispose of the data field.
853  * we don't have to worry about convproc or closure since pointers are stuck
854  * in there directly and format_cmdline's caller is responsible for disposing
855  * of those if necessary.
856  */
857 static void
858 cmdline_bindings_hash_node_delete (Node *p)
859 {
860     struct cmdline_bindings *b = p->data;
861 
862     if (b->conversion != ',')
863     {
864 	free (b->data);
865     }
866     free (b);
867 }
868 
869 
870 
871 /*
872  * assume s is a literal argument and put it between quotes,
873  * escaping as appropriate for a shell command line
874  *
875  * the caller is responsible for disposing of the new string
876  */
877 char *
878 cmdlinequote (char quotes, char *s)
879 {
880     char *quoted = cmdlineescape (quotes, s);
881     char *buf = Xasprintf ("%c%s%c", quotes, quoted, quotes);
882 
883     free (quoted);
884     return buf;
885 }
886 
887 
888 
889 /* read quotes as the type of quotes we are between (if any) and then make our
890  * argument so it could make it past a cmdline parser (using sh as a model)
891  * inside the quotes (if any).
892  *
893  * if you were planning on expanding any paths, it should be done before
894  * calling this function, as it escapes shell metacharacters.
895  *
896  * the caller is responsible for disposing of the new string
897  *
898  * FIXME: See about removing/combining this functionality with shell_escape()
899  * in subr.c.
900  */
901 char *
902 cmdlineescape (char quotes, char *s)
903 {
904     char *buf = NULL;
905     size_t length = 0;
906     char *d = NULL;
907     size_t doff;
908     char *lastspace;
909 
910     lastspace = s - 1;
911     do
912     {
913 	/* FIXME: Single quotes only require other single quotes to be escaped
914 	 * for Bourne Shell.
915 	 */
916 	if ( isspace( *s ) ) lastspace = s;
917 	if( quotes
918 	    ? ( *s == quotes
919 	        || ( quotes == '"'
920 	             && ( *s == '$' || *s == '`' || *s == '\\' ) ) )
921 	    : ( strchr( "\\$`'\"*?", *s )
922 	        || isspace( *s )
923 	        || ( lastspace == ( s - 1 )
924 	             && *s == '~' ) ) )
925 	{
926 	    doff = d - buf;
927 	    expand_string (&buf, &length, doff + 1);
928 	    d = buf + doff;
929 	    *d++ = '\\';
930 	}
931 	doff = d - buf;
932 	expand_string (&buf, &length, doff + 1);
933 	d = buf + doff;
934     } while ((*d++ = *s++) != '\0');
935     return (buf);
936 }
937 
938 
939 
940 /* expand format strings in a command line.  modeled roughly after printf
941  *
942  * this function's arg list must be NULL terminated
943  *
944  * assume a space delimited list of args is the desired final output,
945  * but args can be quoted (" or ').
946  *
947  * the best usage examples are in tag.c & logmsg.c, but here goes:
948  *
949  * INPUTS
950  *    int oldway	to support old format strings
951  *    char *srepos	you guessed it
952  *    char *format	the format string to parse
953  *    ...		NULL terminated data list in the following format:
954  *    			char *userformat, char *printfformat, <type> data
955  *    			    where
956  *    				char *userformat	a list of possible
957  *    							format characters the
958  *    							end user might pass us
959  *    							in the format string
960  *    							(e.g. those found in
961  *    							taginfo or loginfo)
962  *    							multiple characters in
963  *    							this strings will be
964  *    							aliases for each other
965  *    				char *printfformat	the same list of args
966  *    							printf uses to
967  *    							determine what kind of
968  *    							data the next arg will
969  *    							be
970  *    				<type> data		a piece of data to be
971  *    							formatted into the user
972  *    							string, <type>
973  *    							determined by the
974  *    							printfformat string.
975  *    		or
976  *    			char *userformat, char *printfformat, List *data,
977  *    				int (*convproc) (Node *, void *), void *closure
978  *    			    where
979  *    				char *userformat	same as above, except
980  *    							multiple characters in
981  *    							this string represent
982  *    							different node
983  *    							attributes which can be
984  *    							retrieved from data by
985  *    							convproc
986  *    				char *printfformat	= ","
987  *				List *data		the list to be walked
988  *							with walklist &
989  *							convproc to retrieve
990  *							data for each of the
991  *							possible format
992  *							characters in
993  *							userformat
994  *				int (*convproc)()	see data
995  *				void *closure		arg to be passed into
996  *							walklist as closure
997  *							data for convproc
998  *
999  * EXAMPLE
1000  *    (ignoring oldway variable and srepos since those are only around while we
1001  *    SUPPORT_OLD_INFO_FMT_STRINGS)
1002  *    format_cmdline ("/cvsroot/CVSROOT/mytaginfoproc %t %o %{sVv}",
1003  *                    "t", "s", "newtag",
1004  *                    "o", "s", "mov",
1005  *                    "xG", "ld", longintwhichwontbeusedthispass,
1006  *                    "sVv", ",", tlist, pretag_list_to_args_proc,
1007  *                    (void *) mydata,
1008  *                    (char *) NULL);
1009  *
1010  *    would generate the following command line, assuming two files in tlist,
1011  *    file1 & file2, each with old versions 1.1 and new version 1.1.2.3:
1012  *
1013  *    	  /cvsroot/CVSROOT/mytaginfoproc "newtag" "mov" "file1" "1.1" "1.1.2.3" "file2" "1.1" "1.1.2.3"
1014  *
1015  * RETURNS
1016  *    pointer to newly allocated string.  the caller is responsible for
1017  *    disposing of this string.
1018  */
1019 char *
1020 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1021 format_cmdline (bool oldway, const char *srepos, const char *format, ...)
1022 #else /* SUPPORT_OLD_INFO_FMT_STRINGS */
1023 format_cmdline (const char *format, ...)
1024 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1025 {
1026     va_list args;	/* our input function args */
1027     char *buf;		/* where we store our output string */
1028     size_t length;	/* the allocated length of our output string in bytes.
1029 			 * used as a temporary storage for the length of the
1030 			 * next function argument during function
1031 			 * initialization
1032 			 */
1033     char *pfmt;		/* initially the list of fmt keys passed in,
1034 			 * but used as a temporary key buffer later
1035 			 */
1036     char *fmt;		/* buffer for format string which we are processing */
1037     size_t flen;	/* length of fmt buffer */
1038     char *d, *q, *r;    /* for walking strings */
1039     const char *s;
1040     size_t doff, qoff;
1041     char inquotes;
1042 
1043     List *pflist = getlist();	/* our list of input data indexed by format
1044 				 * "strings"
1045 				 */
1046     Node *p;
1047     struct cmdline_bindings *b;
1048     static int warned_of_deprecation = 0;
1049     char key[] = "?";		/* Used as temporary storage for a single
1050 				 * character search string used to locate a
1051 				 * hash key.
1052 				 */
1053 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1054     /* state varialbes in the while loop which parses the actual
1055      * format string in the final parsing pass*/
1056     int onearg;
1057     int subbedsomething;
1058 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1059 
1060 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1061     if (oldway && !warned_of_deprecation)
1062     {
1063 	/* warn the user that we don't like his kind 'round these parts */
1064 	warned_of_deprecation = 1;
1065 	error (0, 0,
1066 "warning:  Set to use deprecated info format strings.  Establish\n"
1067 "compatibility with the new info file format strings (add a temporary '1' in\n"
1068 "all info files after each '%%' which doesn't represent a literal percent)\n"
1069 "and set UseNewInfoFmtStrings=yes in CVSROOT/config.  After that, convert\n"
1070 "individual command lines and scripts to handle the new format at your\n"
1071 "leisure.");
1072     }
1073 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1074 
1075     va_start (args, format);
1076 
1077     /* read our possible format strings
1078      * expect a certain number of arguments by type and a NULL format
1079      * string to terminate the list.
1080      */
1081     while ((pfmt = va_arg (args, char *)) != NULL)
1082     {
1083 	char *conversion = va_arg (args, char *);
1084 
1085 	char conversion_error = 0;
1086 	char char_conversion = 0;
1087 	char decimal_conversion = 0;
1088 	char integer_conversion = 0;
1089 	char string_conversion = 0;
1090 
1091 	/* allocate space to save our data */
1092 	b = xmalloc(sizeof(struct cmdline_bindings));
1093 
1094 	/* where did you think we were going to store all this data??? */
1095 	b->convproc = NULL;
1096 	b->closure = NULL;
1097 
1098 	/* read a length from the conversion string */
1099 	s = conversion;
1100 	length = 0;
1101 	while (!length && *s)
1102 	{
1103 	    switch (*s)
1104 	    {
1105 		case 'h':
1106 		    integer_conversion = 1;
1107 		    if (s[1] == 'h')
1108 		    {
1109 			length = sizeof (char);
1110 			s += 2;
1111 		    }
1112 		    else
1113 		    {
1114 			char_conversion = 1;
1115 			length = sizeof (short);
1116 			s++;
1117 		    }
1118 		    break;
1119 #ifdef HAVE_INTMAX_T
1120 		case 'j':
1121 		    integer_conversion = 1;
1122 		    length = sizeof (intmax_t);
1123 		    s++;
1124 		    break;
1125 #endif /* HAVE_INTMAX_T */
1126 		case 'l':
1127 		    integer_conversion = 1;
1128 		    if (s[1] == 'l')
1129 		    {
1130 #ifdef HAVE_LONG_LONG
1131 			length = sizeof (long long);
1132 #endif
1133 			s += 2;
1134 		    }
1135 		    else
1136 		    {
1137 			char_conversion = 2;
1138 			string_conversion = 2;
1139 			length = sizeof (long);
1140 			s++;
1141 		    }
1142 		    break;
1143 		case 't':
1144 		    integer_conversion = 1;
1145 		    length = sizeof (ptrdiff_t);
1146 		    s++;
1147 		    break;
1148 		case 'z':
1149 		    integer_conversion = 1;
1150 		    length = sizeof (size_t);
1151 		    s++;
1152 		    break;
1153 #ifdef HAVE_LONG_DOUBLE
1154 		case 'L':
1155 		    decimal_conversion = 1;
1156 		    length = sizeof (long double);
1157 		    s++;
1158 		    break;
1159 #endif
1160 		default:
1161 		    char_conversion = 1;
1162 		    decimal_conversion = 1;
1163 		    integer_conversion = 1;
1164 		    string_conversion = 1;
1165 		    /* take care of it when we find out what we're looking for */
1166 		    length = -1;
1167 		    break;
1168 	    }
1169 	}
1170 	/* if we don't have a valid conversion left, that is an error */
1171 	/* read an argument conversion */
1172 	buf = xmalloc (strlen(conversion) + 2);
1173 	*buf = '%';
1174 	strcpy (buf+1, conversion);
1175 	switch (*s)
1176 	{
1177 	    case 'c':
1178 		/* chars (an integer conversion) */
1179 		if (!char_conversion)
1180 		{
1181 		    conversion_error = 1;
1182 		    break;
1183 		}
1184 		if (char_conversion == 2)
1185 		{
1186 #ifdef HAVE_WINT_T
1187 		    length = sizeof (wint_t);
1188 #else
1189 		    conversion_error = 1;
1190 		    break;
1191 #endif
1192 		}
1193 		else
1194 		    length = sizeof (char);
1195 		/* fall through... */
1196 	    case 'd':
1197 	    case 'i':
1198 	    case 'o':
1199 	    case 'u':
1200 	    case 'x':
1201 	    case 'X':
1202 		/* integer conversions */
1203 		if (!integer_conversion)
1204 		{
1205 		    conversion_error = 1;
1206 		    break;
1207 		}
1208 		if (length == -1)
1209 		{
1210 		    length = sizeof (int);
1211 		}
1212 		switch (length)
1213 		{
1214 		    case sizeof(char):
1215 		    {
1216 		    	char arg_char = (char) va_arg (args, int);
1217 			b->data = Xasprintf (buf, arg_char);
1218 			break;
1219 		    }
1220 #ifdef UNIQUE_INT_TYPE_WINT_T		/* implies HAVE_WINT_T */
1221 		    case sizeof(wint_t):
1222 		    {
1223 		    	wint_t arg_wint_t = va_arg (args, wint_t);
1224 			b->data = Xasprintf (buf, arg_wint_t);
1225 			break;
1226 		    }
1227 #endif /* UNIQUE_INT_TYPE_WINT_T */
1228 #ifdef UNIQUE_INT_TYPE_SHORT
1229 		    case sizeof(short):
1230 		    {
1231 		    	short arg_short = (short) va_arg (args, int);
1232 			b->data = Xasprintf (buf, arg_short);
1233 			break;
1234 		    }
1235 #endif /* UNIQUE_INT_TYPE_SHORT */
1236 #ifdef UNIQUE_INT_TYPE_INT
1237 		    case sizeof(int):
1238 		    {
1239 		    	int arg_int = va_arg (args, int);
1240 			b->data = Xasprintf(buf, arg_int);
1241 			break;
1242 		    }
1243 #endif /* UNIQUE_INT_TYPE_INT */
1244 #ifdef UNIQUE_INT_TYPE_LONG
1245 		    case sizeof(long):
1246 		    {
1247 		    	long arg_long = va_arg (args, long);
1248 			b->data = Xasprintf (buf, arg_long);
1249 			break;
1250 		    }
1251 #endif /* UNIQUE_INT_TYPE_LONG */
1252 #ifdef UNIQUE_INT_TYPE_LONG_LONG	/* implies HAVE_LONG_LONG */
1253 		    case sizeof(long long):
1254 		    {
1255 		    	long long arg_long_long = va_arg (args, long long);
1256 			b->data = Xasprintf (buf, arg_long_long);
1257 			break;
1258 		    }
1259 #endif /* UNIQUE_INT_TYPE_LONG_LONG */
1260 #ifdef UNIQUE_INT_TYPE_INTMAX_T		/* implies HAVE_INTMAX_T */
1261 		    case sizeof(intmax_t):
1262 		    {
1263 		    	intmax_t arg_intmax_t = va_arg (args, intmax_t);
1264 			b->data = Xasprintf (buf, arg_intmax_t);
1265 			break;
1266 		    }
1267 #endif /* UNIQUE_INT_TYPE_INTMAX_T */
1268 #ifdef UNIQUE_INT_TYPE_SIZE_T
1269 		    case sizeof(size_t):
1270 		    {
1271 		    	size_t arg_size_t = va_arg (args, size_t);
1272 			b->data = Xasprintf (buf, arg_size_t);
1273 			break;
1274 		    }
1275 #endif /* UNIQUE_INT_TYPE_SIZE_T */
1276 #ifdef UNIQUE_INT_TYPE_PTRDIFF_T
1277 		    case sizeof(ptrdiff_t):
1278 		    {
1279 		    	ptrdiff_t arg_ptrdiff_t = va_arg (args, ptrdiff_t);
1280 			b->data = Xasprintf (buf, arg_ptrdiff_t);
1281 			break;
1282 		    }
1283 #endif /* UNIQUE_INT_TYPE_PTRDIFF_T */
1284 		    default:
1285 	    		dellist(&pflist);
1286 	    		free(b);
1287 			error (1, 0,
1288 "internal error:  unknown integer arg size (%d)",
1289                                length);
1290 			break;
1291 		}
1292 		break;
1293 	    case 'a':
1294 	    case 'A':
1295 	    case 'e':
1296 	    case 'E':
1297 	    case 'f':
1298 	    case 'F':
1299 	    case 'g':
1300 	    case 'G':
1301 		/* decimal conversions */
1302 		if (!decimal_conversion)
1303 		{
1304 		    conversion_error = 1;
1305 		    break;
1306 		}
1307 		if (length == -1)
1308 		{
1309 		    length = sizeof (double);
1310 		}
1311 		switch (length)
1312 		{
1313 		    case sizeof(double):
1314 		    {
1315 		    	double arg_double = va_arg (args, double);
1316 			b->data = Xasprintf (buf, arg_double);
1317 			break;
1318 		    }
1319 #ifdef UNIQUE_FLOAT_TYPE_LONG_DOUBLE	/* implies HAVE_LONG_DOUBLE */
1320 		    case sizeof(long double):
1321 		    {
1322 		    	long double arg_long_double = va_arg (args, long double);
1323 			b->data = Xasprintf (buf, arg_long_double);
1324 			break;
1325 		    }
1326 #endif /* UNIQUE_FLOAT_TYPE_LONG_DOUBLE */
1327 		    default:
1328 	    		dellist(&pflist);
1329 	    		free(b);
1330 			error (1, 0,
1331 "internal error:  unknown floating point arg size (%d)",
1332                                length);
1333 			break;
1334 		}
1335 		break;
1336 	    case 's':
1337 		switch (string_conversion)
1338 		{
1339 		    case 1:
1340 			b->data = xstrdup (va_arg (args, char *));
1341 			break;
1342 #ifdef HAVE_WCHAR_T
1343 		    case 2:
1344 		    {
1345 		    	wchar_t *arg_wchar_t_string = va_arg (args, wchar_t *);
1346 			b->data = Xasprintf (buf, arg_wchar_t_string);
1347 			break;
1348 		    }
1349 #endif /* HAVE_WCHAR_T */
1350 		    default:
1351 			conversion_error = 1;
1352 			break;
1353 		}
1354 		break;
1355 	    case ',':
1356 		if (length != -1)
1357 		{
1358 		    conversion_error = 1;
1359 		    break;
1360 		}
1361 		b->data = va_arg (args, List *);
1362 		b->convproc = va_arg (args, CONVPROC_t);
1363 		b->closure = va_arg (args, void *);
1364 		break;
1365 	    default:
1366 		conversion_error = 1;
1367 		break;
1368 	}
1369 	free (buf);
1370 	/* fail if we found an error or haven't found the end of the string */
1371 	if (conversion_error || s[1])
1372 	{
1373 	    error (1, 0,
1374 "internal error (format_cmdline): '%s' is not a valid conversion!!!",
1375                    conversion);
1376 	}
1377 
1378 
1379 	/* save our type  - we really only care wheter it's a list type (',')
1380 	 * or not from now on, but what the hell...
1381 	 */
1382 	b->conversion = *s;
1383 
1384 	/* separate the user format string into parts and stuff our data into
1385 	 * the pflist (once for each possible string - diverse keys can have
1386 	 * duplicate data).
1387 	 */
1388 	q = pfmt;
1389 	while (*q)
1390 	{
1391     	    struct cmdline_bindings *tb;
1392 	    if (*q == '{')
1393 	    {
1394 		s = q + 1;
1395 		while (*++q && *q != '}');
1396 		r = q + 1;
1397 	    }
1398 	    else
1399 	    {
1400 		s = q++;
1401 		r = q;
1402 	    }
1403 	    if (*r)
1404 	    {
1405 		/* copy the data since we'll need it again */
1406     	    	tb = xmalloc(sizeof(struct cmdline_bindings));
1407 		if (b->conversion == ',')
1408 		{
1409 		    tb->data = b->data;
1410 		}
1411 		else
1412 		{
1413 		    tb->data = xstrdup(b->data);
1414 		}
1415 		tb->conversion = b->conversion;
1416 		tb->convproc = b->convproc;
1417 		tb->closure = b->closure;
1418 	    }
1419 	    else
1420 	    {
1421 		/* we're done after this, so we don't need to copy the data */
1422 		tb = b;
1423 	    }
1424 	    p = getnode();
1425 	    p->key = xmalloc((q - s) + 1);
1426 	    strncpy (p->key, s, q - s);
1427 	    p->key[q-s] = '\0';
1428 	    p->data = tb;
1429 	    p->delproc = cmdline_bindings_hash_node_delete;
1430 	    addnode(pflist,p);
1431 	}
1432     }
1433 
1434     /* we're done with va_list */
1435     va_end(args);
1436 
1437     /* All formatted strings include a format character that resolves to the
1438      * empty string by default, so put it in pflist.
1439      */
1440     /* allocate space to save our data */
1441     b = xmalloc(sizeof(struct cmdline_bindings));
1442     b->conversion = 's';
1443     b->convproc = NULL;
1444     b->closure = NULL;
1445     b->data = xstrdup( "" );
1446     p = getnode();
1447     p->key = xstrdup( "n" );
1448     p->data = b;
1449     p->delproc = cmdline_bindings_hash_node_delete;
1450     addnode( pflist,p );
1451 
1452     /* finally, read the user string and copy it into rargv as appropriate */
1453     /* user format strings look as follows:
1454      *
1455      * %% is a literal %
1456      * \X, where X is any character = \X, (this is the escape you'd expect, but
1457      *        we are leaving the \ for an expected final pass which splits our
1458      *        output string into separate arguments
1459      *
1460      * %X means sub var "X" into location
1461      * %{VWXYZ} means sub V,W,X,Y,Z into location as a single arg.  The shell
1462      *        || would be to quote the comma separated arguments.  Each list
1463      *        that V, W, X, Y, and Z represent attributes of will cause a new
1464      *        tuple to be inserted for each list item with a space between
1465      *        items.
1466      *        e.g."V W1,X1,Z1 W2,X2,Z2 W3,X3,Z3 Y1 Y2" where V is not a list
1467      *        variable, W,X,&Z are attributes of a list with 3 items and Y is an
1468      *        attribute of a second list with 2 items.
1469      * %,{VWXYZ} means to separate the args.  The previous example would produce
1470      *        V W1 X1 Z1 W2 X2 Z2 W3 X3 Z3 Y1 Y2, where each variable is now a
1471      *        separate, space delimited, arguments within a single argument.
1472      * a%{XY}, where 'a' is a literal, still produces a single arg (a"X Y", in
1473      *        shell)
1474      * a%1{XY}, where 'a' is a literal, splits the literal as it produces
1475      *        multiple args (a X Y).  The rule is that each sub will produce a
1476      *        separate arg.  Without a comma, attributes will still be grouped
1477      *        together & comma separated in what could be a single argument,
1478      *        but internal quotes, commas, and spaces are not excaped.
1479      *
1480      * clearing the variable oldway, passed into this function, causes the
1481      * behavior of '1' and "," in the format string to reverse.
1482      */
1483 
1484     /* for convenience, use fmt as a temporary key buffer.
1485      * for speed, attempt to realloc it as little as possible
1486      */
1487     fmt = NULL;
1488     flen = 0;
1489 
1490     /* buf = current argv entry being built
1491      * length = current length of buf
1492      * s = next char in source buffer to read
1493      * d = next char location to write (in buf)
1494      * inquotes = current quote char or NUL
1495      */
1496     s = format;
1497     d = buf = NULL;
1498     length = 0;
1499     doff = d - buf;
1500     expand_string (&buf, &length, doff + 1);
1501     d = buf + doff;
1502 
1503     inquotes = '\0';
1504 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1505     subbedsomething = 0;
1506 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1507     while ((*d++ = *s) != '\0')
1508     {
1509 	int list = 0;
1510 	switch (*s++)
1511 	{
1512 	    case '\\':
1513 		/* the character after a \ goes unprocessed but leave the \ in
1514 		 * the string so the function that splits this string into a
1515 		 * command line later can deal with quotes properly
1516 		 *
1517 		 * ignore a NUL
1518 		 */
1519 		if (*s)
1520 		{
1521     		    doff = d - buf;
1522 		    expand_string (&buf, &length, doff + 1);
1523 		    d = buf + doff;
1524 		    *d++ = *s++;
1525 		}
1526 		break;
1527 	    case '\'':
1528 	    case '"':
1529 		/* keep track of quotes so we can escape quote chars we sub in
1530 		 * - the API is that a quoted format string will guarantee that
1531 		 * it gets passed into the command as a single arg
1532 		 */
1533 		if (!inquotes) inquotes = s[-1];
1534 		else if (s[-1] == inquotes) inquotes = '\0';
1535 		break;
1536 	    case '%':
1537 		if (*s == '%')
1538 		{
1539 		    /* "%%" is a literal "%" */
1540 		    s++;
1541 		    break;
1542 		}
1543 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1544 		if (oldway && subbedsomething)
1545 		{
1546 		    /* the old method was to sub only the first format string */
1547 		    break;
1548 		}
1549 		/* initialize onearg each time we get a new format string */
1550 		onearg = oldway ? 1 : 0;
1551 		subbedsomething = 1;
1552 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1553 		d--;	/* we're going to overwrite the '%' regardless
1554 			 * of other factors... */
1555 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1556 		/* detect '1' && ',' in the fmt string. */
1557 		if (*s == '1')
1558 		{
1559 		    onearg = 1;
1560 		    s++;
1561 		    if (!oldway)
1562 		    {
1563 			/* FIXME - add FILE && LINE */
1564 			error (0, 0,
1565 "Using deprecated info format strings.  Convert your scripts to use\n"
1566 "the new argument format and remove '1's from your info file format strings.");
1567 		    }
1568 		}
1569 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1570 
1571 		/* parse the format string and sub in... */
1572 		if (*s == '{')
1573 		{
1574 		    list = 1;
1575 		    s++;
1576 		}
1577 		/* q = fmt start
1578 		 * r = fmt end + 1
1579 		 */
1580 		q = fmt;
1581 		do
1582 		{
1583 		    qoff = q - fmt;
1584 		    expand_string (&fmt, &flen, qoff + 1);
1585 		    q = fmt + qoff;
1586 		} while ((*q = *s++) && list && *q++ != '}');
1587 		/* we will always copy one character, so, whether in list mode
1588 		 * or not, if we just copied a '\0', then we hit the end of the
1589 		 * string before we should have
1590 		 */
1591 		if (!s[-1])
1592 		{
1593 		    /* if we copied a NUL while processing a list, fail
1594 		     * - we had an empty fmt string or didn't find a list
1595 		     * terminator ('}')
1596 		     */
1597 		    /* FIXME - this wants a file name and line number in a bad
1598 		     * way.
1599 		     */
1600 		    error(1, 0,
1601 "unterminated format string encountered in command spec.\n"
1602 "This error is likely to have been caused by an invalid line in a hook script\n"
1603 "spec (see taginfo, loginfo, verifymsginfo, etc. in the Cederqvist).  Most\n"
1604 "likely the offending line would end with a '%%' character or contain a string\n"
1605 "beginning \"%%{\" and no closing '}' before the end of the line.");
1606 		}
1607 		if (list)
1608 		{
1609 		    q[-1] = '\0';
1610 		}
1611 		else
1612 		{
1613 		    /* We're not in a list, so we must have just copied a
1614 		     * single character.  Terminate the string.
1615 		     */
1616 		    q++;
1617 		    qoff = q - fmt;
1618 		    expand_string (&fmt, &flen, qoff + 1);
1619 		    q = fmt + qoff;
1620 		    *q = '\0';
1621 		}
1622 		/* fmt is now a pointer to a list of fmt chars, though the list
1623 		 * could be a single element one
1624 		 */
1625 		q = fmt;
1626 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1627 		/* always add quotes in the deprecated onearg case - for
1628 		 * backwards compatibility
1629 		 */
1630 		if (onearg)
1631 		{
1632 		    doff = d - buf;
1633 		    expand_string (&buf, &length, doff + 1);
1634 		    d = buf + doff;
1635 		    *d++ = '"';
1636 		}
1637 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1638 		/*
1639 		 * for each character in the fmt string,
1640 		 *
1641 		 * all output will be separate quoted arguments (with
1642 		 * internal quotes escaped) if the argument is in quotes
1643 		 * unless the oldway variable is set, in which case the fmt
1644 		 * statment will correspond to a single argument with
1645 		 * internal space or comma delimited arguments
1646 		 *
1647 		 * see the "user format strings" section above for more info
1648 		 */
1649 		key[0] = *q;
1650 		if ((p = findnode (pflist, key)) != NULL)
1651 		{
1652 		    b = p->data;
1653 		    if (b->conversion == ',')
1654 		    {
1655 			/* process the rest of the format string as a list */
1656 			struct format_cmdline_walklist_closure c;
1657 			c.format = q;
1658 			c.buf = &buf;
1659 			c.length = &length;
1660 			c.d = &d;
1661 			c.quotes = inquotes;
1662 			c.closure = b->closure;
1663 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1664 			c.onearg = onearg;
1665 			c.firstpass = 1;
1666 			c.srepos = srepos;
1667 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1668 			walklist(b->data, b->convproc, &c);
1669 			d--;	/* back up one space.  we know that ^
1670 				   always adds 1 extra */
1671 			q += strlen(q);
1672 		    }
1673 		    else
1674 		    {
1675 			/* got a flat item */
1676 			char *outstr;
1677 			if (strlen(q) > 1)
1678 			{
1679 			    error (1, 0,
1680 "Multiple non-list variables are not allowed in a single format string.");
1681 			}
1682 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1683 			if (onearg)
1684 			{
1685 			    outstr = b->data;
1686 			}
1687 			else /* !onearg */
1688 			{
1689 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1690 			    /* the *only* case possible without
1691 			     * SUPPORT_OLD_INFO_FORMAT_STRINGS
1692 			     * - !onearg */
1693 			    if (!inquotes)
1694 			    {
1695 				doff = d - buf;
1696 				expand_string (&buf, &length, doff + 1);
1697 				d = buf + doff;
1698 				*d++ = '"';
1699 			    }
1700 			    outstr = cmdlineescape (inquotes ? inquotes : '"', b->data);
1701 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1702 			} /* onearg */
1703 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1704 			doff = d - buf;
1705 			expand_string (&buf, &length, doff + strlen(outstr));
1706 			d = buf + doff;
1707 			strncpy(d, outstr, strlen(outstr));
1708 			d += strlen(outstr);
1709 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1710 			if (!onearg)
1711 			{
1712 			    free(outstr);
1713 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1714 			    if (!inquotes)
1715 			    {
1716 				doff = d - buf;
1717 				expand_string (&buf, &length, doff + 1);
1718 				d = buf + doff;
1719 				*d++ = '"';
1720 			    }
1721 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1722 			}
1723 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1724 			q++;
1725 		    }
1726 		}
1727 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1728 		else if (onearg)
1729 		{
1730 		    /* the old standard was to ignore unknown format
1731 		     * characters (print the empty string), but also that
1732 		     * any format character meant print srepos first
1733 		     */
1734 		    q++;
1735 		    doff = d - buf;
1736 		    expand_string (&buf, &length, doff + strlen(srepos));
1737 		    d = buf + doff;
1738 		    strncpy(d, srepos, strlen(srepos));
1739 		    d += strlen(srepos);
1740 		}
1741 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1742 		else /* no key */
1743 		{
1744 		    /* print an error message to the user
1745 		     * FIXME - this should have a file and line number!!! */
1746 		    error (1, 0,
1747 "Unknown format character in info file ('%s').\n"
1748 "Info files are the hook files, verifymsg, taginfo, commitinfo, etc.",
1749                            q);
1750 		}
1751 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1752 		/* always add quotes in the deprecated onearg case - for
1753 		 * backwards compatibility
1754 		 */
1755 		if (onearg)
1756 		{
1757 		    doff = d - buf;
1758 		    expand_string (&buf, &length, doff + 1);
1759 		    d = buf + doff;
1760 		    *d++ = '"';
1761 		}
1762 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1763 		break;
1764 	}
1765 	doff = d - buf;
1766 	expand_string (&buf, &length, doff + 1);
1767 	d = buf + doff;
1768     } /* while (*d++ = *s) */
1769     if (fmt) free (fmt);
1770     if (inquotes)
1771     {
1772 	/* FIXME - we shouldn't need this - Parse_Info should be handling
1773 	 * multiple lines...
1774 	 */
1775 	error (1, 0, "unterminated quote in format string: %s", format);
1776     }
1777 
1778     dellist (&pflist);
1779     return buf;
1780 }
1781 
1782 
1783 
1784 /* Like xstrdup (), but can handle a NULL argument.
1785  */
1786 char *
1787 Xstrdup (const char *string)
1788 {
1789   if (string == NULL) return NULL;
1790   return xmemdup (string, strlen (string) + 1);
1791 }
1792 
1793 
1794 
1795 /* Like xasprintf(), but consider all errors fatal (may never return NULL).
1796  */
1797 char *
1798 Xasprintf (const char *format, ...)
1799 {
1800     va_list args;
1801     char *result;
1802 
1803     va_start (args, format);
1804     if (vasprintf (&result, format, args) < 0)
1805 	error (1, errno, "Failed to write to string.");
1806     va_end (args);
1807 
1808     return result;
1809 }
1810 
1811 
1812 
1813 /* Like xasnprintf(), but consider all errors fatal (may never return NULL).
1814  */
1815 char *
1816 Xasnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
1817 {
1818     va_list args;
1819     char *result;
1820 
1821     va_start (args, format);
1822     result = vasnprintf (resultbuf, lengthp, format, args);
1823     if (result == NULL)
1824 	error (1, errno, "Failed to write to string.");
1825     va_end (args);
1826 
1827     return result;
1828 }
1829 
1830 
1831 
1832 /* Print a warning and return false if P doesn't look like a string specifying
1833  * a boolean value.
1834  *
1835  * Sets *VAL to the parsed value when it is found to be valid.  *VAL will not
1836  * be altered when false is returned.
1837  *
1838  * INPUTS
1839  *   infopath	Where the error is reported to be from on error.  This could
1840  *		be, for example, the name of the file the boolean is being read
1841  *		from.
1842  *   option	An option name being parsed, reported in traces and any error
1843  *		message.
1844  *   p		The string to actually read the option from.
1845  *   val	Pointer to where to store the boolean read from P.
1846  *
1847  * OUTPUTS
1848  *   val	TRUE/FALSE stored, as read, when there are no errors.
1849  *
1850  * RETURNS
1851  *   true	If VAL was read.
1852  *   false	On error.
1853  */
1854 bool
1855 readBool (const char *infopath, const char *option, const char *p, bool *val)
1856 {
1857     TRACE (TRACE_FLOW, "readBool (%s, %s, %s)", infopath, option, p);
1858     if (!strcasecmp (p, "no") || !strcasecmp (p, "false")
1859         || !strcasecmp (p, "off") || !strcmp (p, "0"))
1860     {
1861 	TRACE (TRACE_DATA, "Read %d for %s", *val, option);
1862 	*val = false;
1863 	return true;
1864     }
1865     else if (!strcasecmp (p, "yes") || !strcasecmp (p, "true")
1866 	     || !strcasecmp (p, "on") || !strcmp (p, "1"))
1867     {
1868 	TRACE (TRACE_DATA, "Read %d for %s", *val, option);
1869 	*val = true;
1870 	return true;
1871     }
1872 
1873     error (0, 0, "%s: unrecognized value `%s' for `%s'",
1874 	   infopath, p, option);
1875     return false;
1876 }
1877 
1878 
1879 
1880 /*
1881  * Open a file, exiting with a message on error.
1882  *
1883  * INPUTS
1884  *   name	The name of the file to open.
1885  *   mode	Mode to open file in, as POSIX fopen().
1886  *
1887  * NOTES
1888  *   If you want to handle errors, just call fopen (NAME, MODE).
1889  *
1890  * RETURNS
1891  *   The new FILE pointer.
1892  */
1893 FILE *
1894 xfopen (const char *name, const char *mode)
1895 {
1896     FILE *fp;
1897 
1898     if (!(fp = fopen (name, mode)))
1899 	error (1, errno, "cannot open %s", name);
1900     return fp;
1901 }
1902 
1903 
1904 
1905 /* char *
1906  * xcanonicalize_file_name (const char *path)
1907  *
1908  * Like canonicalize_file_name(), but exit on error.
1909  *
1910  * INPUTS
1911  *  path	The original path.
1912  *
1913  * RETURNS
1914  *  The path with any symbolic links, `.'s, or `..'s, expanded.
1915  *
1916  * ERRORS
1917  *  This function exits with a fatal error if it fails to read the link for
1918  *  any reason.
1919  */
1920 char *
1921 xcanonicalize_file_name (const char *path)
1922 {
1923     char *hardpath = canonicalize_file_name (path);
1924     if (!hardpath)
1925 	error (1, errno, "Failed to resolve path: `%s'", path);
1926     return hardpath;
1927 }
1928 
1929 
1930 
1931 /* Declared in main.c.  */
1932 extern char *server_hostname;
1933 
1934 /* Return true if OTHERHOST resolves to this host in the DNS.
1935  *
1936  * GLOBALS
1937  *   server_hostname	The name of this host, as determined by the call to
1938  *			xgethostname() in main().
1939  *
1940  * RETURNS
1941  *   true	If OTHERHOST equals or resolves to HOSTNAME.
1942  *   false	Otherwise.
1943  */
1944 bool
1945 isThisHost (const char *otherhost)
1946 {
1947     char *fqdno;
1948     char *fqdns;
1949     bool retval;
1950 
1951     /* As an optimization, check the literal strings before looking up
1952      * OTHERHOST in the DNS.
1953      */
1954     if (!strcasecmp (server_hostname, otherhost))
1955 	return true;
1956 
1957     fqdno = canon_host (otherhost);
1958     if (!fqdno)
1959 	error (1, 0, "Name lookup failed for `%s': %s",
1960 	       otherhost, ch_strerror ());
1961     fqdns = canon_host (server_hostname);
1962     if (!fqdns)
1963 	error (1, 0, "Name lookup failed for `%s': %s",
1964 	       server_hostname, ch_strerror ());
1965 
1966     retval = !strcasecmp (fqdns, fqdno);
1967 
1968     free (fqdno);
1969     free (fqdns);
1970     return retval;
1971 }
1972 
1973 
1974 
1975 /* Return true if two paths match, resolving symlinks.
1976  */
1977 bool
1978 isSamePath (const char *path1_in, const char *path2_in)
1979 {
1980     char *p1, *p2;
1981     bool same;
1982 
1983     if (!strcmp (path1_in, path2_in))
1984 	return true;
1985 
1986     /* Path didn't match, but try to resolve any links that may be
1987      * present.
1988      */
1989     if (!isdir (path1_in) || !isdir (path2_in))
1990 	/* To be resolvable, paths must exist on this server.  */
1991 	return false;
1992 
1993     p1 = xcanonicalize_file_name (path1_in);
1994     p2 = xcanonicalize_file_name (path2_in);
1995     if (strcmp (p1, p2))
1996 	same = false;
1997     else
1998 	same = true;
1999 
2000     free (p1);
2001     free (p2);
2002     return same;
2003 }
2004