Sync usage with man page.
[netbsd-mini2440.git] / external / gpl2 / xcvs / dist / src / patch.c
blob9c44846dd944472f8f5627dcc373ffbd0c0871b5
1 /*
2 * Copyright (C) 1986-2005 The Free Software Foundation, Inc.
4 * Portions Copyright (C) 1998-2005 Derek Price, Ximbiot <http://ximbiot.com>,
5 * and others.
7 * Portions Copyright (C) 1992, Brian Berliner and Jeff Polk
8 * Portions Copyright (C) 1989-1992, Brian Berliner
9 *
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 * Patch
15 * Create a Larry Wall format "patch" file between a previous release and the
16 * current head of a module, or between two releases. Can specify the
17 * release as either a date or a revision number.
20 #include "cvs.h"
21 #include "getline.h"
23 static RETSIGTYPE patch_cleanup (int);
24 static Dtype patch_dirproc (void *callerdat, const char *dir,
25 const char *repos, const char *update_dir,
26 List *entries);
27 static int patch_fileproc (void *callerdat, struct file_info *finfo);
28 static int patch_proc (int argc, char **argv, char *xwhere,
29 char *mwhere, char *mfile, int shorten,
30 int local_specified, char *mname, char *msg);
32 static int force_tag_match = 1;
33 static int patch_short = 0;
34 static int toptwo_diffs = 0;
35 static char *options = NULL;
36 static char *rev1 = NULL;
37 static int rev1_validated = 0;
38 static char *rev2 = NULL;
39 static int rev2_validated = 0;
40 static char *date1 = NULL;
41 static char *date2 = NULL;
42 static char *tmpfile1 = NULL;
43 static char *tmpfile2 = NULL;
44 static char *tmpfile3 = NULL;
45 static int unidiff = 0;
47 static const char *const patch_usage[] =
49 "Usage: %s %s [-flR] [-c|-u] [-s|-t] [-V %%d] [-k kopt]\n",
50 " -r rev|-D date [-r rev2 | -D date2] modules...\n",
51 "\t-f\tForce a head revision match if tag/date not found.\n",
52 "\t-l\tLocal directory only, not recursive\n",
53 "\t-R\tProcess directories recursively.\n",
54 "\t-c\tContext diffs (default)\n",
55 "\t-u\tUnidiff format.\n",
56 "\t-s\tShort patch - one liner per file.\n",
57 "\t-t\tTop two diffs - last change made to the file.\n",
58 "\t-V vers\tUse RCS Version \"vers\" for keyword expansion.\n",
59 "\t-k kopt\tSpecify keyword expansion mode.\n",
60 "\t-D date\tDate.\n",
61 "\t-r rev\tRevision - symbolic or numeric.\n",
62 "(Specify the --help global option for a list of other help options)\n",
63 NULL
68 int
69 patch (int argc, char **argv)
71 register int i;
72 int local = 0;
73 int c;
74 int err = 0;
75 DBM *db;
77 if (argc == -1)
78 usage (patch_usage);
80 getoptreset ();
81 while ((c = getopt (argc, argv, "+V:k:cuftsQqlRD:r:")) != -1)
83 switch (c)
85 case 'Q':
86 case 'q':
87 /* The CVS 1.5 client sends these options (in addition to
88 Global_option requests), so we must ignore them. */
89 if (!server_active)
90 error (1, 0,
91 "-q or -Q must be specified before \"%s\"",
92 cvs_cmd_name);
93 break;
94 case 'f':
95 force_tag_match = 0;
96 break;
97 case 'l':
98 local = 1;
99 break;
100 case 'R':
101 local = 0;
102 break;
103 case 't':
104 toptwo_diffs = 1;
105 break;
106 case 's':
107 patch_short = 1;
108 break;
109 case 'D':
110 if (rev2 != NULL || date2 != NULL)
111 error (1, 0,
112 "no more than two revisions/dates can be specified");
113 if (rev1 != NULL || date1 != NULL)
114 date2 = Make_Date (optarg);
115 else
116 date1 = Make_Date (optarg);
117 break;
118 case 'r':
119 if (rev2 != NULL || date2 != NULL)
120 error (1, 0,
121 "no more than two revisions/dates can be specified");
122 if (rev1 != NULL || date1 != NULL)
123 rev2 = optarg;
124 else
125 rev1 = optarg;
126 break;
127 case 'k':
128 if (options)
129 free (options);
130 options = RCS_check_kflag (optarg);
131 break;
132 case 'V':
133 /* This option is pretty seriously broken:
134 1. It is not clear what it does (does it change keyword
135 expansion behavior? If so, how? Or does it have
136 something to do with what version of RCS we are using?
137 Or the format we write RCS files in?).
138 2. Because both it and -k use the options variable,
139 specifying both -V and -k doesn't work.
140 3. At least as of CVS 1.9, it doesn't work (failed
141 assertion in RCS_checkout where it asserts that options
142 starts with -k). Few people seem to be complaining.
143 In the future (perhaps the near future), I have in mind
144 removing it entirely, and updating NEWS and cvs.texinfo,
145 but in case it is a good idea to give people more time
146 to complain if they would miss it, I'll just add this
147 quick and dirty error message for now. */
148 error (1, 0,
149 "the -V option is obsolete and should not be used");
150 break;
151 case 'u':
152 unidiff = 1; /* Unidiff */
153 break;
154 case 'c': /* Context diff */
155 unidiff = 0;
156 break;
157 case '?':
158 default:
159 usage (patch_usage);
160 break;
163 argc -= optind;
164 argv += optind;
166 /* Sanity checks */
167 if (argc < 1)
168 usage (patch_usage);
170 if (toptwo_diffs && patch_short)
171 error (1, 0, "-t and -s options are mutually exclusive");
172 if (toptwo_diffs && (date1 != NULL || date2 != NULL ||
173 rev1 != NULL || rev2 != NULL))
174 error (1, 0, "must not specify revisions/dates with -t option!");
176 if (!toptwo_diffs && (date1 == NULL && date2 == NULL &&
177 rev1 == NULL && rev2 == NULL))
178 error (1, 0, "must specify at least one revision/date!");
179 if (date1 != NULL && date2 != NULL)
180 if (RCS_datecmp (date1, date2) >= 0)
181 error (1, 0, "second date must come after first date!");
183 /* if options is NULL, make it a NULL string */
184 if (options == NULL)
185 options = xstrdup ("");
187 #ifdef CLIENT_SUPPORT
188 if (current_parsed_root->isremote)
190 /* We're the client side. Fire up the remote server. */
191 start_server ();
193 ign_setup ();
195 if (local)
196 send_arg("-l");
197 if (!force_tag_match)
198 send_arg("-f");
199 if (toptwo_diffs)
200 send_arg("-t");
201 if (patch_short)
202 send_arg("-s");
203 if (unidiff)
204 send_arg("-u");
206 if (rev1)
207 option_with_arg ("-r", rev1);
208 if (date1)
209 client_senddate (date1);
210 if (rev2)
211 option_with_arg ("-r", rev2);
212 if (date2)
213 client_senddate (date2);
214 if (options[0] != '\0')
215 send_arg (options);
218 int i;
219 for (i = 0; i < argc; ++i)
220 send_arg (argv[i]);
223 send_to_server ("rdiff\012", 0);
224 return get_responses_and_close ();
226 #endif
228 /* clean up if we get a signal */
229 #ifdef SIGABRT
230 (void)SIG_register (SIGABRT, patch_cleanup);
231 #endif
232 #ifdef SIGHUP
233 (void)SIG_register (SIGHUP, patch_cleanup);
234 #endif
235 #ifdef SIGINT
236 (void)SIG_register (SIGINT, patch_cleanup);
237 #endif
238 #ifdef SIGQUIT
239 (void)SIG_register (SIGQUIT, patch_cleanup);
240 #endif
241 #ifdef SIGPIPE
242 (void)SIG_register (SIGPIPE, patch_cleanup);
243 #endif
244 #ifdef SIGTERM
245 (void)SIG_register (SIGTERM, patch_cleanup);
246 #endif
248 db = open_module ();
249 for (i = 0; i < argc; i++)
250 err += do_module (db, argv[i], PATCH, "Patching", patch_proc,
251 NULL, 0, local, 0, 0, NULL);
252 close_module (db);
253 free (options);
254 patch_cleanup (0);
255 return err;
261 * callback proc for doing the real work of patching
263 /* ARGSUSED */
264 static int
265 patch_proc (int argc, char **argv, char *xwhere, char *mwhere, char *mfile,
266 int shorten, int local_specified, char *mname, char *msg)
268 char *myargv[2];
269 int err = 0;
270 int which;
271 char *repository;
272 char *where;
274 TRACE ( TRACE_FUNCTION, "patch_proc ( %s, %s, %s, %d, %d, %s, %s )",
275 xwhere ? xwhere : "(null)",
276 mwhere ? mwhere : "(null)",
277 mfile ? mfile : "(null)",
278 shorten, local_specified,
279 mname ? mname : "(null)",
280 msg ? msg : "(null)" );
282 repository = xmalloc (strlen (current_parsed_root->directory)
283 + strlen (argv[0])
284 + (mfile == NULL ? 0 : strlen (mfile) + 1) + 2);
285 (void)sprintf (repository, "%s/%s",
286 current_parsed_root->directory, argv[0]);
287 where = xmalloc (strlen (argv[0])
288 + (mfile == NULL ? 0 : strlen (mfile) + 1)
289 + 1);
290 (void)strcpy (where, argv[0]);
292 /* if mfile isn't null, we need to set up to do only part of the module */
293 if (mfile != NULL)
295 char *cp;
296 char *path;
298 /* if the portion of the module is a path, put the dir part on repos */
299 if ((cp = strrchr (mfile, '/')) != NULL)
301 *cp = '\0';
302 (void)strcat (repository, "/");
303 (void)strcat (repository, mfile);
304 (void)strcat (where, "/");
305 (void)strcat (where, mfile);
306 mfile = cp + 1;
309 /* take care of the rest */
310 path = xmalloc (strlen (repository) + strlen (mfile) + 2);
311 (void)sprintf (path, "%s/%s", repository, mfile);
312 if (isdir (path))
314 /* directory means repository gets the dir tacked on */
315 (void)strcpy (repository, path);
316 (void)strcat (where, "/");
317 (void)strcat (where, mfile);
319 else
321 myargv[0] = argv[0];
322 myargv[1] = mfile;
323 argc = 2;
324 argv = myargv;
326 free (path);
329 /* cd to the starting repository */
330 if (CVS_CHDIR (repository) < 0)
332 error (0, errno, "cannot chdir to %s", repository);
333 free (repository);
334 free (where);
335 return 1;
338 if (force_tag_match)
339 which = W_REPOS | W_ATTIC;
340 else
341 which = W_REPOS;
343 if (rev1 != NULL && !rev1_validated)
345 tag_check_valid (rev1, argc - 1, argv + 1, local_specified, 0,
346 repository, false);
347 rev1_validated = 1;
349 if (rev2 != NULL && !rev2_validated)
351 tag_check_valid (rev2, argc - 1, argv + 1, local_specified, 0,
352 repository, false);
353 rev2_validated = 1;
356 /* start the recursion processor */
357 err = start_recursion (patch_fileproc, NULL, patch_dirproc, NULL, NULL,
358 argc - 1, argv + 1, local_specified,
359 which, 0, CVS_LOCK_READ, where, 1, repository );
360 free (repository);
361 free (where);
363 return err;
369 * Called to examine a particular RCS file, as appropriate with the options
370 * that were set above.
372 /* ARGSUSED */
373 static int
374 patch_fileproc (void *callerdat, struct file_info *finfo)
376 struct utimbuf t;
377 char *vers_tag, *vers_head;
378 char *rcs = NULL;
379 char *rcs_orig = NULL;
380 RCSNode *rcsfile;
381 FILE *fp1, *fp2, *fp3;
382 int ret = 0;
383 int isattic = 0;
384 int retcode = 0;
385 char *file1;
386 char *file2;
387 char *strippath;
388 char *line1, *line2;
389 size_t line1_chars_allocated;
390 size_t line2_chars_allocated;
391 char *cp1, *cp2;
392 FILE *fp;
393 int line_length;
394 int dargc = 0;
395 size_t darg_allocated = 0;
396 char **dargv = NULL;
398 line1 = NULL;
399 line1_chars_allocated = 0;
400 line2 = NULL;
401 line2_chars_allocated = 0;
402 vers_tag = vers_head = NULL;
404 /* find the parsed rcs file */
405 if ((rcsfile = finfo->rcs) == NULL)
407 ret = 1;
408 goto out2;
410 if ((rcsfile->flags & VALID) && (rcsfile->flags & INATTIC))
411 isattic = 1;
413 rcs_orig = rcs = Xasprintf ("%s%s", finfo->file, RCSEXT);
415 /* if vers_head is NULL, may have been removed from the release */
416 if (isattic && rev2 == NULL && date2 == NULL)
417 vers_head = NULL;
418 else
420 vers_head = RCS_getversion (rcsfile, rev2, date2, force_tag_match,
421 NULL);
422 if (vers_head != NULL && RCS_isdead (rcsfile, vers_head))
424 free (vers_head);
425 vers_head = NULL;
429 if (toptwo_diffs)
431 if (vers_head == NULL)
433 ret = 1;
434 goto out2;
437 if (!date1)
438 date1 = xmalloc (MAXDATELEN);
439 *date1 = '\0';
440 if (RCS_getrevtime (rcsfile, vers_head, date1, 1) == (time_t)-1)
442 if (!really_quiet)
443 error (0, 0, "cannot find date in rcs file %s revision %s",
444 rcs, vers_head);
445 ret = 1;
446 goto out2;
449 vers_tag = RCS_getversion (rcsfile, rev1, date1, force_tag_match, NULL);
450 if (vers_tag != NULL && RCS_isdead (rcsfile, vers_tag))
452 free (vers_tag);
453 vers_tag = NULL;
456 if ((vers_tag == NULL && vers_head == NULL) ||
457 (vers_tag != NULL && vers_head != NULL &&
458 strcmp (vers_head, vers_tag) == 0))
460 /* Nothing known about specified revs or
461 * not changed between releases.
463 ret = 0;
464 goto out2;
467 if (patch_short && (vers_tag == NULL || vers_head == NULL))
469 /* For adds & removes with a short patch requested, we can print our
470 * error message now and get out.
472 cvs_output ("File ", 0);
473 cvs_output (finfo->fullname, 0);
474 if (vers_tag == NULL)
476 cvs_output (" is new; ", 0);
477 cvs_output (rev2 ? rev2 : date2 ? date2 : "current", 0);
478 cvs_output (" revision ", 0);
479 cvs_output (vers_head, 0);
480 cvs_output ("\n", 1);
482 else
484 cvs_output (" is removed; ", 0);
485 cvs_output (rev1 ? rev1 : date1, 0);
486 cvs_output (" revision ", 0);
487 cvs_output (vers_tag, 0);
488 cvs_output ("\n", 1);
490 ret = 0;
491 goto out2;
494 /* Create 3 empty files. I'm not really sure there is any advantage
495 * to doing so now rather than just waiting until later.
497 * There is - cvs_temp_file opens the file so that it can guarantee that
498 * we have exclusive write access to the file. Unfortunately we spoil that
499 * by closing it and reopening it again. Of course any better solution
500 * requires that the RCS functions accept open file pointers rather than
501 * simple file names.
503 if ((fp1 = cvs_temp_file (&tmpfile1)) == NULL)
505 error (0, errno, "cannot create temporary file %s", tmpfile1);
506 ret = 1;
507 goto out;
509 else
510 if (fclose (fp1) < 0)
511 error (0, errno, "warning: cannot close %s", tmpfile1);
512 if ((fp2 = cvs_temp_file (&tmpfile2)) == NULL)
514 error (0, errno, "cannot create temporary file %s", tmpfile2);
515 ret = 1;
516 goto out;
518 else
519 if (fclose (fp2) < 0)
520 error (0, errno, "warning: cannot close %s", tmpfile2);
521 if ((fp3 = cvs_temp_file (&tmpfile3)) == NULL)
523 error (0, errno, "cannot create temporary file %s", tmpfile3);
524 ret = 1;
525 goto out;
527 else
528 if (fclose (fp3) < 0)
529 error (0, errno, "warning: cannot close %s", tmpfile3);
531 if (vers_tag != NULL)
533 retcode = RCS_checkout (rcsfile, NULL, vers_tag, rev1, options,
534 tmpfile1, NULL, NULL);
535 if (retcode != 0)
537 error (0, 0,
538 "cannot check out revision %s of %s", vers_tag, rcs);
539 ret = 1;
540 goto out;
542 memset ((char *) &t, 0, sizeof (t));
543 if ((t.actime = t.modtime = RCS_getrevtime (rcsfile, vers_tag,
544 NULL, 0)) != -1)
545 /* I believe this timestamp only affects the dates in our diffs,
546 and therefore should be on the server, not the client. */
547 (void)utime (tmpfile1, &t);
549 else if (toptwo_diffs)
551 ret = 1;
552 goto out;
554 if (vers_head != NULL)
556 retcode = RCS_checkout (rcsfile, NULL, vers_head, rev2, options,
557 tmpfile2, NULL, NULL);
558 if (retcode != 0)
560 error (0, 0,
561 "cannot check out revision %s of %s", vers_head, rcs);
562 ret = 1;
563 goto out;
565 if ((t.actime = t.modtime = RCS_getrevtime (rcsfile, vers_head,
566 NULL, 0)) != -1)
567 /* I believe this timestamp only affects the dates in our diffs,
568 and therefore should be on the server, not the client. */
569 (void)utime (tmpfile2, &t);
572 if (unidiff) run_add_arg_p (&dargc, &darg_allocated, &dargv, "-u");
573 else run_add_arg_p (&dargc, &darg_allocated, &dargv, "-c");
574 switch (diff_exec (tmpfile1, tmpfile2, NULL, NULL, dargc, dargv,
575 tmpfile3))
577 case -1: /* fork/wait failure */
578 error (1, errno, "fork for diff failed on %s", rcs);
579 break;
580 case 0: /* nothing to do */
581 break;
582 case 1:
584 * The two revisions are really different, so read the first two
585 * lines of the diff output file, and munge them to include more
586 * reasonable file names that "patch" will understand, unless the
587 * user wanted a short patch. In that case, just output the short
588 * message.
590 if (patch_short)
592 cvs_output ("File ", 0);
593 cvs_output (finfo->fullname, 0);
594 cvs_output (" changed from revision ", 0);
595 cvs_output (vers_tag, 0);
596 cvs_output (" to ", 0);
597 cvs_output (vers_head, 0);
598 cvs_output ("\n", 1);
599 ret = 0;
600 goto out;
603 /* Output an "Index:" line for patch to use */
604 cvs_output ("Index: ", 0);
605 cvs_output (finfo->fullname, 0);
606 cvs_output ("\n", 1);
608 /* Now the munging. */
609 fp = xfopen (tmpfile3, "r");
610 if (getline (&line1, &line1_chars_allocated, fp) < 0 ||
611 getline (&line2, &line2_chars_allocated, fp) < 0)
613 if (feof (fp))
614 error (0, 0, "\
615 failed to read diff file header %s for %s: end of file", tmpfile3, rcs);
616 else
617 error (0, errno,
618 "failed to read diff file header %s for %s",
619 tmpfile3, rcs);
620 ret = 1;
621 if (fclose (fp) < 0)
622 error (0, errno, "error closing %s", tmpfile3);
623 goto out;
625 if (!unidiff)
627 if (strncmp (line1, "*** ", 4) != 0 ||
628 strncmp (line2, "--- ", 4) != 0 ||
629 (cp1 = strchr (line1, '\t')) == NULL ||
630 (cp2 = strchr (line2, '\t')) == NULL)
632 error (0, 0, "invalid diff header for %s", rcs);
633 ret = 1;
634 if (fclose (fp) < 0)
635 error (0, errno, "error closing %s", tmpfile3);
636 goto out;
639 else
641 if (strncmp (line1, "--- ", 4) != 0 ||
642 strncmp (line2, "+++ ", 4) != 0 ||
643 (cp1 = strchr (line1, '\t')) == NULL ||
644 (cp2 = strchr (line2, '\t')) == NULL)
646 error (0, 0, "invalid unidiff header for %s", rcs);
647 ret = 1;
648 if (fclose (fp) < 0)
649 error (0, errno, "error closing %s", tmpfile3);
650 goto out;
653 assert (current_parsed_root != NULL);
654 assert (current_parsed_root->directory != NULL);
656 strippath = Xasprintf ("%s/", current_parsed_root->directory);
658 if (strncmp (rcs, strippath, strlen (strippath)) == 0)
659 rcs += strlen (strippath);
660 free (strippath);
661 if (vers_tag != NULL)
662 file1 = Xasprintf ("%s:%s", finfo->fullname, vers_tag);
663 else
664 file1 = xstrdup (DEVNULL);
666 file2 = Xasprintf ("%s:%s", finfo->fullname,
667 vers_head ? vers_head : "removed");
669 /* Note that the string "diff" is specified by POSIX (for -c)
670 and is part of the diff output format, not the name of a
671 program. */
672 if (unidiff)
674 cvs_output ("diff -u ", 0);
675 cvs_output (file1, 0);
676 cvs_output (" ", 1);
677 cvs_output (file2, 0);
678 cvs_output ("\n", 1);
680 cvs_output ("--- ", 0);
681 cvs_output (file1, 0);
682 cvs_output (cp1, 0);
683 cvs_output ("+++ ", 0);
685 else
687 cvs_output ("diff -c ", 0);
688 cvs_output (file1, 0);
689 cvs_output (" ", 1);
690 cvs_output (file2, 0);
691 cvs_output ("\n", 1);
693 cvs_output ("*** ", 0);
694 cvs_output (file1, 0);
695 cvs_output (cp1, 0);
696 cvs_output ("--- ", 0);
699 cvs_output (finfo->fullname, 0);
700 cvs_output (cp2, 0);
702 /* spew the rest of the diff out */
703 while ((line_length
704 = getline (&line1, &line1_chars_allocated, fp))
705 >= 0)
706 cvs_output (line1, 0);
707 if (line_length < 0 && !feof (fp))
708 error (0, errno, "cannot read %s", tmpfile3);
710 if (fclose (fp) < 0)
711 error (0, errno, "cannot close %s", tmpfile3);
712 free (file1);
713 free (file2);
714 break;
715 default:
716 error (0, 0, "diff failed for %s", finfo->fullname);
718 out:
719 if (line1)
720 free (line1);
721 if (line2)
722 free (line2);
723 if (CVS_UNLINK (tmpfile1) < 0)
724 error (0, errno, "cannot unlink %s", tmpfile1);
725 if (CVS_UNLINK (tmpfile2) < 0)
726 error (0, errno, "cannot unlink %s", tmpfile2);
727 if (CVS_UNLINK (tmpfile3) < 0)
728 error (0, errno, "cannot unlink %s", tmpfile3);
729 free (tmpfile1);
730 free (tmpfile2);
731 free (tmpfile3);
732 tmpfile1 = tmpfile2 = tmpfile3 = NULL;
733 if (darg_allocated)
735 run_arg_free_p (dargc, dargv);
736 free (dargv);
739 out2:
740 if (vers_tag != NULL)
741 free (vers_tag);
742 if (vers_head != NULL)
743 free (vers_head);
744 if (rcs_orig)
745 free (rcs_orig);
746 return ret;
752 * Print a warm fuzzy message
754 /* ARGSUSED */
755 static Dtype
756 patch_dirproc (void *callerdat, const char *dir, const char *repos,
757 const char *update_dir, List *entries)
759 if (!quiet)
760 error (0, 0, "Diffing %s", update_dir);
761 return R_PROCESS;
767 * Clean up temporary files
769 static RETSIGTYPE
770 patch_cleanup (int sig)
772 /* Note that the checks for existence_error are because we are
773 called from a signal handler, without SIG_begincrsect, so
774 we don't know whether the files got created. */
776 static int reenter = 0;
778 if (reenter++)
779 _exit(1);
781 if (tmpfile1 != NULL)
783 if (unlink_file (tmpfile1) < 0
784 && !existence_error (errno))
785 error (0, errno, "cannot remove %s", tmpfile1);
786 free (tmpfile1);
788 if (tmpfile2 != NULL)
790 if (unlink_file (tmpfile2) < 0
791 && !existence_error (errno))
792 error (0, errno, "cannot remove %s", tmpfile2);
793 free (tmpfile2);
795 if (tmpfile3 != NULL)
797 if (unlink_file (tmpfile3) < 0
798 && !existence_error (errno))
799 error (0, errno, "cannot remove %s", tmpfile3);
800 free (tmpfile3);
802 tmpfile1 = tmpfile2 = tmpfile3 = NULL;
804 if (sig != 0)
806 const char *name;
807 char temp[10];
809 switch (sig)
811 #ifdef SIGABRT
812 case SIGABRT:
813 name = "abort";
814 break;
815 #endif
816 #ifdef SIGHUP
817 case SIGHUP:
818 name = "hangup";
819 break;
820 #endif
821 #ifdef SIGINT
822 case SIGINT:
823 name = "interrupt";
824 break;
825 #endif
826 #ifdef SIGQUIT
827 case SIGQUIT:
828 name = "quit";
829 break;
830 #endif
831 #ifdef SIGPIPE
832 case SIGPIPE:
833 name = "broken pipe";
834 break;
835 #endif
836 #ifdef SIGTERM
837 case SIGTERM:
838 name = "termination";
839 break;
840 #endif
841 default:
842 /* This case should never be reached, because we list
843 above all the signals for which we actually establish a
844 signal handler. */
845 sprintf (temp, "%d", sig);
846 name = temp;
847 break;
849 error (0, 0, "received %s signal", name);