117721Speter/* 2175261Sobrien * Copyright (C) 1986-2005 The Free Software Foundation, Inc. 3175261Sobrien * 4175261Sobrien * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>, 5175261Sobrien * and others. 6175261Sobrien * 7175261Sobrien * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk 8175261Sobrien * Portions Copyright (C) 1989-1992, Brian Berliner 917721Speter * 1017721Speter * You may distribute under the terms of the GNU General Public License as 1132785Speter * specified in the README file that comes with the CVS source distribution. 1217721Speter * 1317721Speter * Various useful functions for the CVS support code. 1417721Speter */ 1517721Speter 16128266Speter#include <assert.h> 1717721Speter#include "cvs.h" 1825839Speter#include "getline.h" 1917721Speter 2081404Speter#ifdef HAVE_NANOSLEEP 2181404Speter# include "xtime.h" 2281404Speter#else /* HAVE_NANOSLEEP */ 2381404Speter# if !defined HAVE_USLEEP && defined HAVE_SELECT 2481404Speter /* use select as a workaround */ 2581404Speter# include "xselect.h" 2681404Speter# endif /* !defined HAVE_USLEEP && defined HAVE_SELECT */ 2781404Speter#endif /* !HAVE_NANOSLEEP */ 2881404Speter 2917721Speterextern char *getlogin (); 3017721Speter 3117721Speter/* 3217721Speter * malloc some data and die if it fails 3317721Speter */ 3454427Spetervoid * 3517721Speterxmalloc (bytes) 3617721Speter size_t bytes; 3717721Speter{ 3817721Speter char *cp; 3917721Speter 4017721Speter /* Parts of CVS try to xmalloc zero bytes and then free it. Some 4117721Speter systems have a malloc which returns NULL for zero byte 4217721Speter allocations but a free which can't handle NULL, so compensate. */ 4317721Speter if (bytes == 0) 4417721Speter bytes = 1; 4517721Speter 4617721Speter cp = malloc (bytes); 4717721Speter if (cp == NULL) 4854427Speter { 4954427Speter char buf[80]; 5054427Speter sprintf (buf, "out of memory; can not allocate %lu bytes", 5154427Speter (unsigned long) bytes); 5254427Speter error (1, 0, buf); 5354427Speter } 5417721Speter return (cp); 5517721Speter} 5617721Speter 5717721Speter/* 5817721Speter * realloc data and die if it fails [I've always wanted to have "realloc" do 5917721Speter * a "malloc" if the argument is NULL, but you can't depend on it. Here, I 60128266Speter * can *force* it.] 6117721Speter */ 6217721Spetervoid * 6317721Speterxrealloc (ptr, bytes) 6417721Speter void *ptr; 6517721Speter size_t bytes; 6617721Speter{ 6717721Speter char *cp; 6817721Speter 6917721Speter if (!ptr) 7017721Speter cp = malloc (bytes); 7117721Speter else 7217721Speter cp = realloc (ptr, bytes); 7317721Speter 7417721Speter if (cp == NULL) 7554427Speter { 7654427Speter char buf[80]; 7754427Speter sprintf (buf, "out of memory; can not reallocate %lu bytes", 7854427Speter (unsigned long) bytes); 7954427Speter error (1, 0, buf); 8054427Speter } 8117721Speter return (cp); 8217721Speter} 8317721Speter 8425839Speter/* Two constants which tune expand_string. Having MIN_INCR as large 8525839Speter as 1024 might waste a bit of memory, but it shouldn't be too bad 8625839Speter (CVS used to allocate arrays of, say, 3000, PATH_MAX (8192, often), 8725839Speter or other such sizes). Probably anything which is going to allocate 8825839Speter memory which is likely to get as big as MAX_INCR shouldn't be doing 8925839Speter it in one block which must be contiguous, but since getrcskey does 9025839Speter so, we might as well limit the wasted memory to MAX_INCR or so 9154427Speter bytes. 9225839Speter 9354427Speter MIN_INCR and MAX_INCR should both be powers of two and we generally 9454427Speter try to keep our allocations to powers of two for the most part. 9554427Speter Most malloc implementations these days tend to like that. */ 9654427Speter 9725839Speter#define MIN_INCR 1024 9825839Speter#define MAX_INCR (2*1024*1024) 9925839Speter 10025839Speter/* *STRPTR is a pointer returned from malloc (or NULL), pointing to *N 10125839Speter characters of space. Reallocate it so that points to at least 10225839Speter NEWSIZE bytes of space. Gives a fatal error if out of memory; 10325839Speter if it returns it was successful. */ 10425839Spetervoid 10525839Speterexpand_string (strptr, n, newsize) 10625839Speter char **strptr; 10725839Speter size_t *n; 10825839Speter size_t newsize; 10925839Speter{ 11025839Speter if (*n < newsize) 11125839Speter { 11225839Speter while (*n < newsize) 11325839Speter { 11425839Speter if (*n < MIN_INCR) 11554427Speter *n = MIN_INCR; 11654427Speter else if (*n >= MAX_INCR) 11725839Speter *n += MAX_INCR; 11825839Speter else 11954427Speter { 12025839Speter *n *= 2; 12154427Speter if (*n > MAX_INCR) 12254427Speter *n = MAX_INCR; 12354427Speter } 12425839Speter } 12525839Speter *strptr = xrealloc (*strptr, *n); 12625839Speter } 12725839Speter} 12825839Speter 12981404Speter/* *STR is a pointer to a malloc'd string. *LENP is its allocated 13081404Speter length. Add SRC to the end of it, reallocating if necessary. */ 13181404Spetervoid 132102840Speterxrealloc_and_strcat (str, lenp, src) 13381404Speter char **str; 13481404Speter size_t *lenp; 13581404Speter const char *src; 13681404Speter{ 13781404Speter 13881404Speter expand_string (str, lenp, strlen (*str) + strlen (src) + 1); 13981404Speter strcat (*str, src); 14081404Speter} 14181404Speter 14217721Speter/* 14317721Speter * Duplicate a string, calling xmalloc to allocate some dynamic space 14417721Speter */ 14517721Speterchar * 14617721Speterxstrdup (str) 14717721Speter const char *str; 14817721Speter{ 14917721Speter char *s; 15017721Speter 15117721Speter if (str == NULL) 15217721Speter return ((char *) NULL); 15317721Speter s = xmalloc (strlen (str) + 1); 15417721Speter (void) strcpy (s, str); 15517721Speter return (s); 15617721Speter} 15717721Speter 158128266Speter 159128266Speter 160128266Speter/* Remove trailing newlines from STRING, destructively. 161128266Speter * 162128266Speter * RETURNS 163128266Speter * 164128266Speter * True if any newlines were removed, false otherwise. 165128266Speter */ 166128266Speterint 16717721Speterstrip_trailing_newlines (str) 168128266Speter char *str; 16917721Speter{ 170128266Speter size_t index, origlen; 171128266Speter index = origlen = strlen (str); 17217721Speter 173128266Speter while (index > 0 && str[index-1] == '\n') 174128266Speter str[--index] = '\0'; 175128266Speter 176128266Speter return index != origlen; 17717721Speter} 17817721Speter 179128266Speter 180128266Speter 181128266Speter/* Return the number of levels that PATH ascends above where it starts. 182128266Speter * For example: 183128266Speter * 184128266Speter * "../../foo" -> 2 185128266Speter * "foo/../../bar" -> 1 186128266Speter */ 18725839Speterint 188128266Speterpathname_levels (p) 189128266Speter const char *p; 19025839Speter{ 19125839Speter int level; 19225839Speter int max_level; 19325839Speter 194128266Speter if (p == NULL) return 0; 195128266Speter 19625839Speter max_level = 0; 19725839Speter level = 0; 19825839Speter do 19925839Speter { 200128266Speter /* Now look for pathname level-ups. */ 201128266Speter if (p[0] == '.' && p[1] == '.' && (p[2] == '\0' || ISDIRSEP (p[2]))) 20225839Speter { 20325839Speter --level; 20425839Speter if (-level > max_level) 20525839Speter max_level = -level; 20625839Speter } 207128266Speter else if (p[0] == '\0' || ISDIRSEP (p[0]) || 208128266Speter (p[0] == '.' && (p[1] == '\0' || ISDIRSEP (p[1])))) 20925839Speter ; 21025839Speter else 21125839Speter ++level; 212128266Speter 213128266Speter /* q = strchr (p, '/'); but sub ISDIRSEP() for '/': */ 214128266Speter while (*p != '\0' && !ISDIRSEP (*p)) p++; 215128266Speter if (*p != '\0') p++; 216128266Speter } while (*p != '\0'); 21725839Speter return max_level; 21825839Speter} 21925839Speter 220128266Speter 221128266Speter 22226065Speter/* Free a vector, where (*ARGV)[0], (*ARGV)[1], ... (*ARGV)[*PARGC - 1] 22326065Speter are malloc'd and so is *ARGV itself. Such a vector is allocated by 22426065Speter line2argv or expand_wild, for example. */ 22517721Spetervoid 22617721Speterfree_names (pargc, argv) 22717721Speter int *pargc; 22817721Speter char **argv; 22917721Speter{ 23017721Speter register int i; 23117721Speter 23217721Speter for (i = 0; i < *pargc; i++) 23317721Speter { /* only do through *pargc */ 23417721Speter free (argv[i]); 23517721Speter } 23625839Speter free (argv); 23717721Speter *pargc = 0; /* and set it to zero when done */ 23817721Speter} 23917721Speter 24032785Speter/* Convert LINE into arguments separated by SEPCHARS. Set *ARGC 24125839Speter to the number of arguments found, and (*ARGV)[0] to the first argument, 24225839Speter (*ARGV)[1] to the second, etc. *ARGV is malloc'd and so are each of 24325839Speter (*ARGV)[0], (*ARGV)[1], ... Use free_names() to return the memory 24425839Speter allocated here back to the free pool. */ 24517721Spetervoid 24632785Speterline2argv (pargc, argv, line, sepchars) 24717721Speter int *pargc; 24825839Speter char ***argv; 24917721Speter char *line; 25032785Speter char *sepchars; 25117721Speter{ 25217721Speter char *cp; 25325839Speter /* Could make a case for size_t or some other unsigned type, but 25425839Speter we'll stick with int to avoid signed/unsigned warnings when 25525839Speter comparing with *pargc. */ 25625839Speter int argv_allocated; 25717721Speter 25825839Speter /* Small for testing. */ 25966525Speter argv_allocated = 1; 26025839Speter *argv = (char **) xmalloc (argv_allocated * sizeof (**argv)); 26125839Speter 26217721Speter *pargc = 0; 26332785Speter for (cp = strtok (line, sepchars); cp; cp = strtok ((char *) NULL, sepchars)) 26417721Speter { 26525839Speter if (*pargc == argv_allocated) 26625839Speter { 26725839Speter argv_allocated *= 2; 26825839Speter *argv = xrealloc (*argv, argv_allocated * sizeof (**argv)); 26925839Speter } 27025839Speter (*argv)[*pargc] = xstrdup (cp); 27117721Speter (*pargc)++; 27217721Speter } 27317721Speter} 27417721Speter 27517721Speter/* 27617721Speter * Returns the number of dots ('.') found in an RCS revision number 27717721Speter */ 27817721Speterint 27917721Speternumdots (s) 28017721Speter const char *s; 28117721Speter{ 28217721Speter int dots = 0; 28317721Speter 28417721Speter for (; *s; s++) 28517721Speter { 28617721Speter if (*s == '.') 28717721Speter dots++; 28817721Speter } 28917721Speter return (dots); 29017721Speter} 29117721Speter 29232785Speter/* Compare revision numbers REV1 and REV2 by consecutive fields. 29332785Speter Return negative, zero, or positive in the manner of strcmp. The 29432785Speter two revision numbers must have the same number of fields, or else 29532785Speter compare_revnums will return an inaccurate result. */ 29632785Speterint 29732785Spetercompare_revnums (rev1, rev2) 29832785Speter const char *rev1; 29932785Speter const char *rev2; 30032785Speter{ 301128266Speter const char *sp, *tp; 30232785Speter char *snext, *tnext; 30332785Speter int result = 0; 30432785Speter 305128266Speter sp = rev1; 306128266Speter tp = rev2; 30732785Speter while (result == 0) 30832785Speter { 30932785Speter result = strtoul (sp, &snext, 10) - strtoul (tp, &tnext, 10); 31032785Speter if (*snext == '\0' || *tnext == '\0') 31132785Speter break; 31232785Speter sp = snext + 1; 31332785Speter tp = tnext + 1; 31432785Speter } 31532785Speter 31632785Speter return result; 31732785Speter} 31832785Speter 319130303Speter/* Increment a revision number. Working on the string is a bit awkward, 320130303Speter but it avoid problems with integer overflow should the revision numbers 321130303Speter get really big. */ 32232785Speterchar * 32332785Speterincrement_revnum (rev) 32432785Speter const char *rev; 32532785Speter{ 32632785Speter char *newrev, *p; 32732785Speter size_t len = strlen (rev); 32832785Speter 329130303Speter newrev = xmalloc (len + 2); 33032785Speter memcpy (newrev, rev, len + 1); 331130303Speter for (p = newrev + len; p != newrev; ) 33232785Speter { 333130303Speter --p; 334130303Speter if (!isdigit(*p)) 335130303Speter { 336130303Speter ++p; 337130303Speter break; 338130303Speter } 339130303Speter if (*p != '9') 340130303Speter { 341130303Speter ++*p; 342130303Speter return newrev; 343130303Speter } 344130303Speter *p = '0'; 34532785Speter } 346130303Speter /* The number was all 9s, so change the first character to 1 and add 347130303Speter a 0 to the end. */ 348130303Speter *p = '1'; 349130303Speter p = newrev + len; 350130303Speter *p++ = '0'; 351130303Speter *p = '\0'; 35232785Speter return newrev; 35332785Speter} 35432785Speter 35526801Speter/* Return the username by which the caller should be identified in 35626801Speter CVS, in contexts such as the author field of RCS files, various 35734461Speter logs, etc. */ 35817721Speterchar * 35917721Spetergetcaller () 36017721Speter{ 36132785Speter#ifndef SYSTEM_GETCALLER 36234461Speter static char *cache; 36317721Speter struct passwd *pw; 36417721Speter uid_t uid; 36532785Speter#endif 36617721Speter 36726801Speter /* If there is a CVS username, return it. */ 36826801Speter#ifdef AUTH_SERVER_SUPPORT 36926801Speter if (CVS_Username != NULL) 37026801Speter return CVS_Username; 37126801Speter#endif 37226801Speter 37332785Speter#ifdef SYSTEM_GETCALLER 37432785Speter return SYSTEM_GETCALLER (); 37532785Speter#else 37626801Speter /* Get the caller's login from his uid. If the real uid is "root" 37726801Speter try LOGNAME USER or getlogin(). If getlogin() and getpwuid() 37826801Speter both fail, return the uid as a string. */ 37926801Speter 38034461Speter if (cache != NULL) 38134461Speter return cache; 38234461Speter 38317721Speter uid = getuid (); 38417721Speter if (uid == (uid_t) 0) 38517721Speter { 38634461Speter char *name; 38734461Speter 38817721Speter /* super-user; try getlogin() to distinguish */ 38917721Speter if (((name = getlogin ()) || (name = getenv("LOGNAME")) || 39017721Speter (name = getenv("USER"))) && *name) 39134461Speter { 39234461Speter cache = xstrdup (name); 39334461Speter return cache; 39434461Speter } 39517721Speter } 39617721Speter if ((pw = (struct passwd *) getpwuid (uid)) == NULL) 39717721Speter { 39834461Speter char uidname[20]; 39934461Speter 40017721Speter (void) sprintf (uidname, "uid%lu", (unsigned long) uid); 40134461Speter cache = xstrdup (uidname); 40234461Speter return cache; 40317721Speter } 40434461Speter cache = xstrdup (pw->pw_name); 40534461Speter return cache; 40632785Speter#endif 40717721Speter} 40817721Speter 40917721Speter#ifdef lint 41017721Speter#ifndef __GNUC__ 41117721Speter/* ARGSUSED */ 41217721Spetertime_t 41317721Speterget_date (date, now) 41417721Speter char *date; 41517721Speter struct timeb *now; 41617721Speter{ 41717721Speter time_t foo = 0; 41817721Speter 41917721Speter return (foo); 42017721Speter} 42117721Speter#endif 42217721Speter#endif 42317721Speter 424128266Speter 425128266Speter 426128266Speter/* Given some revision, REV, return the first prior revision that exists in the 427128266Speter * RCS file, RCS. 428128266Speter * 429128266Speter * ASSUMPTIONS 430128266Speter * REV exists. 431128266Speter * 432128266Speter * INPUTS 433128266Speter * RCS The RCS node pointer. 434128266Speter * REV An existing revision in the RCS file referred to by RCS. 435128266Speter * 436128266Speter * RETURNS 437128266Speter * The first prior revision that exists in the RCS file, or NULL if no prior 438128266Speter * revision exists. The caller is responsible for disposing of this string. 439128266Speter * 440128266Speter * NOTES 441128266Speter * This function currently neglects the case where we are on the trunk with 442128266Speter * rev = X.1, where X != 1. If rev = X.Y, where X != 1 and Y > 1, then this 443128266Speter * function should work fine, as revision X.1 must exist, due to RCS rules. 444128266Speter */ 445128266Speterchar * 446128266Speterprevious_rev (rcs, rev) 447128266Speter RCSNode *rcs; 448128266Speter const char *rev; 449128266Speter{ 450128266Speter char *p; 451128266Speter char *tmp = xstrdup (rev); 452128266Speter long r1; 453128266Speter char *retval; 454128266Speter 455128266Speter /* Our retval can have no more digits and dots than our input revision. */ 456128266Speter retval = xmalloc (strlen (rev) + 1); 457128266Speter p = strrchr (tmp, '.'); 458128266Speter *p = '\0'; 459128266Speter r1 = strtol (p+1, NULL, 10); 460128266Speter do { 461128266Speter if (--r1 == 0) 462128266Speter { 463128266Speter /* If r1 == 0, then we must be on a branch and our parent must 464128266Speter * exist, or we must be on the trunk with a REV like X.1. 465128266Speter * We are neglecting the X.1 with X != 1 case by assuming that 466128266Speter * there is no previous revision when we discover we were on 467128266Speter * the trunk. 468128266Speter */ 469128266Speter p = strrchr (tmp, '.'); 470128266Speter if (p == NULL) 471128266Speter /* We are on the trunk. */ 472128266Speter retval = NULL; 473128266Speter else 474128266Speter { 475128266Speter *p = '\0'; 476128266Speter sprintf (retval, "%s", tmp); 477128266Speter } 478128266Speter break; 479128266Speter } 480128266Speter sprintf (retval, "%s.%ld", tmp, r1); 481128266Speter } while (!RCS_exist_rev (rcs, retval)); 482128266Speter 483128266Speter free (tmp); 484128266Speter return retval; 485128266Speter} 486128266Speter 487128266Speter 488128266Speter 48917721Speter/* Given two revisions, find their greatest common ancestor. If the 49017721Speter two input revisions exist, then rcs guarantees that the gca will 49117721Speter exist. */ 49217721Speter 49317721Speterchar * 49417721Spetergca (rev1, rev2) 49532785Speter const char *rev1; 49632785Speter const char *rev2; 49717721Speter{ 49817721Speter int dots; 499107484Speter char *gca, *g; 500107484Speter const char *p1, *p2; 501107484Speter int r1, r2; 50225839Speter char *retval; 50317721Speter 50417721Speter if (rev1 == NULL || rev2 == NULL) 50517721Speter { 50617721Speter error (0, 0, "sanity failure in gca"); 50717721Speter abort(); 50817721Speter } 50917721Speter 51025839Speter /* The greatest common ancestor will have no more dots, and numbers 51125839Speter of digits for each component no greater than the arguments. Therefore 51225839Speter this string will be big enough. */ 513107484Speter g = gca = xmalloc (strlen (rev1) + strlen (rev2) + 100); 51425839Speter 51517721Speter /* walk the strings, reading the common parts. */ 516107484Speter p1 = rev1; 517107484Speter p2 = rev2; 51817721Speter do 51917721Speter { 520107484Speter r1 = strtol (p1, (char **) &p1, 10); 521107484Speter r2 = strtol (p2, (char **) &p2, 10); 52217721Speter 52317721Speter /* use the lowest. */ 524107484Speter (void) sprintf (g, "%d.", r1 < r2 ? r1 : r2); 525107484Speter g += strlen (g); 526107484Speter if (*p1 == '.') ++p1; 527107484Speter else break; 528107484Speter if (*p2 == '.') ++p2; 529107484Speter else break; 530107484Speter } while (r1 == r2); 53117721Speter 532107484Speter /* erase that last dot. */ 533107484Speter *--g = '\0'; 53417721Speter 53517721Speter /* numbers differ, or we ran out of strings. we're done with the 53617721Speter common parts. */ 53717721Speter 53817721Speter dots = numdots (gca); 53917721Speter if (dots == 0) 54017721Speter { 54117721Speter /* revisions differ in trunk major number. */ 54217721Speter 543107484Speter if (r2 < r1) p1 = p2; 544107484Speter if (*p1 == '\0') 54517721Speter { 54617721Speter /* we only got one number. this is strange. */ 54717721Speter error (0, 0, "bad revisions %s or %s", rev1, rev2); 54817721Speter abort(); 54917721Speter } 55017721Speter else 55117721Speter { 55217721Speter /* we have a minor number. use it. */ 553107484Speter *g++ = '.'; 554107484Speter while (*p1 != '.' && *p1 != '\0') 555107484Speter *g++ = *p1++; 556107484Speter *g = '\0'; 55717721Speter } 55817721Speter } 55917721Speter else if ((dots & 1) == 0) 56017721Speter { 56117721Speter /* if we have an even number of dots, then we have a branch. 56217721Speter remove the last number in order to make it a revision. */ 56317721Speter 564107484Speter g = strrchr (gca, '.'); 565107484Speter *g = '\0'; 56617721Speter } 56717721Speter 56825839Speter retval = xstrdup (gca); 56925839Speter free (gca); 57025839Speter return retval; 57117721Speter} 57217721Speter 57332785Speter/* Give fatal error if REV is numeric and ARGC,ARGV imply we are 57432785Speter planning to operate on more than one file. The current directory 57532785Speter should be the working directory. Note that callers assume that we 57632785Speter will only be checking the first character of REV; it need not have 57732785Speter '\0' at the end of the tag name and other niceties. Right now this 57832785Speter is only called from admin.c, but if people like the concept it probably 57932785Speter should also be called from diff -r, update -r, get -r, and log -r. */ 58032785Speter 58132785Spetervoid 58232785Spetercheck_numeric (rev, argc, argv) 58332785Speter const char *rev; 58432785Speter int argc; 58532785Speter char **argv; 58632785Speter{ 58754427Speter if (rev == NULL || !isdigit ((unsigned char) *rev)) 58832785Speter return; 58932785Speter 59032785Speter /* Note that the check for whether we are processing more than one 59132785Speter file is (basically) syntactic; that is, we don't behave differently 59232785Speter depending on whether a directory happens to contain only a single 59332785Speter file or whether it contains more than one. I strongly suspect this 59432785Speter is the least confusing behavior. */ 59532785Speter if (argc != 1 59632785Speter || (!wrap_name_has (argv[0], WRAP_TOCVS) && isdir (argv[0]))) 59732785Speter { 59832785Speter error (0, 0, "while processing more than one file:"); 59932785Speter error (1, 0, "attempt to specify a numeric revision"); 60032785Speter } 60132785Speter} 60232785Speter 60317721Speter/* 60417721Speter * Sanity checks and any required fix-up on message passed to RCS via '-m'. 60517721Speter * RCS 5.7 requires that a non-total-whitespace, non-null message be provided 60632785Speter * with '-m'. Returns a newly allocated, non-empty buffer with whitespace 60732785Speter * stripped from end of lines and end of buffer. 60832785Speter * 60932785Speter * TODO: We no longer use RCS to manage repository files, so maybe this 61032785Speter * nonsense about non-empty log fields can be dropped. 61117721Speter */ 61217721Speterchar * 61317721Spetermake_message_rcslegal (message) 614128266Speter const char *message; 61517721Speter{ 616128266Speter char *dst, *dp; 617128266Speter const char *mp; 61832785Speter 61932785Speter if (message == NULL) message = ""; 62032785Speter 62132785Speter /* Strip whitespace from end of lines and end of string. */ 62232785Speter dp = dst = (char *) xmalloc (strlen (message) + 1); 62332785Speter for (mp = message; *mp != '\0'; ++mp) 62417721Speter { 62532785Speter if (*mp == '\n') 62632785Speter { 62732785Speter /* At end-of-line; backtrack to last non-space. */ 62832785Speter while (dp > dst && (dp[-1] == ' ' || dp[-1] == '\t')) 62932785Speter --dp; 63032785Speter } 63132785Speter *dp++ = *mp; 63232785Speter } 63317721Speter 63432785Speter /* Backtrack to last non-space at end of string, and truncate. */ 63554427Speter while (dp > dst && isspace ((unsigned char) dp[-1])) 63632785Speter --dp; 63732785Speter *dp = '\0'; 63817721Speter 63932785Speter /* After all that, if there was no non-space in the string, 64032785Speter substitute a non-empty message. */ 64132785Speter if (*dst == '\0') 64232785Speter { 64332785Speter free (dst); 64432785Speter dst = xstrdup ("*** empty log message ***"); 64517721Speter } 64617721Speter 64732785Speter return dst; 64817721Speter} 64925839Speter 650128266Speter 651128266Speter 65225839Speter/* Does the file FINFO contain conflict markers? The whole concept 65325839Speter of looking at the contents of the file to figure out whether there are 65425839Speter unresolved conflicts is kind of bogus (people do want to manage files 65525839Speter which contain those patterns not as conflict markers), but for now it 65625839Speter is what we do. */ 65725839Speterint 65825839Speterfile_has_markers (finfo) 65932785Speter const struct file_info *finfo; 66025839Speter{ 66125839Speter FILE *fp; 66225839Speter char *line = NULL; 66325839Speter size_t line_allocated = 0; 66425839Speter int result; 66525839Speter 66625839Speter result = 0; 66725839Speter fp = CVS_FOPEN (finfo->file, "r"); 66825839Speter if (fp == NULL) 66925839Speter error (1, errno, "cannot open %s", finfo->fullname); 67025839Speter while (getline (&line, &line_allocated, fp) > 0) 67125839Speter { 67266525Speter if (strncmp (line, RCS_MERGE_PAT_1, sizeof RCS_MERGE_PAT_1 - 1) == 0 || 67366525Speter strncmp (line, RCS_MERGE_PAT_2, sizeof RCS_MERGE_PAT_2 - 1) == 0 || 67466525Speter strncmp (line, RCS_MERGE_PAT_3, sizeof RCS_MERGE_PAT_3 - 1) == 0) 67525839Speter { 67625839Speter result = 1; 67725839Speter goto out; 67825839Speter } 67925839Speter } 68025839Speter if (ferror (fp)) 68125839Speter error (0, errno, "cannot read %s", finfo->fullname); 68225839Speterout: 68325839Speter if (fclose (fp) < 0) 68425839Speter error (0, errno, "cannot close %s", finfo->fullname); 68525839Speter if (line != NULL) 68625839Speter free (line); 68725839Speter return result; 68825839Speter} 68932785Speter 69032785Speter/* Read the entire contents of the file NAME into *BUF. 69132785Speter If NAME is NULL, read from stdin. *BUF 69232785Speter is a pointer returned from malloc (or NULL), pointing to *BUFSIZE 69332785Speter bytes of space. The actual size is returned in *LEN. On error, 69432785Speter give a fatal error. The name of the file to use in error messages 69532785Speter (typically will include a directory if we have changed directory) 69632785Speter is FULLNAME. MODE is "r" for text or "rb" for binary. */ 69732785Speter 69832785Spetervoid 69932785Speterget_file (name, fullname, mode, buf, bufsize, len) 70032785Speter const char *name; 70132785Speter const char *fullname; 70232785Speter const char *mode; 70332785Speter char **buf; 70432785Speter size_t *bufsize; 70532785Speter size_t *len; 70632785Speter{ 70732785Speter struct stat s; 70832785Speter size_t nread; 70932785Speter char *tobuf; 71032785Speter FILE *e; 71132785Speter size_t filesize; 71232785Speter 71332785Speter if (name == NULL) 71432785Speter { 71532785Speter e = stdin; 71632785Speter filesize = 100; /* force allocation of minimum buffer */ 71732785Speter } 71832785Speter else 71932785Speter { 72054427Speter /* Although it would be cleaner in some ways to just read 72154427Speter until end of file, reallocating the buffer, this function 72254427Speter does get called on files in the working directory which can 72354427Speter be of arbitrary size, so I think we better do all that 72454427Speter extra allocation. */ 72554427Speter 72654427Speter if (CVS_STAT (name, &s) < 0) 72732785Speter error (1, errno, "can't stat %s", fullname); 72834461Speter 72932785Speter /* Convert from signed to unsigned. */ 73032785Speter filesize = s.st_size; 73132785Speter 73232785Speter e = open_file (name, mode); 73332785Speter } 73432785Speter 73566525Speter if (*buf == NULL || *bufsize <= filesize) 73632785Speter { 73766525Speter *bufsize = filesize + 1; 73832785Speter *buf = xrealloc (*buf, *bufsize); 73932785Speter } 74032785Speter 74132785Speter tobuf = *buf; 74232785Speter nread = 0; 74332785Speter while (1) 74432785Speter { 74532785Speter size_t got; 74632785Speter 74732785Speter got = fread (tobuf, 1, *bufsize - (tobuf - *buf), e); 74832785Speter if (ferror (e)) 74932785Speter error (1, errno, "can't read %s", fullname); 75032785Speter nread += got; 75132785Speter tobuf += got; 75232785Speter 75332785Speter if (feof (e)) 75432785Speter break; 75532785Speter 75654427Speter /* Allocate more space if needed. */ 75732785Speter if (tobuf == *buf + *bufsize) 75832785Speter { 75932785Speter int c; 76032785Speter long off; 76132785Speter 76232785Speter c = getc (e); 76332785Speter if (c == EOF) 76432785Speter break; 76532785Speter off = tobuf - *buf; 76632785Speter expand_string (buf, bufsize, *bufsize + 100); 76732785Speter tobuf = *buf + off; 76832785Speter *tobuf++ = c; 76932785Speter ++nread; 77032785Speter } 77132785Speter } 77232785Speter 77332785Speter if (e != stdin && fclose (e) < 0) 77432785Speter error (0, errno, "cannot close %s", fullname); 77532785Speter 77632785Speter *len = nread; 77732785Speter 77832785Speter /* Force *BUF to be large enough to hold a null terminator. */ 77966525Speter if (nread == *bufsize) 78066525Speter expand_string (buf, bufsize, *bufsize + 1); 78166525Speter (*buf)[nread] = '\0'; 78232785Speter} 78354427Speter 78454427Speter 78554427Speter/* Follow a chain of symbolic links to its destination. FILENAME 78654427Speter should be a handle to a malloc'd block of memory which contains the 78754427Speter beginning of the chain. This routine will replace the contents of 78854427Speter FILENAME with the destination (a real file). */ 78954427Speter 79054427Spetervoid 79154427Speterresolve_symlink (filename) 79254427Speter char **filename; 79354427Speter{ 794128266Speter if (filename == NULL || *filename == NULL) 79554427Speter return; 79654427Speter 79754427Speter while (islink (*filename)) 79854427Speter { 79954427Speter#ifdef HAVE_READLINK 80054427Speter /* The clean thing to do is probably to have each filesubr.c 80154427Speter implement this (with an error if not supported by the 80254427Speter platform, in which case islink would presumably return 0). 80354427Speter But that would require editing each filesubr.c and so the 80454427Speter expedient hack seems to be looking at HAVE_READLINK. */ 805128266Speter char *newname = xreadlink (*filename); 80654427Speter 80754427Speter if (isabsolute (newname)) 80854427Speter { 80954427Speter free (*filename); 81054427Speter *filename = newname; 81154427Speter } 81254427Speter else 81354427Speter { 814128266Speter const char *oldname = last_component (*filename); 81554427Speter int dirlen = oldname - *filename; 81654427Speter char *fullnewname = xmalloc (dirlen + strlen (newname) + 1); 81754427Speter strncpy (fullnewname, *filename, dirlen); 81854427Speter strcpy (fullnewname + dirlen, newname); 81954427Speter free (newname); 82054427Speter free (*filename); 82154427Speter *filename = fullnewname; 82254427Speter } 823102840Speter#else 824102840Speter error (1, 0, "internal error: islink doesn't like readlink"); 825102840Speter#endif 82654427Speter } 82754427Speter} 82866525Speter 82966525Speter/* 83066525Speter * Rename a file to an appropriate backup name based on BAKPREFIX. 83166525Speter * If suffix non-null, then ".<suffix>" is appended to the new name. 83266525Speter * 83366525Speter * Returns the new name, which caller may free() if desired. 83466525Speter */ 83566525Speterchar * 83666525Speterbackup_file (filename, suffix) 83766525Speter const char *filename; 83866525Speter const char *suffix; 83966525Speter{ 84066525Speter char *backup_name; 84166525Speter 84266525Speter if (suffix == NULL) 84366525Speter { 84466525Speter backup_name = xmalloc (sizeof (BAKPREFIX) + strlen (filename) + 1); 84566525Speter sprintf (backup_name, "%s%s", BAKPREFIX, filename); 84666525Speter } 84766525Speter else 84866525Speter { 84966525Speter backup_name = xmalloc (sizeof (BAKPREFIX) 85066525Speter + strlen (filename) 85166525Speter + strlen (suffix) 85266525Speter + 2); /* one for dot, one for trailing '\0' */ 85366525Speter sprintf (backup_name, "%s%s.%s", BAKPREFIX, filename, suffix); 85466525Speter } 85566525Speter 85666525Speter if (isfile (filename)) 85766525Speter copy_file (filename, backup_name); 85866525Speter 85966525Speter return backup_name; 86066525Speter} 86166525Speter 86281404Speter/* 86381404Speter * Copy a string into a buffer escaping any shell metacharacters. The 86481404Speter * buffer should be at least twice as long as the string. 86581404Speter * 86681404Speter * Returns a pointer to the terminating NUL byte in buffer. 86781404Speter */ 86881404Speter 86981404Speterchar * 87081404Spetershell_escape(buf, str) 87181404Speter char *buf; 87281404Speter const char *str; 87381404Speter{ 87481404Speter static const char meta[] = "$`\\\""; 87581404Speter const char *p; 87681404Speter 87781404Speter for (;;) 87881404Speter { 87981404Speter p = strpbrk(str, meta); 88081404Speter if (!p) p = str + strlen(str); 88181404Speter if (p > str) 88281404Speter { 88381404Speter memcpy(buf, str, p - str); 88481404Speter buf += p - str; 88581404Speter } 88681404Speter if (!*p) break; 88781404Speter *buf++ = '\\'; 88881404Speter *buf++ = *p++; 88981404Speter str = p; 89081404Speter } 89181404Speter *buf = '\0'; 89281404Speter return buf; 89381404Speter} 89481404Speter 895128266Speter 896128266Speter 89781404Speter/* 89881404Speter * We can only travel forwards in time, not backwards. :) 89981404Speter */ 90081404Spetervoid 90181404Spetersleep_past (desttime) 90281404Speter time_t desttime; 90381404Speter{ 90481404Speter time_t t; 90581404Speter long s; 90681404Speter long us; 90781404Speter 90881404Speter while (time (&t) <= desttime) 90981404Speter { 91081404Speter#ifdef HAVE_GETTIMEOFDAY 91181404Speter struct timeval tv; 91281404Speter gettimeofday (&tv, NULL); 91381404Speter if (tv.tv_sec > desttime) 91481404Speter break; 91581404Speter s = desttime - tv.tv_sec; 91681404Speter if (tv.tv_usec > 0) 91781404Speter us = 1000000 - tv.tv_usec; 91881404Speter else 91981404Speter { 92081404Speter s++; 92181404Speter us = 0; 92281404Speter } 92381404Speter#else 92481404Speter /* default to 20 ms increments */ 92581404Speter s = desttime - t; 92681404Speter us = 20000; 92781404Speter#endif 92881404Speter 92981404Speter#if defined(HAVE_NANOSLEEP) 93081404Speter { 93181404Speter struct timespec ts; 93281404Speter ts.tv_sec = s; 93381404Speter ts.tv_nsec = us * 1000; 93481404Speter (void)nanosleep (&ts, NULL); 93581404Speter } 93681404Speter#elif defined(HAVE_USLEEP) 93781404Speter if (s > 0) 93881404Speter (void)sleep (s); 93981404Speter else 94081404Speter (void)usleep (us); 94181404Speter#elif defined(HAVE_SELECT) 94281404Speter { 94381404Speter /* use select instead of sleep since it is a fairly portable way of 94481404Speter * sleeping for ms. 94581404Speter */ 94681404Speter struct timeval tv; 94781404Speter tv.tv_sec = s; 94881404Speter tv.tv_usec = us; 949128266Speter (void)select (0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL, 950128266Speter &tv); 95181404Speter } 95281404Speter#else 95381404Speter if (us > 0) s++; 95481404Speter (void)sleep(s); 95581404Speter#endif 95681404Speter } 95781404Speter} 958128266Speter 959128266Speter 960128266Speter 961128266Speter/* Return non-zero iff FILENAME is absolute. 962128266Speter Trivial under Unix, but more complicated under other systems. */ 963128266Speterint 964128266Speterisabsolute (filename) 965128266Speter const char *filename; 966128266Speter{ 967128266Speter return ISABSOLUTE (filename); 968128266Speter} 969