1/* utility functions for `patch' */ 2 3/* $Id: util.c 8008 2004-06-16 21:22:10Z korli $ */ 4 5/* Copyright 1986 Larry Wall 6 Copyright 1992, 1993, 1997-1998, 1999 Free Software Foundation, Inc. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2, or (at your option) 11 any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; see the file COPYING. 20 If not, write to the Free Software Foundation, 21 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 22 23#define XTERN extern 24#include <common.h> 25#include <backupfile.h> 26#include <basename.h> 27#include <quotearg.h> 28#include <quotesys.h> 29#include <version.h> 30#undef XTERN 31#define XTERN 32#include <util.h> 33#include <xalloc.h> 34 35#include <maketime.h> 36#include <partime.h> 37 38#include <signal.h> 39#if !defined SIGCHLD && defined SIGCLD 40#define SIGCHLD SIGCLD 41#endif 42#if ! HAVE_RAISE && ! defined raise 43# define raise(sig) kill (getpid (), sig) 44#endif 45 46#ifdef __STDC__ 47# include <stdarg.h> 48# define vararg_start va_start 49#else 50# define vararg_start(ap,p) va_start (ap) 51# if HAVE_VARARGS_H 52# include <varargs.h> 53# else 54 typedef char *va_list; 55# define va_dcl int va_alist; 56# define va_start(ap) ((ap) = (va_list) &va_alist) 57# define va_arg(ap, t) (((t *) ((ap) += sizeof (t))) [-1]) 58# define va_end(ap) 59# endif 60#endif 61 62static void makedirs PARAMS ((char *)); 63 64/* Move a file FROM (where *FROM_NEEDS_REMOVAL is nonzero if FROM 65 needs removal when cleaning up at the end of execution) 66 to TO, renaming it if possible and copying it if necessary. 67 If we must create TO, use MODE to create it. 68 If FROM is null, remove TO (ignoring FROMSTAT). 69 FROM_NEEDS_REMOVAL must be nonnull if FROM is nonnull. 70 Back up TO if BACKUP is nonzero. */ 71 72void 73move_file (char const *from, int volatile *from_needs_removal, 74 char *to, mode_t mode, int backup) 75{ 76 struct stat to_st; 77 int to_errno = ! backup ? -1 : stat (to, &to_st) == 0 ? 0 : errno; 78 79 if (backup) 80 { 81 int try_makedirs_errno = 0; 82 char *bakname; 83 84 if (origprae || origbase) 85 { 86 char const *p = origprae ? origprae : ""; 87 char const *b = origbase ? origbase : ""; 88 char const *o = base_name (to); 89 size_t plen = strlen (p); 90 size_t tlen = o - to; 91 size_t blen = strlen (b); 92 size_t osize = strlen (o) + 1; 93 bakname = xmalloc (plen + tlen + blen + osize); 94 memcpy (bakname, p, plen); 95 memcpy (bakname + plen, to, tlen); 96 memcpy (bakname + plen + tlen, b, blen); 97 memcpy (bakname + plen + tlen + blen, o, osize); 98 for (p += FILESYSTEM_PREFIX_LEN (p); *p; p++) 99 if (ISSLASH (*p)) 100 { 101 try_makedirs_errno = ENOENT; 102 break; 103 } 104 } 105 else 106 { 107 bakname = find_backup_file_name (to, backup_type); 108 if (!bakname) 109 memory_fatal (); 110 } 111 112 if (to_errno) 113 { 114 int fd; 115 116 if (debug & 4) 117 say ("Creating empty unreadable file %s\n", quotearg (bakname)); 118 119 try_makedirs_errno = ENOENT; 120 unlink (bakname); 121 while ((fd = creat (bakname, 0)) < 0) 122 { 123 if (errno != try_makedirs_errno) 124 pfatal ("Can't create file %s", quotearg (bakname)); 125 makedirs (bakname); 126 try_makedirs_errno = 0; 127 } 128 if (close (fd) != 0) 129 pfatal ("Can't close file %s", quotearg (bakname)); 130 } 131 else 132 { 133 if (debug & 4) 134 say ("Renaming file %s to %s\n", 135 quotearg_n (0, to), quotearg_n (1, bakname)); 136 while (rename (to, bakname) != 0) 137 { 138 if (errno != try_makedirs_errno) 139 pfatal ("Can't rename file %s to %s", 140 quotearg_n (0, to), quotearg_n (1, bakname)); 141 makedirs (bakname); 142 try_makedirs_errno = 0; 143 } 144 } 145 146 free (bakname); 147 } 148 149 if (from) 150 { 151 if (debug & 4) 152 say ("Renaming file %s to %s\n", 153 quotearg_n (0, from), quotearg_n (1, to)); 154 155 if (rename (from, to) == 0) 156 *from_needs_removal = 0; 157 else 158 { 159 int to_dir_known_to_exist = 0; 160 161 if (errno == ENOENT 162 && (to_errno == -1 || to_errno == ENOENT)) 163 { 164 makedirs (to); 165 to_dir_known_to_exist = 1; 166 if (rename (from, to) == 0) 167 { 168 *from_needs_removal = 0; 169 return; 170 } 171 } 172 173 if (errno == EXDEV) 174 { 175 if (! backup) 176 { 177 if (unlink (to) == 0) 178 to_dir_known_to_exist = 1; 179 else if (errno != ENOENT) 180 pfatal ("Can't remove file %s", quotearg (to)); 181 } 182 if (! to_dir_known_to_exist) 183 makedirs (to); 184 copy_file (from, to, 0, mode); 185 return; 186 } 187 188 pfatal ("Can't rename file %s to %s", 189 quotearg_n (0, from), quotearg_n (1, to)); 190 } 191 } 192 else if (! backup) 193 { 194 if (debug & 4) 195 say ("Removing file %s\n", quotearg (to)); 196 if (unlink (to) != 0) 197 pfatal ("Can't remove file %s", quotearg (to)); 198 } 199} 200 201/* Create FILE with OPEN_FLAGS, and with MODE adjusted so that 202 we can read and write the file and that the file is not executable. 203 Return the file descriptor. */ 204int 205create_file (char const *file, int open_flags, mode_t mode) 206{ 207 int fd; 208 mode |= S_IRUSR | S_IWUSR; 209 mode &= ~ (S_IXUSR | S_IXGRP | S_IXOTH); 210 if (! (O_CREAT && O_TRUNC)) 211 close (creat (file, mode)); 212 fd = open (file, O_CREAT | O_TRUNC | open_flags, mode); 213 if (fd < 0) 214 pfatal ("Can't create file %s", quotearg (file)); 215 return fd; 216} 217 218/* Copy a file. */ 219 220void 221copy_file (char const *from, char const *to, int to_flags, mode_t mode) 222{ 223 int tofd; 224 int fromfd; 225 size_t i; 226 227 if ((fromfd = open (from, O_RDONLY | O_BINARY)) < 0) 228 pfatal ("Can't reopen file %s", quotearg (from)); 229 tofd = create_file (to, O_WRONLY | O_BINARY | to_flags, mode); 230 while ((i = read (fromfd, buf, bufsize)) != 0) 231 { 232 if (i == (size_t) -1) 233 read_fatal (); 234 if (write (tofd, buf, i) != i) 235 write_fatal (); 236 } 237 if (close (fromfd) != 0) 238 read_fatal (); 239 if (close (tofd) != 0) 240 write_fatal (); 241} 242 243static char const DEV_NULL[] = NULL_DEVICE; 244 245static char const RCSSUFFIX[] = ",v"; 246static char const CHECKOUT[] = "co %s"; 247static char const CHECKOUT_LOCKED[] = "co -l %s"; 248static char const RCSDIFF1[] = "rcsdiff %s"; 249 250static char const SCCSPREFIX[] = "s."; 251static char const GET[] = "get "; 252static char const GET_LOCKED[] = "get -e "; 253static char const SCCSDIFF1[] = "get -p "; 254static char const SCCSDIFF2[] = "|diff - %s"; 255 256static char const CLEARTOOL_CO[] = "cleartool co -unr -nc "; 257 258/* Return "RCS" if FILENAME is controlled by RCS, 259 "SCCS" if it is controlled by SCCS, 260 "ClearCase" if it is controlled by Clearcase, and 0 otherwise. 261 READONLY is nonzero if we desire only readonly access to FILENAME. 262 FILESTAT describes FILENAME's status or is 0 if FILENAME does not exist. 263 If successful and if GETBUF is nonzero, set *GETBUF to a command 264 that gets the file; similarly for DIFFBUF and a command to diff the file 265 (but set *DIFFBUF to 0 if the diff operation is meaningless). 266 *GETBUF and *DIFFBUF must be freed by the caller. */ 267char const * 268version_controller (char const *filename, int readonly, 269 struct stat const *filestat, char **getbuf, char **diffbuf) 270{ 271 struct stat cstat; 272 char const *filebase = base_name (filename); 273 char const *dotslash = *filename == '-' ? "./" : ""; 274 size_t dir_len = filebase - filename; 275 size_t filenamelen = strlen (filename); 276 size_t maxfixlen = sizeof "SCCS/" - 1 + sizeof SCCSPREFIX - 1; 277 size_t maxtrysize = filenamelen + maxfixlen + 1; 278 size_t quotelen = quote_system_arg (0, filename); 279 size_t maxgetsize = sizeof CLEARTOOL_CO + quotelen + maxfixlen; 280 size_t maxdiffsize = 281 (sizeof SCCSDIFF1 + sizeof SCCSDIFF2 + sizeof DEV_NULL - 1 282 + 2 * quotelen + maxfixlen); 283 char *trybuf = xmalloc (maxtrysize); 284 char const *r = 0; 285 286 strcpy (trybuf, filename); 287 288#define try1(f,a1) (sprintf (trybuf + dir_len, f, a1), stat (trybuf, &cstat) == 0) 289#define try2(f,a1,a2) (sprintf (trybuf + dir_len, f, a1,a2), stat (trybuf, &cstat) == 0) 290 291 /* Check that RCS file is not working file. 292 Some hosts don't report file name length errors. */ 293 294 if ((try2 ("RCS/%s%s", filebase, RCSSUFFIX) 295 || try1 ("RCS/%s", filebase) 296 || try2 ("%s%s", filebase, RCSSUFFIX)) 297 && ! (filestat 298 && filestat->st_dev == cstat.st_dev 299 && filestat->st_ino == cstat.st_ino)) 300 { 301 if (getbuf) 302 { 303 char *p = *getbuf = xmalloc (maxgetsize); 304 sprintf (p, readonly ? CHECKOUT : CHECKOUT_LOCKED, dotslash); 305 p += strlen (p); 306 p += quote_system_arg (p, filename); 307 *p = '\0'; 308 } 309 310 if (diffbuf) 311 { 312 char *p = *diffbuf = xmalloc (maxdiffsize); 313 sprintf (p, RCSDIFF1, dotslash); 314 p += strlen (p); 315 p += quote_system_arg (p, filename); 316 *p++ = '>'; 317 strcpy (p, DEV_NULL); 318 } 319 320 r = "RCS"; 321 } 322 else if (try2 ("SCCS/%s%s", SCCSPREFIX, filebase) 323 || try2 ("%s%s", SCCSPREFIX, filebase)) 324 { 325 if (getbuf) 326 { 327 char *p = *getbuf = xmalloc (maxgetsize); 328 sprintf (p, readonly ? GET : GET_LOCKED); 329 p += strlen (p); 330 p += quote_system_arg (p, trybuf); 331 *p = '\0'; 332 } 333 334 if (diffbuf) 335 { 336 char *p = *diffbuf = xmalloc (maxdiffsize); 337 strcpy (p, SCCSDIFF1); 338 p += sizeof SCCSDIFF1 - 1; 339 p += quote_system_arg (p, trybuf); 340 sprintf (p, SCCSDIFF2, dotslash); 341 p += strlen (p); 342 p += quote_system_arg (p, filename); 343 *p++ = '>'; 344 strcpy (p, DEV_NULL); 345 } 346 347 r = "SCCS"; 348 } 349 else if (!readonly && filestat 350 && try1 ("%s@@", filebase) && S_ISDIR (cstat.st_mode)) 351 { 352 if (getbuf) 353 { 354 char *p = *getbuf = xmalloc (maxgetsize); 355 strcpy (p, CLEARTOOL_CO); 356 p += sizeof CLEARTOOL_CO - 1; 357 p += quote_system_arg (p, filename); 358 *p = '\0'; 359 } 360 361 if (diffbuf) 362 *diffbuf = 0; 363 364 r = "ClearCase"; 365 } 366 367 free (trybuf); 368 return r; 369} 370 371/* Get FILENAME from version control system CS. The file already exists if 372 EXISTS is nonzero. Only readonly access is needed if READONLY is nonzero. 373 Use the command GETBUF to actually get the named file. 374 Store the resulting file status into *FILESTAT. 375 Return nonzero if successful. */ 376int 377version_get (char const *filename, char const *cs, int exists, int readonly, 378 char const *getbuf, struct stat *filestat) 379{ 380 if (patch_get < 0) 381 { 382 ask ("Get file %s from %s%s? [y] ", 383 quotearg (filename), cs, readonly ? "" : " with lock"); 384 if (*buf == 'n') 385 return 0; 386 } 387 388 if (dry_run) 389 { 390 if (! exists) 391 fatal ("can't do dry run on nonexistent version-controlled file %s; invoke `%s' and try again", 392 quotearg (filename), getbuf); 393 } 394 else 395 { 396 if (verbosity == VERBOSE) 397 say ("Getting file %s from %s%s...\n", quotearg (filename), 398 cs, readonly ? "" : " with lock"); 399 if (systemic (getbuf) != 0) 400 fatal ("Can't get file %s from %s", quotearg (filename), cs); 401 if (stat (filename, filestat) != 0) 402 pfatal ("%s", quotearg (filename)); 403 } 404 405 return 1; 406} 407 408/* Allocate a unique area for a string. */ 409 410char * 411savebuf (register char const *s, register size_t size) 412{ 413 register char *rv; 414 415 assert (s && size); 416 rv = malloc (size); 417 418 if (! rv) 419 { 420 if (! using_plan_a) 421 memory_fatal (); 422 } 423 else 424 memcpy (rv, s, size); 425 426 return rv; 427} 428 429char * 430savestr (char const *s) 431{ 432 return savebuf (s, strlen (s) + 1); 433} 434 435void 436remove_prefix (char *p, size_t prefixlen) 437{ 438 char const *s = p + prefixlen; 439 while ((*p++ = *s++)) 440 continue; 441} 442 443char * 444format_linenum (char numbuf[LINENUM_LENGTH_BOUND + 1], LINENUM n) 445{ 446 char *p = numbuf + LINENUM_LENGTH_BOUND; 447 *p = '\0'; 448 449 if (n < 0) 450 { 451 do 452 *--p = '0' - (int) (n % 10); 453 while ((n /= 10) != 0); 454 455 *--p = '-'; 456 } 457 else 458 { 459 do 460 *--p = '0' + (int) (n % 10); 461 while ((n /= 10) != 0); 462 } 463 464 return p; 465} 466 467#if !HAVE_VPRINTF 468#define vfprintf my_vfprintf 469static int 470vfprintf (FILE *stream, char const *format, va_list args) 471{ 472#if !HAVE_DOPRNT && HAVE__DOPRINTF 473# define _doprnt _doprintf 474#endif 475#if HAVE_DOPRNT || HAVE__DOPRINTF 476 _doprnt (format, args, stream); 477 return ferror (stream) ? -1 : 0; 478#else 479 int *a = (int *) args; 480 return fprintf (stream, format, 481 a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9]); 482#endif 483} 484#endif /* !HAVE_VPRINTF */ 485 486/* Terminal output, pun intended. */ 487 488void 489fatal (char const *format, ...) 490{ 491 va_list args; 492 fprintf (stderr, "%s: **** ", program_name); 493 vararg_start (args, format); 494 vfprintf (stderr, format, args); 495 va_end (args); 496 putc ('\n', stderr); 497 fflush (stderr); 498 fatal_exit (0); 499} 500 501void 502memory_fatal (void) 503{ 504 fatal ("out of memory"); 505} 506 507void 508read_fatal (void) 509{ 510 pfatal ("read error"); 511} 512 513void 514write_fatal (void) 515{ 516 pfatal ("write error"); 517} 518 519/* Say something from patch, something from the system, then silence . . . */ 520 521void 522pfatal (char const *format, ...) 523{ 524 int errnum = errno; 525 va_list args; 526 fprintf (stderr, "%s: **** ", program_name); 527 vararg_start (args, format); 528 vfprintf (stderr, format, args); 529 va_end (args); 530 fflush (stderr); /* perror bypasses stdio on some hosts. */ 531 errno = errnum; 532 perror (" "); 533 fflush (stderr); 534 fatal_exit (0); 535} 536 537/* Tell the user something. */ 538 539void 540say (char const *format, ...) 541{ 542 va_list args; 543 vararg_start (args, format); 544 vfprintf (stdout, format, args); 545 va_end (args); 546 fflush (stdout); 547} 548 549/* Get a response from the user, somehow or other. */ 550 551void 552ask (char const *format, ...) 553{ 554 static int ttyfd = -2; 555 int r; 556 va_list args; 557 558 vararg_start (args, format); 559 vfprintf (stdout, format, args); 560 va_end (args); 561 fflush (stdout); 562 563 if (ttyfd == -2) 564 { 565 /* If standard output is not a tty, don't bother opening /dev/tty, 566 since it's unlikely that stdout will be seen by the tty user. 567 The isatty test also works around a bug in GNU Emacs 19.34 under Linux 568 which makes a call-process `patch' hang when it reads from /dev/tty. 569 POSIX.2 requires that we read /dev/tty, though. */ 570 ttyfd = (posixly_correct || isatty (STDOUT_FILENO) 571 ? open (TTY_DEVICE, O_RDONLY) 572 : -1); 573 } 574 575 if (ttyfd < 0) 576 { 577 /* No terminal at all -- default it. */ 578 printf ("\n"); 579 buf[0] = '\n'; 580 buf[1] = '\0'; 581 } 582 else 583 { 584 size_t s = 0; 585 while ((r = read (ttyfd, buf + s, bufsize - 1 - s)) == bufsize - 1 - s 586 && buf[bufsize - 2] != '\n') 587 { 588 s = bufsize - 1; 589 bufsize *= 2; 590 buf = realloc (buf, bufsize); 591 if (!buf) 592 memory_fatal (); 593 } 594 if (r == 0) 595 printf ("EOF\n"); 596 else if (r < 0) 597 { 598 perror ("tty read"); 599 fflush (stderr); 600 close (ttyfd); 601 ttyfd = -1; 602 r = 0; 603 } 604 buf[s + r] = '\0'; 605 } 606} 607 608/* Return nonzero if it OK to reverse a patch. */ 609 610int 611ok_to_reverse (char const *format, ...) 612{ 613 int r = 0; 614 615 if (noreverse || ! (force && verbosity == SILENT)) 616 { 617 va_list args; 618 vararg_start (args, format); 619 vfprintf (stdout, format, args); 620 va_end (args); 621 } 622 623 if (noreverse) 624 { 625 printf (" Skipping patch.\n"); 626 skip_rest_of_patch = TRUE; 627 r = 0; 628 } 629 else if (force) 630 { 631 if (verbosity != SILENT) 632 printf (" Applying it anyway.\n"); 633 r = 0; 634 } 635 else if (batch) 636 { 637 say (reverse ? " Ignoring -R.\n" : " Assuming -R.\n"); 638 r = 1; 639 } 640 else 641 { 642 ask (reverse ? " Ignore -R? [n] " : " Assume -R? [n] "); 643 r = *buf == 'y'; 644 if (! r) 645 { 646 ask ("Apply anyway? [n] "); 647 if (*buf != 'y') 648 { 649 if (verbosity != SILENT) 650 say ("Skipping patch.\n"); 651 skip_rest_of_patch = TRUE; 652 } 653 } 654 } 655 656 return r; 657} 658 659/* How to handle certain events when not in a critical region. */ 660 661#define NUM_SIGS (sizeof (sigs) / sizeof (*sigs)) 662static int const sigs[] = { 663#ifdef SIGHUP 664 SIGHUP, 665#endif 666#ifdef SIGPIPE 667 SIGPIPE, 668#endif 669#ifdef SIGTERM 670 SIGTERM, 671#endif 672#ifdef SIGXCPU 673 SIGXCPU, 674#endif 675#ifdef SIGXFSZ 676 SIGXFSZ, 677#endif 678 SIGINT 679}; 680 681#if !HAVE_SIGPROCMASK 682#define sigset_t int 683#define sigemptyset(s) (*(s) = 0) 684#ifndef sigmask 685#define sigmask(sig) (1 << ((sig) - 1)) 686#endif 687#define sigaddset(s, sig) (*(s) |= sigmask (sig)) 688#define sigismember(s, sig) ((*(s) & sigmask (sig)) != 0) 689#ifndef SIG_BLOCK 690#define SIG_BLOCK 0 691#endif 692#ifndef SIG_UNBLOCK 693#define SIG_UNBLOCK (SIG_BLOCK + 1) 694#endif 695#ifndef SIG_SETMASK 696#define SIG_SETMASK (SIG_BLOCK + 2) 697#endif 698#define sigprocmask(how, n, o) \ 699 ((how) == SIG_BLOCK \ 700 ? ((o) ? *(o) = sigblock (*(n)) : sigblock (*(n))) \ 701 : (how) == SIG_UNBLOCK \ 702 ? sigsetmask (((o) ? *(o) = sigblock (0) : sigblock (0)) & ~*(n)) \ 703 : (o ? *(o) = sigsetmask (*(n)) : sigsetmask (*(n)))) 704#if !HAVE_SIGSETMASK 705#define sigblock(mask) 0 706#define sigsetmask(mask) 0 707#endif 708#endif 709 710static sigset_t initial_signal_mask; 711static sigset_t signals_to_block; 712 713#if ! HAVE_SIGACTION 714static RETSIGTYPE fatal_exit_handler PARAMS ((int)) __attribute__ ((noreturn)); 715static RETSIGTYPE 716fatal_exit_handler (int sig) 717{ 718 signal (sig, SIG_IGN); 719 fatal_exit (sig); 720} 721#endif 722 723void 724set_signals (int reset) 725{ 726 int i; 727#if HAVE_SIGACTION 728 struct sigaction initial_act, fatal_act; 729 fatal_act.sa_handler = fatal_exit; 730 sigemptyset (&fatal_act.sa_mask); 731 fatal_act.sa_flags = 0; 732#define setup_handler(sig) sigaction (sig, &fatal_act, (struct sigaction *) 0) 733#else 734#define setup_handler(sig) signal (sig, fatal_exit_handler) 735#endif 736 737 if (!reset) 738 { 739#ifdef SIGCHLD 740 /* System V fork+wait does not work if SIGCHLD is ignored. */ 741 signal (SIGCHLD, SIG_DFL); 742#endif 743 sigemptyset (&signals_to_block); 744 for (i = 0; i < NUM_SIGS; i++) 745 { 746 int ignoring_signal; 747#if HAVE_SIGACTION 748 if (sigaction (sigs[i], (struct sigaction *) 0, &initial_act) != 0) 749 continue; 750 ignoring_signal = initial_act.sa_handler == SIG_IGN; 751#else 752 ignoring_signal = signal (sigs[i], SIG_IGN) == SIG_IGN; 753#endif 754 if (! ignoring_signal) 755 { 756 sigaddset (&signals_to_block, sigs[i]); 757 setup_handler (sigs[i]); 758 } 759 } 760 } 761 else 762 { 763 /* Undo the effect of ignore_signals. */ 764#if HAVE_SIGPROCMASK || HAVE_SIGSETMASK 765 sigprocmask (SIG_SETMASK, &initial_signal_mask, (sigset_t *) 0); 766#else 767 for (i = 0; i < NUM_SIGS; i++) 768 if (sigismember (&signals_to_block, sigs[i])) 769 setup_handler (sigs[i]); 770#endif 771 } 772} 773 774/* How to handle certain events when in a critical region. */ 775 776void 777ignore_signals (void) 778{ 779#if HAVE_SIGPROCMASK || HAVE_SIGSETMASK 780 sigprocmask (SIG_BLOCK, &signals_to_block, &initial_signal_mask); 781#else 782 int i; 783 for (i = 0; i < NUM_SIGS; i++) 784 if (sigismember (&signals_to_block, sigs[i])) 785 signal (sigs[i], SIG_IGN); 786#endif 787} 788 789void 790exit_with_signal (int sig) 791{ 792 sigset_t s; 793 signal (sig, SIG_DFL); 794 sigemptyset (&s); 795 sigaddset (&s, sig); 796 sigprocmask (SIG_UNBLOCK, &s, (sigset_t *) 0); 797 raise (sig); 798 exit (2); 799} 800 801int 802systemic (char const *command) 803{ 804 if (debug & 8) 805 say ("+ %s\n", command); 806 fflush (stdout); 807 return system (command); 808} 809 810/* Replace '/' with '\0' in FILENAME if it marks a place that 811 needs testing for the existence of directory. Return the address 812 of the last location replaced, or 0 if none were replaced. */ 813static char * 814replace_slashes (char *filename) 815{ 816 char *f; 817 char *last_location_replaced = 0; 818 char const *component_start; 819 820 for (f = filename + FILESYSTEM_PREFIX_LEN (filename); ISSLASH (*f); f++) 821 continue; 822 823 component_start = f; 824 825 for (; *f; f++) 826 if (ISSLASH (*f)) 827 { 828 char *slash = f; 829 830 /* Treat multiple slashes as if they were one slash. */ 831 while (ISSLASH (f[1])) 832 f++; 833 834 /* Ignore slashes at the end of the path. */ 835 if (! f[1]) 836 break; 837 838 /* "." and ".." need not be tested. */ 839 if (! (slash - component_start <= 2 840 && component_start[0] == '.' && slash[-1] == '.')) 841 { 842 *slash = '\0'; 843 last_location_replaced = slash; 844 } 845 846 component_start = f + 1; 847 } 848 849 return last_location_replaced; 850} 851 852/* Make sure we'll have the directories to create a file. 853 Ignore the last element of `filename'. */ 854 855static void 856makedirs (register char *filename) 857{ 858 register char *f; 859 register char *flim = replace_slashes (filename); 860 861 if (flim) 862 { 863 /* Create any missing directories, replacing NULs by '/'s. 864 Ignore errors. We may have to keep going even after an EEXIST, 865 since the path may contain ".."s; and when there is an EEXIST 866 failure the system may return some other error number. 867 Any problems will eventually be reported when we create the file. */ 868 for (f = filename; f <= flim; f++) 869 if (!*f) 870 { 871 mkdir (filename, 872 S_IRUSR|S_IWUSR|S_IXUSR 873 |S_IRGRP|S_IWGRP|S_IXGRP 874 |S_IROTH|S_IWOTH|S_IXOTH); 875 *f = '/'; 876 } 877 } 878} 879 880/* Remove empty ancestor directories of FILENAME. 881 Ignore errors, since the path may contain ".."s, and when there 882 is an EEXIST failure the system may return some other error number. */ 883void 884removedirs (char *filename) 885{ 886 size_t i; 887 888 for (i = strlen (filename); i != 0; i--) 889 if (ISSLASH (filename[i]) 890 && ! (ISSLASH (filename[i - 1]) 891 || (filename[i - 1] == '.' 892 && (i == 1 893 || ISSLASH (filename[i - 2]) 894 || (filename[i - 2] == '.' 895 && (i == 2 896 || ISSLASH (filename[i - 3]))))))) 897 { 898 filename[i] = '\0'; 899 if (rmdir (filename) == 0 && verbosity == VERBOSE) 900 say ("Removed empty directory %s\n", quotearg (filename)); 901 filename[i] = '/'; 902 } 903} 904 905static time_t initial_time; 906 907void 908init_time (void) 909{ 910 time (&initial_time); 911} 912 913/* Make filenames more reasonable. */ 914 915char * 916fetchname (char *at, int strip_leading, time_t *pstamp) 917{ 918 char *name; 919 register char *t; 920 int sleading = strip_leading; 921 time_t stamp = (time_t) -1; 922 923 while (ISSPACE ((unsigned char) *at)) 924 at++; 925 if (debug & 128) 926 say ("fetchname %s %d\n", at, strip_leading); 927 928 name = at; 929 /* Strip up to `strip_leading' leading slashes and null terminate. 930 If `strip_leading' is negative, strip all leading slashes. */ 931 for (t = at; *t; t++) 932 { 933 if (ISSLASH (*t)) 934 { 935 while (ISSLASH (t[1])) 936 t++; 937 if (strip_leading < 0 || --sleading >= 0) 938 name = t+1; 939 } 940 else if (ISSPACE ((unsigned char) *t)) 941 { 942 char const *u = t; 943 944 if (set_time | set_utc) 945 stamp = str2time (&u, initial_time, 946 set_utc ? 0L : TM_LOCAL_ZONE); 947 else 948 { 949 /* The head says the file is nonexistent if the timestamp 950 is the epoch; but the listed time is local time, not UTC, 951 and POSIX.1 allows local time offset anywhere in the range 952 -25:00 < offset < +26:00. Match any time in that 953 range by assuming local time is -25:00 and then matching 954 any ``local'' time T in the range 0 < T < 25+26 hours. */ 955 stamp = str2time (&u, initial_time, -25L * 60 * 60); 956 if (0 < stamp && stamp < (25 + 26) * 60L * 60) 957 stamp = 0; 958 } 959 960 if (*u && ! ISSPACE ((unsigned char) *u)) 961 stamp = (time_t) -1; 962 963 *t = '\0'; 964 break; 965 } 966 } 967 968 if (!*name) 969 return 0; 970 971 /* If the name is "/dev/null", ignore the name and mark the file 972 as being nonexistent. The name "/dev/null" appears in patches 973 regardless of how NULL_DEVICE is spelled. */ 974 if (strcmp (at, "/dev/null") == 0) 975 { 976 if (pstamp) 977 *pstamp = 0; 978 return 0; 979 } 980 981 /* Ignore the name if it doesn't have enough slashes to strip off. */ 982 if (0 < sleading) 983 return 0; 984 985 if (pstamp) 986 *pstamp = stamp; 987 988 return savestr (name); 989} 990 991void 992Fseek (FILE *stream, file_offset offset, int ptrname) 993{ 994 if (file_seek (stream, offset, ptrname) != 0) 995 pfatal ("fseek"); 996} 997