2 * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
4 * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
7 * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
8 * Portions Copyright (C) 1989-1992, Brian Berliner
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.
13 * Various useful functions for the CVS support code.
18 #include "canonicalize.h"
19 #include "canon-host.h"
21 #include "vasprintf.h"
22 #include "vasnprintf.h"
31 extern char *getlogin (void);
35 /* *STRPTR is a pointer returned from malloc (or NULL), pointing to *N
36 characters of space. Reallocate it so that points to at least
37 NEWSIZE bytes of space. Gives a fatal error if out of memory;
38 if it returns it was successful. */
40 expand_string (char **strptr
, size_t *n
, size_t newsize
)
43 *strptr
= x2realloc (*strptr
, n
);
49 * Xreadlink (const char *link, size_t size)
52 * link The original path.
53 * size A guess as to the size needed for the path. It need
56 * The resolution of the final symbolic link in the path.
59 * This function exits with a fatal error if it fails to read the
60 * link for any reason.
63 Xreadlink (const char *link
, size_t size
)
65 char *file
= xreadlink (link
, size
);
68 error (1, errno
, "cannot readlink %s", link
);
75 /* *STR is a pointer to a malloc'd string or NULL. *LENP is its allocated
76 * length. If *STR is NULL then *LENP must be 0 and visa-versa.
77 * Add SRC to the end of *STR, reallocating *STR if necessary. */
79 xrealloc_and_strcat (char **str
, size_t *lenp
, const char *src
)
82 expand_string (str
, lenp
, (newstr
? 0 : strlen (*str
)) + strlen (src
) + 1);
91 /* Remove trailing newlines from STRING, destructively.
95 * True if any newlines were removed, false otherwise.
98 strip_trailing_newlines (char *str
)
100 size_t index
, origlen
;
101 index
= origlen
= strlen (str
);
103 while (index
> 0 && str
[index
-1] == '\n')
106 return index
!= origlen
;
111 /* Return the number of levels that PATH ascends above where it starts.
115 * "foo/../../bar" -> 1
118 pathname_levels (const char *p
)
123 if (p
== NULL
) return 0;
129 /* Now look for pathname level-ups. */
130 if (p
[0] == '.' && p
[1] == '.' && (p
[2] == '\0' || ISSLASH (p
[2])))
133 if (-level
> max_level
)
136 else if (p
[0] == '\0' || ISSLASH (p
[0]) ||
137 (p
[0] == '.' && (p
[1] == '\0' || ISSLASH (p
[1]))))
142 /* q = strchr (p, '/'); but sub ISSLASH() for '/': */
143 while (*p
!= '\0' && !ISSLASH (*p
)) p
++;
145 } while (*p
!= '\0');
151 /* Free a vector, where (*ARGV)[0], (*ARGV)[1], ... (*ARGV)[*PARGC - 1]
152 are malloc'd and so is *ARGV itself. Such a vector is allocated by
153 line2argv or expand_wild, for example. */
155 free_names (int *pargc
, char **argv
)
159 for (i
= 0; i
< *pargc
; i
++)
160 { /* only do through *pargc */
164 *pargc
= 0; /* and set it to zero when done */
169 /* Convert LINE into arguments separated by SEPCHARS. Set *ARGC
170 to the number of arguments found, and (*ARGV)[0] to the first argument,
171 (*ARGV)[1] to the second, etc. *ARGV is malloc'd and so are each of
172 (*ARGV)[0], (*ARGV)[1], ... Use free_names() to return the memory
173 allocated here back to the free pool. */
175 line2argv (int *pargc
, char ***argv
, char *line
, char *sepchars
)
178 /* Could make a case for size_t or some other unsigned type, but
179 we'll stick with int to avoid signed/unsigned warnings when
180 comparing with *pargc. */
183 /* Small for testing. */
185 *argv
= xnmalloc (argv_allocated
, sizeof (**argv
));
188 for (cp
= strtok (line
, sepchars
); cp
; cp
= strtok (NULL
, sepchars
))
190 if (*pargc
== argv_allocated
)
193 *argv
= xnrealloc (*argv
, argv_allocated
, sizeof (**argv
));
195 (*argv
)[*pargc
] = xstrdup (cp
);
203 * Returns the number of dots ('.') found in an RCS revision number
206 numdots (const char *s
)
220 /* Compare revision numbers REV1 and REV2 by consecutive fields.
221 Return negative, zero, or positive in the manner of strcmp. The
222 two revision numbers must have the same number of fields, or else
223 compare_revnums will return an inaccurate result. */
225 compare_revnums (const char *rev1
, const char *rev2
)
235 result
= strtoul (sp
, &snext
, 10) - strtoul (tp
, &tnext
, 10);
236 if (*snext
== '\0' || *tnext
== '\0')
247 /* Increment a revision number. Working on the string is a bit awkward,
248 but it avoid problems with integer overflow should the revision numbers
251 increment_revnum (const char *rev
)
254 size_t len
= strlen (rev
);
256 newrev
= xmalloc (len
+ 2);
257 memcpy (newrev
, rev
, len
+ 1);
258 for (p
= newrev
+ len
; p
!= newrev
; )
273 /* The number was all 9s, so change the first character to 1 and add
284 /* Return the username by which the caller should be identified in
285 CVS, in contexts such as the author field of RCS files, various
290 #ifndef SYSTEM_GETCALLER
296 /* If there is a CVS username, return it. */
297 #ifdef AUTH_SERVER_SUPPORT
298 if (CVS_Username
!= NULL
)
302 #ifdef SYSTEM_GETCALLER
303 return SYSTEM_GETCALLER ();
305 /* Get the caller's login from his uid. If the real uid is "root"
306 try LOGNAME USER or getlogin(). If getlogin() and getpwuid()
307 both fail, return the uid as a string. */
313 if (uid
== (uid_t
) 0)
317 /* super-user; try getlogin() to distinguish */
318 if (((name
= getlogin ()) || (name
= getenv("LOGNAME")) ||
319 (name
= getenv("USER"))) && *name
)
321 cache
= xstrdup (name
);
325 if ((pw
= (struct passwd
*) getpwuid (uid
)) == NULL
)
327 cache
= Xasprintf ("uid%lu", (unsigned long) uid
);
330 cache
= xstrdup (pw
->pw_name
);
341 get_date (struct timespec
*result
, char const *p
, struct timespec
const *now
)
353 /* Given some revision, REV, return the first prior revision that exists in the
360 * RCS The RCS node pointer.
361 * REV An existing revision in the RCS file referred to by RCS.
364 * The first prior revision that exists in the RCS file, or NULL if no prior
365 * revision exists. The caller is responsible for disposing of this string.
368 * This function currently neglects the case where we are on the trunk with
369 * rev = X.1, where X != 1. If rev = X.Y, where X != 1 and Y > 1, then this
370 * function should work fine, as revision X.1 must exist, due to RCS rules.
373 previous_rev (RCSNode
*rcs
, const char *rev
)
376 char *tmp
= xstrdup (rev
);
380 /* Our retval can have no more digits and dots than our input revision. */
381 retval
= xmalloc (strlen (rev
) + 1);
382 p
= strrchr (tmp
, '.');
384 r1
= strtol (p
+1, NULL
, 10);
388 /* If r1 == 0, then we must be on a branch and our parent must
389 * exist, or we must be on the trunk with a REV like X.1.
390 * We are neglecting the X.1 with X != 1 case by assuming that
391 * there is no previous revision when we discover we were on
394 p
= strrchr (tmp
, '.');
396 /* We are on the trunk. */
401 sprintf (retval
, "%s", tmp
);
405 sprintf (retval
, "%s.%ld", tmp
, r1
);
406 } while (!RCS_exist_rev (rcs
, retval
));
414 /* Given two revisions, find their greatest common ancestor. If the
415 two input revisions exist, then rcs guarantees that the gca will
418 gca (const char *rev1
, const char *rev2
)
426 if (rev1
== NULL
|| rev2
== NULL
)
428 error (0, 0, "sanity failure in gca");
432 /* The greatest common ancestor will have no more dots, and numbers
433 of digits for each component no greater than the arguments. Therefore
434 this string will be big enough. */
435 g
= gca
= xmalloc (strlen (rev1
) + strlen (rev2
) + 100);
437 /* walk the strings, reading the common parts. */
442 r1
= strtol (p1
, (char **) &p1
, 10);
443 r2
= strtol (p2
, (char **) &p2
, 10);
445 /* use the lowest. */
446 (void) sprintf (g
, "%d.", r1
< r2
? r1
: r2
);
448 if (*p1
== '.') ++p1
;
450 if (*p2
== '.') ++p2
;
454 /* erase that last dot. */
457 /* numbers differ, or we ran out of strings. we're done with the
460 dots
= numdots (gca
);
463 /* revisions differ in trunk major number. */
465 if (r2
< r1
) p1
= p2
;
468 /* we only got one number. this is strange. */
469 error (0, 0, "bad revisions %s or %s", rev1
, rev2
);
474 /* we have a minor number. use it. */
476 while (*p1
!= '.' && *p1
!= '\0')
481 else if ((dots
& 1) == 0)
483 /* if we have an even number of dots, then we have a branch.
484 remove the last number in order to make it a revision. */
486 g
= strrchr (gca
, '.');
490 retval
= xstrdup (gca
);
497 /* Give fatal error if REV is numeric and ARGC,ARGV imply we are
498 planning to operate on more than one file. The current directory
499 should be the working directory. Note that callers assume that we
500 will only be checking the first character of REV; it need not have
501 '\0' at the end of the tag name and other niceties. Right now this
502 is only called from admin.c, but if people like the concept it probably
503 should also be called from diff -r, update -r, get -r, and log -r. */
505 check_numeric (const char *rev
, int argc
, char **argv
)
507 if (rev
== NULL
|| !isdigit ((unsigned char) *rev
))
510 /* Note that the check for whether we are processing more than one
511 file is (basically) syntactic; that is, we don't behave differently
512 depending on whether a directory happens to contain only a single
513 file or whether it contains more than one. I strongly suspect this
514 is the least confusing behavior. */
516 || (!wrap_name_has (argv
[0], WRAP_TOCVS
) && isdir (argv
[0])))
518 error (0, 0, "while processing more than one file:");
519 error (1, 0, "attempt to specify a numeric revision");
526 * Sanity checks and any required fix-up on message passed to RCS via '-m'.
527 * RCS 5.7 requires that a non-total-whitespace, non-null message be provided
528 * with '-m'. Returns a newly allocated, non-empty buffer with whitespace
529 * stripped from end of lines and end of buffer.
531 * TODO: We no longer use RCS to manage repository files, so maybe this
532 * nonsense about non-empty log fields can be dropped.
535 make_message_rcsvalid (const char *message
)
540 if (message
== NULL
) message
= "";
542 /* Strip whitespace from end of lines and end of string. */
543 dp
= dst
= (char *) xmalloc (strlen (message
) + 1);
544 for (mp
= message
; *mp
!= '\0'; ++mp
)
548 /* At end-of-line; backtrack to last non-space. */
549 while (dp
> dst
&& (dp
[-1] == ' ' || dp
[-1] == '\t'))
555 /* Backtrack to last non-space at end of string, and truncate. */
556 while (dp
> dst
&& isspace ((unsigned char) dp
[-1]))
560 /* After all that, if there was no non-space in the string,
561 substitute a non-empty message. */
565 dst
= xstrdup ("*** empty log message ***");
573 /* Does the file FINFO contain conflict markers? The whole concept
574 of looking at the contents of the file to figure out whether there are
575 unresolved conflicts is kind of bogus (people do want to manage files
576 which contain those patterns not as conflict markers), but for now it
579 file_has_markers (const struct file_info
*finfo
)
583 size_t line_allocated
= 0;
587 fp
= CVS_FOPEN (finfo
->file
, "r");
589 error (1, errno
, "cannot open %s", finfo
->fullname
);
590 while (getline (&line
, &line_allocated
, fp
) > 0)
592 if (strncmp (line
, RCS_MERGE_PAT_1
, sizeof RCS_MERGE_PAT_1
- 1) == 0 ||
593 strncmp (line
, RCS_MERGE_PAT_2
, sizeof RCS_MERGE_PAT_2
- 1) == 0 ||
594 strncmp (line
, RCS_MERGE_PAT_3
, sizeof RCS_MERGE_PAT_3
- 1) == 0)
601 error (0, errno
, "cannot read %s", finfo
->fullname
);
604 error (0, errno
, "cannot close %s", finfo
->fullname
);
612 /* Read the entire contents of the file NAME into *BUF.
613 If NAME is NULL, read from stdin. *BUF
614 is a pointer returned from malloc (or NULL), pointing to *BUFSIZE
615 bytes of space. The actual size is returned in *LEN. On error,
616 give a fatal error. The name of the file to use in error messages
617 (typically will include a directory if we have changed directory)
618 is FULLNAME. MODE is "r" for text or "rb" for binary. */
620 get_file (const char *name
, const char *fullname
, const char *mode
, char **buf
,
621 size_t *bufsize
, size_t *len
)
632 filesize
= 100; /* force allocation of minimum buffer */
636 /* Although it would be cleaner in some ways to just read
637 until end of file, reallocating the buffer, this function
638 does get called on files in the working directory which can
639 be of arbitrary size, so I think we better do all that
642 if (stat (name
, &s
) < 0)
643 error (1, errno
, "can't stat %s", fullname
);
645 /* Convert from signed to unsigned. */
646 filesize
= s
.st_size
;
648 e
= xfopen (name
, mode
);
651 if (*buf
== NULL
|| *bufsize
<= filesize
)
653 *bufsize
= filesize
+ 1;
654 *buf
= xrealloc (*buf
, *bufsize
);
663 got
= fread (tobuf
, 1, *bufsize
- (tobuf
- *buf
), e
);
665 error (1, errno
, "can't read %s", fullname
);
672 /* Allocate more space if needed. */
673 if (tobuf
== *buf
+ *bufsize
)
682 expand_string (buf
, bufsize
, *bufsize
+ 100);
689 if (e
!= stdin
&& fclose (e
) < 0)
690 error (0, errno
, "cannot close %s", fullname
);
694 /* Force *BUF to be large enough to hold a null terminator. */
695 if (nread
== *bufsize
)
696 expand_string (buf
, bufsize
, *bufsize
+ 1);
697 (*buf
)[nread
] = '\0';
702 /* Follow a chain of symbolic links to its destination. FILENAME
703 should be a handle to a malloc'd block of memory which contains the
704 beginning of the chain. This routine will replace the contents of
705 FILENAME with the destination (a real file). */
707 resolve_symlink (char **filename
)
711 if (filename
== NULL
|| *filename
== NULL
)
714 while ((rsize
= islink (*filename
)) > 0)
717 /* The clean thing to do is probably to have each filesubr.c
718 implement this (with an error if not supported by the
719 platform, in which case islink would presumably return 0).
720 But that would require editing each filesubr.c and so the
721 expedient hack seems to be looking at HAVE_READLINK. */
722 char *newname
= Xreadlink (*filename
, rsize
);
724 if (ISABSOLUTE (newname
))
731 const char *oldname
= last_component (*filename
);
732 int dirlen
= oldname
- *filename
;
733 char *fullnewname
= xmalloc (dirlen
+ strlen (newname
) + 1);
734 strncpy (fullnewname
, *filename
, dirlen
);
735 strcpy (fullnewname
+ dirlen
, newname
);
738 *filename
= fullnewname
;
741 error (1, 0, "internal error: islink doesn't like readlink");
749 * Rename a file to an appropriate backup name based on BAKPREFIX.
750 * If suffix non-null, then ".<suffix>" is appended to the new name.
752 * Returns the new name, which caller may free() if desired.
755 backup_file (const char *filename
, const char *suffix
)
757 char *backup_name
= Xasprintf ("%s%s%s%s", BAKPREFIX
, filename
,
758 suffix
? "." : "", suffix
? suffix
: "");
760 if (isfile (filename
))
761 copy_file (filename
, backup_name
);
769 * Copy a string into a buffer escaping any shell metacharacters. The
770 * buffer should be at least twice as long as the string.
772 * Returns a pointer to the terminating NUL byte in buffer.
775 shell_escape(char *buf
, const char *str
)
777 static const char meta
[] = "$`\\\"";
782 p
= strpbrk(str
, meta
);
783 if (!p
) p
= str
+ strlen(str
);
786 memcpy(buf
, str
, p
- str
);
801 * We can only travel forwards in time, not backwards. :)
804 sleep_past (time_t desttime
)
810 while (time (&t
) <= desttime
)
812 #ifdef HAVE_GETTIMEOFDAY
814 gettimeofday (&tv
, NULL
);
815 if (tv
.tv_sec
> desttime
)
817 s
= desttime
- tv
.tv_sec
;
819 us
= 1000000 - tv
.tv_usec
;
826 /* default to 20 ms increments */
834 ts
.tv_nsec
= us
* 1000;
835 (void)nanosleep (&ts
, NULL
);
842 /* used to store callback data in a list indexed by the user format string
844 typedef int (*CONVPROC_t
) (Node
*, void *);
845 struct cmdline_bindings
852 /* since we store the above in a list, we need to dispose of the data field.
853 * we don't have to worry about convproc or closure since pointers are stuck
854 * in there directly and format_cmdline's caller is responsible for disposing
855 * of those if necessary.
858 cmdline_bindings_hash_node_delete (Node
*p
)
860 struct cmdline_bindings
*b
= p
->data
;
862 if (b
->conversion
!= ',')
872 * assume s is a literal argument and put it between quotes,
873 * escaping as appropriate for a shell command line
875 * the caller is responsible for disposing of the new string
878 cmdlinequote (char quotes
, char *s
)
880 char *quoted
= cmdlineescape (quotes
, s
);
881 char *buf
= Xasprintf ("%c%s%c", quotes
, quoted
, quotes
);
889 /* read quotes as the type of quotes we are between (if any) and then make our
890 * argument so it could make it past a cmdline parser (using sh as a model)
891 * inside the quotes (if any).
893 * if you were planning on expanding any paths, it should be done before
894 * calling this function, as it escapes shell metacharacters.
896 * the caller is responsible for disposing of the new string
898 * FIXME: See about removing/combining this functionality with shell_escape()
902 cmdlineescape (char quotes
, char *s
)
913 /* FIXME: Single quotes only require other single quotes to be escaped
916 if ( isspace( *s
) ) lastspace
= s
;
920 && ( *s
== '$' || *s
== '`' || *s
== '\\' ) ) )
921 : ( strchr( "\\$`'\"*?", *s
)
923 || ( lastspace
== ( s
- 1 )
927 expand_string (&buf
, &length
, doff
+ 1);
932 expand_string (&buf
, &length
, doff
+ 1);
934 } while ((*d
++ = *s
++) != '\0');
940 /* expand format strings in a command line. modeled roughly after printf
942 * this function's arg list must be NULL terminated
944 * assume a space delimited list of args is the desired final output,
945 * but args can be quoted (" or ').
947 * the best usage examples are in tag.c & logmsg.c, but here goes:
950 * int oldway to support old format strings
951 * char *srepos you guessed it
952 * char *format the format string to parse
953 * ... NULL terminated data list in the following format:
954 * char *userformat, char *printfformat, <type> data
956 * char *userformat a list of possible
957 * format characters the
958 * end user might pass us
959 * in the format string
960 * (e.g. those found in
961 * taginfo or loginfo)
962 * multiple characters in
963 * this strings will be
964 * aliases for each other
965 * char *printfformat the same list of args
967 * determine what kind of
968 * data the next arg will
970 * <type> data a piece of data to be
971 * formatted into the user
974 * printfformat string.
976 * char *userformat, char *printfformat, List *data,
977 * int (*convproc) (Node *, void *), void *closure
979 * char *userformat same as above, except
980 * multiple characters in
981 * this string represent
983 * attributes which can be
984 * retrieved from data by
986 * char *printfformat = ","
987 * List *data the list to be walked
989 * convproc to retrieve
990 * data for each of the
994 * int (*convproc)() see data
995 * void *closure arg to be passed into
996 * walklist as closure
1000 * (ignoring oldway variable and srepos since those are only around while we
1001 * SUPPORT_OLD_INFO_FMT_STRINGS)
1002 * format_cmdline ("/cvsroot/CVSROOT/mytaginfoproc %t %o %{sVv}",
1003 * "t", "s", "newtag",
1005 * "xG", "ld", longintwhichwontbeusedthispass,
1006 * "sVv", ",", tlist, pretag_list_to_args_proc,
1010 * would generate the following command line, assuming two files in tlist,
1011 * file1 & file2, each with old versions 1.1 and new version 1.1.2.3:
1013 * /cvsroot/CVSROOT/mytaginfoproc "newtag" "mov" "file1" "1.1" "1.1.2.3" "file2" "1.1" "1.1.2.3"
1016 * pointer to newly allocated string. the caller is responsible for
1017 * disposing of this string.
1020 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1021 format_cmdline (bool oldway
, const char *srepos
, const char *format
, ...)
1022 #else /* SUPPORT_OLD_INFO_FMT_STRINGS */
1023 format_cmdline (const char *format
, ...)
1024 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1026 va_list args
; /* our input function args */
1027 char *buf
; /* where we store our output string */
1028 size_t length
; /* the allocated length of our output string in bytes.
1029 * used as a temporary storage for the length of the
1030 * next function argument during function
1033 char *pfmt
; /* initially the list of fmt keys passed in,
1034 * but used as a temporary key buffer later
1036 char *fmt
; /* buffer for format string which we are processing */
1037 size_t flen
; /* length of fmt buffer */
1038 char *d
, *q
, *r
; /* for walking strings */
1043 List
*pflist
= getlist(); /* our list of input data indexed by format
1047 struct cmdline_bindings
*b
;
1048 static int warned_of_deprecation
= 0;
1049 char key
[] = "?"; /* Used as temporary storage for a single
1050 * character search string used to locate a
1053 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1054 /* state varialbes in the while loop which parses the actual
1055 * format string in the final parsing pass*/
1057 int subbedsomething
;
1058 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1060 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1061 if (oldway
&& !warned_of_deprecation
)
1063 /* warn the user that we don't like his kind 'round these parts */
1064 warned_of_deprecation
= 1;
1066 "warning: Set to use deprecated info format strings. Establish\n"
1067 "compatibility with the new info file format strings (add a temporary '1' in\n"
1068 "all info files after each '%%' which doesn't represent a literal percent)\n"
1069 "and set UseNewInfoFmtStrings=yes in CVSROOT/config. After that, convert\n"
1070 "individual command lines and scripts to handle the new format at your\n"
1073 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1075 va_start (args
, format
);
1077 /* read our possible format strings
1078 * expect a certain number of arguments by type and a NULL format
1079 * string to terminate the list.
1081 while ((pfmt
= va_arg (args
, char *)) != NULL
)
1083 char *conversion
= va_arg (args
, char *);
1085 char conversion_error
= 0;
1086 char char_conversion
= 0;
1087 char decimal_conversion
= 0;
1088 char integer_conversion
= 0;
1089 char string_conversion
= 0;
1091 /* allocate space to save our data */
1092 b
= xmalloc(sizeof(struct cmdline_bindings
));
1094 /* where did you think we were going to store all this data??? */
1098 /* read a length from the conversion string */
1101 while (!length
&& *s
)
1106 integer_conversion
= 1;
1109 length
= sizeof (char);
1114 char_conversion
= 1;
1115 length
= sizeof (short);
1119 #ifdef HAVE_INTMAX_T
1121 integer_conversion
= 1;
1122 length
= sizeof (intmax_t);
1125 #endif /* HAVE_INTMAX_T */
1127 integer_conversion
= 1;
1130 #ifdef HAVE_LONG_LONG
1131 length
= sizeof (long long);
1137 char_conversion
= 2;
1138 string_conversion
= 2;
1139 length
= sizeof (long);
1144 integer_conversion
= 1;
1145 length
= sizeof (ptrdiff_t);
1149 integer_conversion
= 1;
1150 length
= sizeof (size_t);
1153 #ifdef HAVE_LONG_DOUBLE
1155 decimal_conversion
= 1;
1156 length
= sizeof (long double);
1161 char_conversion
= 1;
1162 decimal_conversion
= 1;
1163 integer_conversion
= 1;
1164 string_conversion
= 1;
1165 /* take care of it when we find out what we're looking for */
1170 /* if we don't have a valid conversion left, that is an error */
1171 /* read an argument conversion */
1172 buf
= xmalloc (strlen(conversion
) + 2);
1174 strcpy (buf
+1, conversion
);
1178 /* chars (an integer conversion) */
1179 if (!char_conversion
)
1181 conversion_error
= 1;
1184 if (char_conversion
== 2)
1187 length
= sizeof (wint_t);
1189 conversion_error
= 1;
1194 length
= sizeof (char);
1195 /* fall through... */
1202 /* integer conversions */
1203 if (!integer_conversion
)
1205 conversion_error
= 1;
1210 length
= sizeof (int);
1216 char arg_char
= (char) va_arg (args
, int);
1217 b
->data
= Xasprintf (buf
, arg_char
);
1220 #ifdef UNIQUE_INT_TYPE_WINT_T /* implies HAVE_WINT_T */
1221 case sizeof(wint_t):
1223 wint_t arg_wint_t
= va_arg (args
, wint_t);
1224 b
->data
= Xasprintf (buf
, arg_wint_t
);
1227 #endif /* UNIQUE_INT_TYPE_WINT_T */
1228 #ifdef UNIQUE_INT_TYPE_SHORT
1231 short arg_short
= (short) va_arg (args
, int);
1232 b
->data
= Xasprintf (buf
, arg_short
);
1235 #endif /* UNIQUE_INT_TYPE_SHORT */
1236 #ifdef UNIQUE_INT_TYPE_INT
1239 int arg_int
= va_arg (args
, int);
1240 b
->data
= Xasprintf(buf
, arg_int
);
1243 #endif /* UNIQUE_INT_TYPE_INT */
1244 #ifdef UNIQUE_INT_TYPE_LONG
1247 long arg_long
= va_arg (args
, long);
1248 b
->data
= Xasprintf (buf
, arg_long
);
1251 #endif /* UNIQUE_INT_TYPE_LONG */
1252 #ifdef UNIQUE_INT_TYPE_LONG_LONG /* implies HAVE_LONG_LONG */
1253 case sizeof(long long):
1255 long long arg_long_long
= va_arg (args
, long long);
1256 b
->data
= Xasprintf (buf
, arg_long_long
);
1259 #endif /* UNIQUE_INT_TYPE_LONG_LONG */
1260 #ifdef UNIQUE_INT_TYPE_INTMAX_T /* implies HAVE_INTMAX_T */
1261 case sizeof(intmax_t):
1263 intmax_t arg_intmax_t
= va_arg (args
, intmax_t);
1264 b
->data
= Xasprintf (buf
, arg_intmax_t
);
1267 #endif /* UNIQUE_INT_TYPE_INTMAX_T */
1268 #ifdef UNIQUE_INT_TYPE_SIZE_T
1269 case sizeof(size_t):
1271 size_t arg_size_t
= va_arg (args
, size_t);
1272 b
->data
= Xasprintf (buf
, arg_size_t
);
1275 #endif /* UNIQUE_INT_TYPE_SIZE_T */
1276 #ifdef UNIQUE_INT_TYPE_PTRDIFF_T
1277 case sizeof(ptrdiff_t):
1279 ptrdiff_t arg_ptrdiff_t
= va_arg (args
, ptrdiff_t);
1280 b
->data
= Xasprintf (buf
, arg_ptrdiff_t
);
1283 #endif /* UNIQUE_INT_TYPE_PTRDIFF_T */
1288 "internal error: unknown integer arg size (%d)",
1301 /* decimal conversions */
1302 if (!decimal_conversion
)
1304 conversion_error
= 1;
1309 length
= sizeof (double);
1313 case sizeof(double):
1315 double arg_double
= va_arg (args
, double);
1316 b
->data
= Xasprintf (buf
, arg_double
);
1319 #ifdef UNIQUE_FLOAT_TYPE_LONG_DOUBLE /* implies HAVE_LONG_DOUBLE */
1320 case sizeof(long double):
1322 long double arg_long_double
= va_arg (args
, long double);
1323 b
->data
= Xasprintf (buf
, arg_long_double
);
1326 #endif /* UNIQUE_FLOAT_TYPE_LONG_DOUBLE */
1331 "internal error: unknown floating point arg size (%d)",
1337 switch (string_conversion
)
1340 b
->data
= xstrdup (va_arg (args
, char *));
1345 wchar_t *arg_wchar_t_string
= va_arg (args
, wchar_t *);
1346 b
->data
= Xasprintf (buf
, arg_wchar_t_string
);
1349 #endif /* HAVE_WCHAR_T */
1351 conversion_error
= 1;
1358 conversion_error
= 1;
1361 b
->data
= va_arg (args
, List
*);
1362 b
->convproc
= va_arg (args
, CONVPROC_t
);
1363 b
->closure
= va_arg (args
, void *);
1366 conversion_error
= 1;
1370 /* fail if we found an error or haven't found the end of the string */
1371 if (conversion_error
|| s
[1])
1374 "internal error (format_cmdline): '%s' is not a valid conversion!!!",
1379 /* save our type - we really only care wheter it's a list type (',')
1380 * or not from now on, but what the hell...
1384 /* separate the user format string into parts and stuff our data into
1385 * the pflist (once for each possible string - diverse keys can have
1391 struct cmdline_bindings
*tb
;
1395 while (*++q
&& *q
!= '}');
1405 /* copy the data since we'll need it again */
1406 tb
= xmalloc(sizeof(struct cmdline_bindings
));
1407 if (b
->conversion
== ',')
1413 tb
->data
= xstrdup(b
->data
);
1415 tb
->conversion
= b
->conversion
;
1416 tb
->convproc
= b
->convproc
;
1417 tb
->closure
= b
->closure
;
1421 /* we're done after this, so we don't need to copy the data */
1425 p
->key
= xmalloc((q
- s
) + 1);
1426 strncpy (p
->key
, s
, q
- s
);
1429 p
->delproc
= cmdline_bindings_hash_node_delete
;
1434 /* we're done with va_list */
1437 /* All formatted strings include a format character that resolves to the
1438 * empty string by default, so put it in pflist.
1440 /* allocate space to save our data */
1441 b
= xmalloc(sizeof(struct cmdline_bindings
));
1442 b
->conversion
= 's';
1445 b
->data
= xstrdup( "" );
1447 p
->key
= xstrdup( "n" );
1449 p
->delproc
= cmdline_bindings_hash_node_delete
;
1450 addnode( pflist
,p
);
1452 /* finally, read the user string and copy it into rargv as appropriate */
1453 /* user format strings look as follows:
1456 * \X, where X is any character = \X, (this is the escape you'd expect, but
1457 * we are leaving the \ for an expected final pass which splits our
1458 * output string into separate arguments
1460 * %X means sub var "X" into location
1461 * %{VWXYZ} means sub V,W,X,Y,Z into location as a single arg. The shell
1462 * || would be to quote the comma separated arguments. Each list
1463 * that V, W, X, Y, and Z represent attributes of will cause a new
1464 * tuple to be inserted for each list item with a space between
1466 * e.g."V W1,X1,Z1 W2,X2,Z2 W3,X3,Z3 Y1 Y2" where V is not a list
1467 * variable, W,X,&Z are attributes of a list with 3 items and Y is an
1468 * attribute of a second list with 2 items.
1469 * %,{VWXYZ} means to separate the args. The previous example would produce
1470 * V W1 X1 Z1 W2 X2 Z2 W3 X3 Z3 Y1 Y2, where each variable is now a
1471 * separate, space delimited, arguments within a single argument.
1472 * a%{XY}, where 'a' is a literal, still produces a single arg (a"X Y", in
1474 * a%1{XY}, where 'a' is a literal, splits the literal as it produces
1475 * multiple args (a X Y). The rule is that each sub will produce a
1476 * separate arg. Without a comma, attributes will still be grouped
1477 * together & comma separated in what could be a single argument,
1478 * but internal quotes, commas, and spaces are not excaped.
1480 * clearing the variable oldway, passed into this function, causes the
1481 * behavior of '1' and "," in the format string to reverse.
1484 /* for convenience, use fmt as a temporary key buffer.
1485 * for speed, attempt to realloc it as little as possible
1490 /* buf = current argv entry being built
1491 * length = current length of buf
1492 * s = next char in source buffer to read
1493 * d = next char location to write (in buf)
1494 * inquotes = current quote char or NUL
1500 expand_string (&buf
, &length
, doff
+ 1);
1504 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1505 subbedsomething
= 0;
1506 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1507 while ((*d
++ = *s
) != '\0')
1513 /* the character after a \ goes unprocessed but leave the \ in
1514 * the string so the function that splits this string into a
1515 * command line later can deal with quotes properly
1522 expand_string (&buf
, &length
, doff
+ 1);
1529 /* keep track of quotes so we can escape quote chars we sub in
1530 * - the API is that a quoted format string will guarantee that
1531 * it gets passed into the command as a single arg
1533 if (!inquotes
) inquotes
= s
[-1];
1534 else if (s
[-1] == inquotes
) inquotes
= '\0';
1539 /* "%%" is a literal "%" */
1543 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1544 if (oldway
&& subbedsomething
)
1546 /* the old method was to sub only the first format string */
1549 /* initialize onearg each time we get a new format string */
1550 onearg
= oldway
? 1 : 0;
1551 subbedsomething
= 1;
1552 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1553 d
--; /* we're going to overwrite the '%' regardless
1554 * of other factors... */
1555 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1556 /* detect '1' && ',' in the fmt string. */
1563 /* FIXME - add FILE && LINE */
1565 "Using deprecated info format strings. Convert your scripts to use\n"
1566 "the new argument format and remove '1's from your info file format strings.");
1569 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1571 /* parse the format string and sub in... */
1584 expand_string (&fmt
, &flen
, qoff
+ 1);
1586 } while ((*q
= *s
++) && list
&& *q
++ != '}');
1587 /* we will always copy one character, so, whether in list mode
1588 * or not, if we just copied a '\0', then we hit the end of the
1589 * string before we should have
1593 /* if we copied a NUL while processing a list, fail
1594 * - we had an empty fmt string or didn't find a list
1597 /* FIXME - this wants a file name and line number in a bad
1601 "unterminated format string encountered in command spec.\n"
1602 "This error is likely to have been caused by an invalid line in a hook script\n"
1603 "spec (see taginfo, loginfo, verifymsginfo, etc. in the Cederqvist). Most\n"
1604 "likely the offending line would end with a '%%' character or contain a string\n"
1605 "beginning \"%%{\" and no closing '}' before the end of the line.");
1613 /* We're not in a list, so we must have just copied a
1614 * single character. Terminate the string.
1618 expand_string (&fmt
, &flen
, qoff
+ 1);
1622 /* fmt is now a pointer to a list of fmt chars, though the list
1623 * could be a single element one
1626 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1627 /* always add quotes in the deprecated onearg case - for
1628 * backwards compatibility
1633 expand_string (&buf
, &length
, doff
+ 1);
1637 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1639 * for each character in the fmt string,
1641 * all output will be separate quoted arguments (with
1642 * internal quotes escaped) if the argument is in quotes
1643 * unless the oldway variable is set, in which case the fmt
1644 * statment will correspond to a single argument with
1645 * internal space or comma delimited arguments
1647 * see the "user format strings" section above for more info
1650 if ((p
= findnode (pflist
, key
)) != NULL
)
1653 if (b
->conversion
== ',')
1655 /* process the rest of the format string as a list */
1656 struct format_cmdline_walklist_closure c
;
1661 c
.quotes
= inquotes
;
1662 c
.closure
= b
->closure
;
1663 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1667 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1668 walklist(b
->data
, b
->convproc
, &c
);
1669 d
--; /* back up one space. we know that ^
1670 always adds 1 extra */
1675 /* got a flat item */
1680 "Multiple non-list variables are not allowed in a single format string.");
1682 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1689 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1690 /* the *only* case possible without
1691 * SUPPORT_OLD_INFO_FORMAT_STRINGS
1696 expand_string (&buf
, &length
, doff
+ 1);
1700 outstr
= cmdlineescape (inquotes
? inquotes
: '"', b
->data
);
1701 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1703 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1705 expand_string (&buf
, &length
, doff
+ strlen(outstr
));
1707 strncpy(d
, outstr
, strlen(outstr
));
1708 d
+= strlen(outstr
);
1709 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1713 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1717 expand_string (&buf
, &length
, doff
+ 1);
1721 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1723 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1727 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1730 /* the old standard was to ignore unknown format
1731 * characters (print the empty string), but also that
1732 * any format character meant print srepos first
1736 expand_string (&buf
, &length
, doff
+ strlen(srepos
));
1738 strncpy(d
, srepos
, strlen(srepos
));
1739 d
+= strlen(srepos
);
1741 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1744 /* print an error message to the user
1745 * FIXME - this should have a file and line number!!! */
1747 "Unknown format character in info file ('%s').\n"
1748 "Info files are the hook files, verifymsg, taginfo, commitinfo, etc.",
1751 #ifdef SUPPORT_OLD_INFO_FMT_STRINGS
1752 /* always add quotes in the deprecated onearg case - for
1753 * backwards compatibility
1758 expand_string (&buf
, &length
, doff
+ 1);
1762 #endif /* SUPPORT_OLD_INFO_FMT_STRINGS */
1766 expand_string (&buf
, &length
, doff
+ 1);
1768 } /* while (*d++ = *s) */
1769 if (fmt
) free (fmt
);
1772 /* FIXME - we shouldn't need this - Parse_Info should be handling
1775 error (1, 0, "unterminated quote in format string: %s", format
);
1784 /* Like xstrdup (), but can handle a NULL argument.
1787 Xstrdup (const char *string
)
1789 if (string
== NULL
) return NULL
;
1790 return xmemdup (string
, strlen (string
) + 1);
1795 /* Like xasprintf(), but consider all errors fatal (may never return NULL).
1798 Xasprintf (const char *format
, ...)
1803 va_start (args
, format
);
1804 if (vasprintf (&result
, format
, args
) < 0)
1805 error (1, errno
, "Failed to write to string.");
1813 /* Like xasnprintf(), but consider all errors fatal (may never return NULL).
1816 Xasnprintf (char *resultbuf
, size_t *lengthp
, const char *format
, ...)
1821 va_start (args
, format
);
1822 result
= vasnprintf (resultbuf
, lengthp
, format
, args
);
1824 error (1, errno
, "Failed to write to string.");
1832 /* Print a warning and return false if P doesn't look like a string specifying
1835 * Sets *VAL to the parsed value when it is found to be valid. *VAL will not
1836 * be altered when false is returned.
1839 * infopath Where the error is reported to be from on error. This could
1840 * be, for example, the name of the file the boolean is being read
1842 * option An option name being parsed, reported in traces and any error
1844 * p The string to actually read the option from.
1845 * val Pointer to where to store the boolean read from P.
1848 * val TRUE/FALSE stored, as read, when there are no errors.
1851 * true If VAL was read.
1855 readBool (const char *infopath
, const char *option
, const char *p
, bool *val
)
1857 TRACE (TRACE_FLOW
, "readBool (%s, %s, %s)", infopath
, option
, p
);
1858 if (!strcasecmp (p
, "no") || !strcasecmp (p
, "false")
1859 || !strcasecmp (p
, "off") || !strcmp (p
, "0"))
1861 TRACE (TRACE_DATA
, "Read %d for %s", *val
, option
);
1865 else if (!strcasecmp (p
, "yes") || !strcasecmp (p
, "true")
1866 || !strcasecmp (p
, "on") || !strcmp (p
, "1"))
1868 TRACE (TRACE_DATA
, "Read %d for %s", *val
, option
);
1873 error (0, 0, "%s: unrecognized value `%s' for `%s'",
1874 infopath
, p
, option
);
1881 * Open a file, exiting with a message on error.
1884 * name The name of the file to open.
1885 * mode Mode to open file in, as POSIX fopen().
1888 * If you want to handle errors, just call fopen (NAME, MODE).
1891 * The new FILE pointer.
1894 xfopen (const char *name
, const char *mode
)
1898 if (!(fp
= fopen (name
, mode
)))
1899 error (1, errno
, "cannot open %s", name
);
1906 * xcanonicalize_file_name (const char *path)
1908 * Like canonicalize_file_name(), but exit on error.
1911 * path The original path.
1914 * The path with any symbolic links, `.'s, or `..'s, expanded.
1917 * This function exits with a fatal error if it fails to read the link for
1921 xcanonicalize_file_name (const char *path
)
1923 char *hardpath
= canonicalize_file_name (path
);
1925 error (1, errno
, "Failed to resolve path: `%s'", path
);
1931 /* Declared in main.c. */
1932 extern char *server_hostname
;
1934 /* Return true if OTHERHOST resolves to this host in the DNS.
1937 * server_hostname The name of this host, as determined by the call to
1938 * xgethostname() in main().
1941 * true If OTHERHOST equals or resolves to HOSTNAME.
1945 isThisHost (const char *otherhost
)
1951 /* As an optimization, check the literal strings before looking up
1952 * OTHERHOST in the DNS.
1954 if (!strcasecmp (server_hostname
, otherhost
))
1957 fqdno
= canon_host (otherhost
);
1959 error (1, 0, "Name lookup failed for `%s': %s",
1960 otherhost
, ch_strerror ());
1961 fqdns
= canon_host (server_hostname
);
1963 error (1, 0, "Name lookup failed for `%s': %s",
1964 server_hostname
, ch_strerror ());
1966 retval
= !strcasecmp (fqdns
, fqdno
);
1975 /* Return true if two paths match, resolving symlinks.
1978 isSamePath (const char *path1_in
, const char *path2_in
)
1983 if (!strcmp (path1_in
, path2_in
))
1986 /* Path didn't match, but try to resolve any links that may be
1989 if (!isdir (path1_in
) || !isdir (path2_in
))
1990 /* To be resolvable, paths must exist on this server. */
1993 p1
= xcanonicalize_file_name (path1_in
);
1994 p2
= xcanonicalize_file_name (path2_in
);
1995 if (strcmp (p1
, p2
))