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