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