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>
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)
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.
20 #include "vasprintf.h"
21 #include "vasnprintf.h"
28 #if !defined HAVE_NANOSLEEP && !defined HAVE_USLEEP && defined HAVE_SELECT
29 /* use select as a workaround */
31 #endif /* !defined HAVE_NANOSLEEP && !defined HAVE_USLEEP && defined HAVE_SELECT */
33 extern char *getlogin (void);
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. */
42 expand_string (char **strptr, size_t *n, size_t newsize)
45 *strptr = x2realloc (*strptr, n);
51 * Xreadlink (const char *link, size_t size)
54 * link The original path.
55 * size A guess as to the size needed for the path. It need
58 * The resolution of the final symbolic link in the path.
61 * This function exits with a fatal error if it fails to read the
62 * link for any reason.
65 Xreadlink (const char *link, size_t size)
67 char *file = xreadlink (link, size);
70 error (1, errno, "cannot readlink %s", link);
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. */
81 xrealloc_and_strcat (char **str, size_t *lenp, const char *src)
84 expand_string (str, lenp, (newstr ? 0 : strlen (*str)) + strlen (src) + 1);
93 /* Remove trailing newlines from STRING, destructively.
97 * True if any newlines were removed, false otherwise.
100 strip_trailing_newlines (char *str)
102 size_t index, origlen;
103 index = origlen = strlen (str);
105 while (index > 0 && str[index-1] == '\n')
108 return index != origlen;
113 /* Return the number of levels that PATH ascends above where it starts.
117 * "foo/../../bar" -> 1
120 pathname_levels (const char *p)
125 if (p == NULL) return 0;
131 /* Now look for pathname level-ups. */
132 if (p[0] == '.' && p[1] == '.' && (p[2] == '\0' || ISSLASH (p[2])))
135 if (-level > max_level)
138 else if (p[0] == '\0' || ISSLASH (p[0]) ||
139 (p[0] == '.' && (p[1] == '\0' || ISSLASH (p[1]))))
144 /* q = strchr (p, '/'); but sub ISSLASH() for '/': */
145 while (*p != '\0' && !ISSLASH (*p)) p++;
147 } while (*p != '\0');
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. */
157 free_names (int *pargc, char **argv)
161 for (i = 0; i < *pargc; i++)
162 { /* only do through *pargc */
166 *pargc = 0; /* and set it to zero when done */
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. */
177 line2argv (int *pargc, char ***argv, char *line, char *sepchars)
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. */
185 /* Small for testing. */
187 *argv = (char **) xmalloc (argv_allocated * sizeof (**argv));
190 for (cp = strtok (line, sepchars); cp; cp = strtok ((char *) NULL, sepchars))
192 if (*pargc == argv_allocated)
195 *argv = xrealloc (*argv, argv_allocated * sizeof (**argv));
197 (*argv)[*pargc] = xstrdup (cp);
205 * Returns the number of dots ('.') found in an RCS revision number
208 numdots (const char *s)
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. */
227 compare_revnums (const char *rev1, const char *rev2)
237 result = strtoul (sp, &snext, 10) - strtoul (tp, &tnext, 10);
238 if (*snext == '\0' || *tnext == '\0')
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
253 increment_revnum (const char *rev)
256 size_t len = strlen (rev);
258 newrev = xmalloc (len + 2);
259 memcpy (newrev, rev, len + 1);
260 for (p = newrev + len; p != newrev; )
275 /* The number was all 9s, so change the first character to 1 and add
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
292 #ifndef SYSTEM_GETCALLER
298 /* If there is a CVS username, return it. */
299 #ifdef AUTH_SERVER_SUPPORT
300 if (CVS_Username != NULL)
304 #ifdef SYSTEM_GETCALLER
305 return SYSTEM_GETCALLER ();
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. */
315 if (uid == (uid_t) 0)
319 /* super-user; try getlogin() to distinguish */
320 if (((name = getlogin ()) || (name = getenv("LOGNAME")) ||
321 (name = getenv("USER"))) && *name)
323 cache = xstrdup (name);
327 if ((pw = (struct passwd *) getpwuid (uid)) == NULL)
331 (void) sprintf (uidname, "uid%lu", (unsigned long) uid);
332 cache = xstrdup (uidname);
335 cache = xstrdup (pw->pw_name);
346 get_date( char *date, struct timeb *now )
357 /* Given some revision, REV, return the first prior revision that exists in the
364 * RCS The RCS node pointer.
365 * REV An existing revision in the RCS file referred to by RCS.
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.
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.
377 previous_rev (RCSNode *rcs, const char *rev)
380 char *tmp = xstrdup (rev);
384 /* Our retval can have no more digits and dots than our input revision. */
385 retval = xmalloc (strlen (rev) + 1);
386 p = strrchr (tmp, '.');
388 r1 = strtol (p+1, NULL, 10);
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
398 p = strrchr (tmp, '.');
400 /* We are on the trunk. */
405 sprintf (retval, "%s", tmp);
409 sprintf (retval, "%s.%ld", tmp, r1);
410 } while (!RCS_exist_rev (rcs, retval));
418 /* Given two revisions, find their greatest common ancestor. If the
419 two input revisions exist, then rcs guarantees that the gca will
422 gca (const char *rev1, const char *rev2)
430 if (rev1 == NULL || rev2 == NULL)
432 error (0, 0, "sanity failure in gca");
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);
441 /* walk the strings, reading the common parts. */
446 r1 = strtol (p1, (char **) &p1, 10);
447 r2 = strtol (p2, (char **) &p2, 10);
449 /* use the lowest. */
450 (void) sprintf (g, "%d.", r1 < r2 ? r1 : r2);
452 if (*p1 == '.') ++p1;
454 if (*p2 == '.') ++p2;
458 /* erase that last dot. */
461 /* numbers differ, or we ran out of strings. we're done with the
464 dots = numdots (gca);
467 /* revisions differ in trunk major number. */
469 if (r2 < r1) p1 = p2;
472 /* we only got one number. this is strange. */
473 error (0, 0, "bad revisions %s or %s", rev1, rev2);
478 /* we have a minor number. use it. */
480 while (*p1 != '.' && *p1 != '\0')
485 else if ((dots & 1) == 0)
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. */
490 g = strrchr (gca, '.');
494 retval = xstrdup (gca);
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. */
509 check_numeric (const char *rev, int argc, char **argv)
511 if (rev == NULL || !isdigit ((unsigned char) *rev))
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. */
520 || (!wrap_name_has (argv[0], WRAP_TOCVS) && isdir (argv[0])))
522 error (0, 0, "while processing more than one file:");
523 error (1, 0, "attempt to specify a numeric revision");
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.
535 * TODO: We no longer use RCS to manage repository files, so maybe this
536 * nonsense about non-empty log fields can be dropped.
539 make_message_rcsvalid (const char *message)
544 if (message == NULL) message = "";
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)
552 /* At end-of-line; backtrack to last non-space. */
553 while (dp > dst && (dp[-1] == ' ' || dp[-1] == '\t'))
559 /* Backtrack to last non-space at end of string, and truncate. */
560 while (dp > dst && isspace ((unsigned char) dp[-1]))
564 /* After all that, if there was no non-space in the string,
565 substitute a non-empty message. */
569 dst = xstrdup ("*** empty log message ***");
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
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.
588 * The ts_conflict field is not NULL.
591 * TRUE ts_conflict matches the current timestamp.
592 * FALSE The ts_conflict field does not match the file's
596 file_has_conflict (const struct file_info *finfo, const char *ts_conflict)
601 /* If ts_conflict is NULL, there was no merge since the last
602 * commit and there can be no conflict.
604 assert (ts_conflict);
607 * If the timestamp has changed and no
608 * conflict indicators are found, it isn't a
612 #ifdef SERVER_SUPPORT
614 retcode = ts_conflict[0] == '=' && ts_conflict[1] == '\0';
616 #endif /* SERVER_SUPPORT */
618 filestamp = time_stamp (finfo->file);
619 retcode = !strcmp (ts_conflict, filestamp);
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
634 file_has_markers (const struct file_info *finfo)
638 size_t line_allocated = 0;
642 fp = CVS_FOPEN (finfo->file, "r");
644 error (1, errno, "cannot open %s", finfo->fullname);
645 while (getline (&line, &line_allocated, fp) > 0)
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)
656 error (0, errno, "cannot read %s", finfo->fullname);
659 error (0, errno, "cannot close %s", finfo->fullname);
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. */
675 get_file (const char *name, const char *fullname, const char *mode, char **buf,
676 size_t *bufsize, size_t *len)
687 filesize = 100; /* force allocation of minimum buffer */
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
697 if (CVS_STAT (name, &s) < 0)
698 error (1, errno, "can't stat %s", fullname);
700 /* Convert from signed to unsigned. */
701 filesize = s.st_size;
703 e = open_file (name, mode);
706 if (*buf == NULL || *bufsize <= filesize)
708 *bufsize = filesize + 1;
709 *buf = xrealloc (*buf, *bufsize);
718 got = fread (tobuf, 1, *bufsize - (tobuf - *buf), e);
720 error (1, errno, "can't read %s", fullname);
727 /* Allocate more space if needed. */
728 if (tobuf == *buf + *bufsize)
737 expand_string (buf, bufsize, *bufsize + 100);
744 if (e != stdin && fclose (e) < 0)
745 error (0, errno, "cannot close %s", fullname);
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';
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). */
762 resolve_symlink (char **filename)
766 if (filename == NULL || *filename == NULL)
769 while ((rsize = islink (*filename)) > 0)
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);
779 if (isabsolute (newname))
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);
793 *filename = fullnewname;
796 error (1, 0, "internal error: islink doesn't like readlink");
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.
807 * Returns the new name, which caller may free() if desired.
810 backup_file (const char *filename, const char *suffix)
816 backup_name = xmalloc (sizeof (BAKPREFIX) + strlen (filename) + 1);
817 sprintf (backup_name, "%s%s", BAKPREFIX, filename);
821 backup_name = xmalloc (sizeof (BAKPREFIX)
824 + 2); /* one for dot, one for trailing '\0' */
825 sprintf (backup_name, "%s%s.%s", BAKPREFIX, filename, suffix);
828 if (isfile (filename))
829 copy_file (filename, backup_name);
837 * Copy a string into a buffer escaping any shell metacharacters. The
838 * buffer should be at least twice as long as the string.
840 * Returns a pointer to the terminating NUL byte in buffer.
843 shell_escape(char *buf, const char *str)
845 static const char meta[] = "$`\\\"";
850 p = strpbrk(str, meta);
851 if (!p) p = str + strlen(str);
854 memcpy(buf, str, p - str);
869 * We can only travel forwards in time, not backwards. :)
872 sleep_past (time_t desttime)
878 while (time (&t) <= desttime)
880 #ifdef HAVE_GETTIMEOFDAY
882 gettimeofday (&tv, NULL);
883 if (tv.tv_sec > desttime)
885 s = desttime - tv.tv_sec;
887 us = 1000000 - tv.tv_usec;
894 /* default to 20 ms increments */
902 ts.tv_nsec = us * 1000;
903 (void)nanosleep (&ts, NULL);
910 /* used to store callback data in a list indexed by the user format string
912 typedef int (*CONVPROC_t) (Node *, void *);
913 struct cmdline_bindings
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.
926 cmdline_bindings_hash_node_delete (Node *p)
928 struct cmdline_bindings *b = p->data;
930 if (b->conversion != ',')
940 * assume s is a literal argument and put it between quotes,
941 * escaping as appropriate for a shell command line
943 * the caller is responsible for disposing of the new string
946 cmdlinequote (char quotes, char *s)
948 char *quoted = cmdlineescape (quotes, s);
949 char *buf = xmalloc(strlen(quoted)+3);
953 strcat (buf, quoted);
955 buf[strlen(buf)+1] = '\0';
956 buf[strlen(buf)] = quotes;
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).
966 * if you were planning on expanding any paths, it should be done before
967 * calling this function, as it escapes shell metacharacters.
969 * the caller is responsible for disposing of the new string
971 * FIXME: See about removing/combining this functionality with shell_escape()
975 cmdlineescape (char quotes, char *s)
986 /* FIXME: Single quotes only require other single quotes to be escaped
989 if ( isspace( *s ) ) lastspace = s;
993 && ( *s == '$' || *s == '`' || *s == '\\' ) ) )
994 : ( strchr( "\\$`'\"*?", *s )
996 || ( lastspace == ( s - 1 )
1000 expand_string (&buf, &length, doff + 1);
1005 expand_string (&buf, &length, doff + 1);
1007 } while ((*d++ = *s++) != '\0');
1013 /* expand format strings in a command line. modeled roughly after printf
1015 * this function's arg list must be NULL terminated
1017 * assume a space delimited list of args is the desired final output,
1018 * but args can be quoted (" or ').
1020 * the best usage examples are in tag.c & logmsg.c, but here goes:
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
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
1040 * determine what kind of
1041 * data the next arg will
1043 * <type> data a piece of data to be
1044 * formatted into the user
1047 * printfformat string.
1049 * char *userformat, char *printfformat, List *data,
1050 * int (*convproc) (Node *, void *), void *closure
1052 * char *userformat same as above, except
1053 * multiple characters in
1054 * this string represent
1056 * attributes which can be
1057 * retrieved from data by
1059 * char *printfformat = ","
1060 * List *data the list to be walked
1062 * convproc to retrieve
1063 * data for each of the
1067 * int (*convproc)() see data
1068 * void *closure arg to be passed into
1069 * walklist as closure
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",
1078 * "xG", "ld", longintwhichwontbeusedthispass,
1079 * "sVv", ",", tlist, pretag_list_to_args_proc,
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:
1086 * /cvsroot/CVSROOT/mytaginfoproc "newtag" "mov" "file1" "1.1" "1.1.2.3" "file2" "1.1" "1.1.2.3"
1089 * pointer to newly allocated string. the caller is responsible for
1090 * disposing of this string.
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 */
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
1106 char *pfmt; /* initially the list of fmt keys passed in,
1107 * but used as a temporary key buffer later
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 */
1116 List *pflist = getlist(); /* our list of input data indexed by format
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
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*/
1130 int subbedsomething;
1131 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1133 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1134 if (oldway && !warned_of_deprecation)
1136 /* warn the user that we don't like his kind 'round these parts */
1137 warned_of_deprecation = 1;
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"
1146 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1148 va_start (args, format);
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.
1154 while ((pfmt = va_arg (args, char *)) != NULL)
1156 char *conversion = va_arg (args, char *);
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;
1164 /* allocate space to save our data */
1165 b = xmalloc(sizeof(struct cmdline_bindings));
1167 /* where did you think we were going to store all this data??? */
1171 /* read a length from the conversion string */
1174 while (!length && *s)
1179 integer_conversion = 1;
1182 length = sizeof (char);
1187 char_conversion = 1;
1188 length = sizeof (short);
1192 #ifdef HAVE_INTMAX_T
1194 integer_conversion = 1;
1195 length = sizeof (intmax_t);
1198 #endif /* HAVE_INTMAX_T */
1200 integer_conversion = 1;
1203 #ifdef HAVE_LONG_LONG
1204 length = sizeof (long long);
1210 char_conversion = 2;
1211 string_conversion = 2;
1212 length = sizeof (long);
1217 integer_conversion = 1;
1218 length = sizeof (ptrdiff_t);
1222 integer_conversion = 1;
1223 length = sizeof (size_t);
1226 #ifdef HAVE_LONG_DOUBLE
1228 decimal_conversion = 1;
1229 length = sizeof (long double);
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 */
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);
1247 strcpy (buf+1, conversion);
1251 /* chars (an integer conversion) */
1252 if (!char_conversion)
1254 conversion_error = 1;
1257 if (char_conversion == 2)
1260 length = sizeof (wint_t);
1262 conversion_error = 1;
1267 length = sizeof (char);
1268 /* fall through... */
1275 /* integer conversions */
1276 if (!integer_conversion)
1278 conversion_error = 1;
1283 length = sizeof (int);
1289 char arg_char = (char) va_arg (args, int);
1290 b->data = Xasprintf (buf, arg_char);
1293 #ifdef UNIQUE_INT_TYPE_WINT_T /* implies HAVE_WINT_T */
1294 case sizeof(wint_t):
1296 wint_t arg_wint_t = va_arg (args, wint_t);
1297 b->data = Xasprintf (buf, arg_wint_t);
1300 #endif /* UNIQUE_INT_TYPE_WINT_T */
1301 #ifdef UNIQUE_INT_TYPE_SHORT
1304 short arg_short = (short) va_arg (args, int);
1305 b->data = Xasprintf (buf, arg_short);
1308 #endif /* UNIQUE_INT_TYPE_SHORT */
1309 #ifdef UNIQUE_INT_TYPE_INT
1312 int arg_int = va_arg (args, int);
1313 b->data = Xasprintf(buf, arg_int);
1316 #endif /* UNIQUE_INT_TYPE_INT */
1317 #ifdef UNIQUE_INT_TYPE_LONG
1320 long arg_long = va_arg (args, long);
1321 b->data = Xasprintf (buf, arg_long);
1324 #endif /* UNIQUE_INT_TYPE_LONG */
1325 #ifdef UNIQUE_INT_TYPE_LONG_LONG /* implies HAVE_LONG_LONG */
1326 case sizeof(long long):
1328 long long arg_long_long = va_arg (args, long long);
1329 b->data = Xasprintf (buf, arg_long_long);
1332 #endif /* UNIQUE_INT_TYPE_LONG_LONG */
1333 #ifdef UNIQUE_INT_TYPE_INTMAX_T /* implies HAVE_INTMAX_T */
1334 case sizeof(intmax_t):
1336 intmax_t arg_intmax_t = va_arg (args, intmax_t);
1337 b->data = Xasprintf (buf, arg_intmax_t);
1340 #endif /* UNIQUE_INT_TYPE_INTMAX_T */
1341 #ifdef UNIQUE_INT_TYPE_SIZE_T
1342 case sizeof(size_t):
1344 size_t arg_size_t = va_arg (args, size_t);
1345 b->data = Xasprintf (buf, arg_size_t);
1348 #endif /* UNIQUE_INT_TYPE_SIZE_T */
1349 #ifdef UNIQUE_INT_TYPE_PTRDIFF_T
1350 case sizeof(ptrdiff_t):
1352 ptrdiff_t arg_ptrdiff_t = va_arg (args, ptrdiff_t);
1353 b->data = Xasprintf (buf, arg_ptrdiff_t);
1356 #endif /* UNIQUE_INT_TYPE_PTRDIFF_T */
1361 "internal error: unknown integer arg size (%d)",
1374 /* decimal conversions */
1375 if (!decimal_conversion)
1377 conversion_error = 1;
1382 length = sizeof (double);
1386 case sizeof(double):
1388 double arg_double = va_arg (args, double);
1389 b->data = Xasprintf (buf, arg_double);
1392 #ifdef UNIQUE_FLOAT_TYPE_LONG_DOUBLE /* implies HAVE_LONG_DOUBLE */
1393 case sizeof(long double):
1395 long double arg_long_double = va_arg (args, long double);
1396 b->data = Xasprintf (buf, arg_long_double);
1399 #endif /* UNIQUE_FLOAT_TYPE_LONG_DOUBLE */
1404 "internal error: unknown floating point arg size (%d)",
1410 switch (string_conversion)
1413 b->data = xstrdup (va_arg (args, char *));
1418 wchar_t *arg_wchar_t_string = va_arg (args, wchar_t *);
1419 b->data = Xasprintf (buf, arg_wchar_t_string);
1422 #endif /* HAVE_WCHAR_T */
1424 conversion_error = 1;
1431 conversion_error = 1;
1434 b->data = va_arg (args, List *);
1435 b->convproc = va_arg (args, CONVPROC_t);
1436 b->closure = va_arg (args, void *);
1439 conversion_error = 1;
1443 /* fail if we found an error or haven't found the end of the string */
1444 if (conversion_error || s[1])
1447 "internal error (format_cmdline): '%s' is not a valid conversion!!!",
1452 /* save our type - we really only care wheter it's a list type (',')
1453 * or not from now on, but what the hell...
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
1464 struct cmdline_bindings *tb;
1468 while (*++q && *q != '}');
1478 /* copy the data since we'll need it again */
1479 tb = xmalloc(sizeof(struct cmdline_bindings));
1480 if (b->conversion == ',')
1486 tb->data = xstrdup(b->data);
1488 tb->conversion = b->conversion;
1489 tb->convproc = b->convproc;
1490 tb->closure = b->closure;
1494 /* we're done after this, so we don't need to copy the data */
1498 p->key = xmalloc((q - s) + 1);
1499 strncpy (p->key, s, q - s);
1502 p->delproc = cmdline_bindings_hash_node_delete;
1507 /* we're done with va_list */
1510 /* All formatted strings include a format character that resolves to the
1511 * empty string by default, so put it in pflist.
1513 /* allocate space to save our data */
1514 b = xmalloc(sizeof(struct cmdline_bindings));
1515 b->conversion = 's';
1518 b->data = xstrdup( "" );
1520 p->key = xstrdup( "n" );
1522 p->delproc = cmdline_bindings_hash_node_delete;
1523 addnode( pflist,p );
1525 /* finally, read the user string and copy it into rargv as appropriate */
1526 /* user format strings look as follows:
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
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
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
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.
1553 * clearing the variable oldway, passed into this function, causes the
1554 * behavior of '1' and "," in the format string to reverse.
1557 /* for convenience, use fmt as a temporary key buffer.
1558 * for speed, attempt to realloc it as little as possible
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
1573 expand_string (&buf, &length, doff + 1);
1577 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1578 subbedsomething = 0;
1579 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1580 while ((*d++ = *s) != '\0')
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
1595 expand_string (&buf, &length, doff + 1);
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
1606 if (!inquotes) inquotes = s[-1];
1607 else if (s[-1] == inquotes) inquotes = '\0';
1612 /* "%%" is a literal "%" */
1616 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1617 if (oldway && subbedsomething)
1619 /* the old method was to sub only the first format string */
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. */
1636 /* FIXME - add FILE && LINE */
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.");
1642 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1644 /* parse the format string and sub in... */
1657 expand_string (&fmt, &flen, qoff + 1);
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
1666 /* if we copied a NUL while processing a list, fail
1667 * - we had an empty fmt string or didn't find a list
1670 /* FIXME - this wants a file name and line number in a bad
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.");
1686 /* We're not in a list, so we must have just copied a
1687 * single character. Terminate the string.
1691 expand_string (&fmt, &flen, qoff + 1);
1695 /* fmt is now a pointer to a list of fmt chars, though the list
1696 * could be a single element one
1699 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1700 /* always add quotes in the deprecated onearg case - for
1701 * backwards compatibility
1706 expand_string (&buf, &length, doff + 1);
1710 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1712 * for each character in the fmt string,
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
1720 * see the "user format strings" section above for more info
1723 if ((p = findnode (pflist, key)) != NULL)
1726 if (b->conversion == ',')
1728 /* process the rest of the format string as a list */
1729 struct format_cmdline_walklist_closure c;
1734 c.quotes = inquotes;
1735 c.closure = b->closure;
1736 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
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 */
1748 /* got a flat item */
1753 "Multiple non-list variables are not allowed in a single format string.");
1755 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1762 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1763 /* the *only* case possible without
1764 * SUPPORT_OLD_INFO_FORMAT_STRINGS
1769 expand_string (&buf, &length, doff + 1);
1773 outstr = cmdlineescape (inquotes ? inquotes : '"', b->data);
1774 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1776 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1778 expand_string (&buf, &length, doff + strlen(outstr));
1780 strncpy(d, outstr, strlen(outstr));
1781 d += strlen(outstr);
1782 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1786 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1790 expand_string (&buf, &length, doff + 1);
1794 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1796 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1800 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
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
1809 expand_string (&buf, &length, doff + strlen(srepos));
1811 strncpy(d, srepos, strlen(srepos));
1812 d += strlen(srepos);
1814 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1817 /* print an error message to the user
1818 * FIXME - this should have a file and line number!!! */
1820 "Unknown format character in info file ('%s').\n"
1821 "Info files are the hook files, verifymsg, taginfo, commitinfo, etc.",
1824 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1825 /* always add quotes in the deprecated onearg case - for
1826 * backwards compatibility
1831 expand_string (&buf, &length, doff + 1);
1835 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1839 expand_string (&buf, &length, doff + 1);
1841 } /* while (*d++ = *s) */
1842 if (fmt) free (fmt);
1845 /* FIXME - we shouldn't need this - Parse_Info should be handling
1848 error (1, 0, "unterminated quote in format string: %s", format);
1857 /* Return true iff FILENAME is absolute.
1858 Trivial under Unix, but more complicated under other systems. */
1860 isabsolute (filename)
1861 const char *filename;
1863 return ISABSOLUTE (filename);
1869 * void cvs_trace(int level, const char *fmt, ...)
1871 * Print tracing information to stderr on request. Levels are implemented
1874 void cvs_trace (int level, const char *fmt, ...)
1881 #ifdef SERVER_SUPPORT
1882 fprintf (stderr,"%c -> ",server_active?'S':' ');
1883 #else /* ! SERVER_SUPPORT */
1884 fprintf (stderr," -> ");
1886 vfprintf (stderr, fmt, va);
1887 fprintf (stderr,"\n");
1894 /* Like xstrdup (), but can handle a NULL argument.
1897 Xstrdup (const char *string)
1899 if (string == NULL) return NULL;
1900 return xmemdup (string, strlen (string) + 1);
1905 /* Like xasprintf(), but consider all errors fatal (may never return NULL).
1908 Xasprintf (const char *format, ...)
1913 va_start (args, format);
1914 if (vasprintf (&result, format, args) < 0)
1915 error (1, errno, "Failed to write to string.");
1923 /* Like xasnprintf(), but consider all errors fatal (may never return NULL).
1926 Xasnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
1931 va_start (args, format);
1932 result = vasnprintf (resultbuf, lengthp, format, args);
1934 error (1, errno, "Failed to write to string.");
1942 /* Print a warning and return false if P doesn't look like a string specifying
1945 * Sets *VAL to the parsed value when it is found to be valid. *VAL will not
1946 * be altered when false is returned.
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
1952 * option An option name being parsed, reported in traces and any error
1954 * p The string to actually read the option from.
1955 * val Pointer to where to store the boolean read from P.
1958 * val TRUE/FALSE stored, as read, when there are no errors.
1961 * true If VAL was read.
1965 readBool (const char *infopath, const char *option, const char *p, bool *val)
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"))
1971 TRACE (TRACE_DATA, "Read %d for %s", *val, option);
1975 else if (!strcasecmp (p, "yes") || !strcasecmp (p, "true")
1976 || !strcasecmp (p, "on") || !strcmp (p, "1"))
1978 TRACE (TRACE_DATA, "Read %d for %s", *val, option);
1983 error (0, 0, "%s: unrecognized value `%s' for `%s'",
1984 infopath, p, option);