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