⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdiff.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	int diff_fds[2];	if (pipe (diff_fds) != 0)	  perror_fatal ("pipe");	diffpid = fork ();	if (diffpid < 0)	  perror_fatal ("fork failed");	if (!diffpid)	  {	    signal (SIGINT, SIG_IGN);  /* in case user interrupts editor */	    signal (SIGPIPE, SIG_DFL);	    close (diff_fds[0]);	    if (diff_fds[1] != STDOUT_FILENO)	      {		dup2 (diff_fds[1], STDOUT_FILENO);		close (diff_fds[1]);	      }	    execdiff ();	  }	close (diff_fds[1]);	diffout = fdopen (diff_fds[0], "r");	if (!diffout)	  perror_fatal ("fdopen");      }#endif /* HAVE_FORK */      lf_init (&diff_filt, diffout);      lf_init (&lfilt, left);      lf_init (&rfilt, right);      interact_ok = interact (&diff_filt, &lfilt, &rfilt, out);      ck_fclose (left);      ck_fclose (right);      ck_fclose (out);      {	int wstatus;#if ! HAVE_FORK	wstatus = pclose (diffout);#else	ck_fclose (diffout);	while (waitpid (diffpid, &wstatus, 0) < 0)	  if (errno == EINTR)	    checksigs ();	  else	    perror_fatal ("wait failed");	diffpid = 0;#endif	if (tmpmade)	  {	    unlink (tmpname);	    tmpmade = 0;	  }	if (! interact_ok)	  exiterr ();	if (! (WIFEXITED (wstatus) && WEXITSTATUS (wstatus) < 2))	  fatal ("Subsidiary diff failed");	untrapsig (0);	checksigs ();	exit (WEXITSTATUS (wstatus));      }    }  return 0;			/* Fool -Wall . . . */}static voiddiffarg (a)     char const *a;{  static unsigned diffargs, diffargsmax;  if (diffargs == diffargsmax)    {      if (! diffargsmax)	{	  diffargv = (char const **) xmalloc (sizeof (char));	  diffargsmax = 8;	}      diffargsmax *= 2;      diffargv = (char const **) realloc (diffargv,					  diffargsmax * sizeof (char const *));      if (! diffargv)	fatal ("out of memory");    }  diffargv[diffargs++] = a;}static voidexecdiff (){  execvp (diffbin, (char **) diffargv);  write (STDERR_FILENO, diffbin, strlen (diffbin));  write (STDERR_FILENO, ": not found\n", 12);  _exit (2);}/* Signal handling */#define NUM_SIGS (sizeof (sigs) / sizeof (*sigs))static int const sigs[] = {#ifdef SIGHUP       SIGHUP,#endif#ifdef SIGQUIT       SIGQUIT,#endif#ifdef SIGTERM       SIGTERM,#endif#ifdef SIGXCPU       SIGXCPU,#endif#ifdef SIGXFSZ       SIGXFSZ,#endif       SIGINT,       SIGPIPE};/* Prefer `sigaction' if it is available, since `signal' can lose signals.  */#if HAVE_SIGACTIONstatic struct sigaction initial_action[NUM_SIGS];#define initial_handler(i) (initial_action[i].sa_handler)#elsestatic RETSIGTYPE (*initial_action[NUM_SIGS]) ();#define initial_handler(i) (initial_action[i])#endifstatic int volatile ignore_SIGINT;static int volatile signal_received;static int sigs_trapped;static RETSIGTYPEcatchsig (s)     int s;{#if ! HAVE_SIGACTION  signal (s, SIG_IGN);#endif  if (! (s == SIGINT && ignore_SIGINT))    signal_received = s;}static voidtrapsigs (){  int i;#if HAVE_SIGACTION  struct sigaction catchaction;  bzero (&catchaction, sizeof (catchaction));  catchaction.sa_handler = catchsig;#ifdef SA_INTERRUPT  /* Non-Posix BSD-style systems like SunOS 4.1.x need this     so that `read' calls are interrupted properly.  */  catchaction.sa_flags = SA_INTERRUPT;#endif  sigemptyset (&catchaction.sa_mask);  for (i = 0;  i < NUM_SIGS;  i++)    sigaddset (&catchaction.sa_mask, sigs[i]);  for (i = 0;  i < NUM_SIGS;  i++)    {      sigaction (sigs[i], 0, &initial_action[i]);      if (initial_handler (i) != SIG_IGN	  && sigaction (sigs[i], &catchaction, 0) != 0)	fatal ("signal error");    }#else /* ! HAVE_SIGACTION */  for (i = 0;  i < NUM_SIGS;  i++)    {      initial_action[i] = signal (sigs[i], SIG_IGN);      if (initial_handler (i) != SIG_IGN	  && signal (sigs[i], catchsig) != SIG_IGN)	fatal ("signal error");    }#endif /* ! HAVE_SIGACTION */#if !defined(SIGCHLD) && defined(SIGCLD)#define SIGCHLD SIGCLD#endif#ifdef SIGCHLD  /* System V fork+wait does not work if SIGCHLD is ignored.  */  signal (SIGCHLD, SIG_DFL);#endif  sigs_trapped = 1;}/* Untrap signal S, or all trapped signals if S is zero.  */static voiduntrapsig (s)     int s;{  int i;  if (sigs_trapped)    for (i = 0;  i < NUM_SIGS;  i++)      if ((!s || sigs[i] == s)  &&  initial_handler (i) != SIG_IGN)#if HAVE_SIGACTION	  sigaction (sigs[i], &initial_action[i], 0);#else	  signal (sigs[i], initial_action[i]);#endif}/* Exit if a signal has been received.  */static voidchecksigs (){  int s = signal_received;  if (s)    {      cleanup ();      /* Yield an exit status indicating that a signal was received.  */      untrapsig (s);      kill (getpid (), s);      /* That didn't work, so exit with error status.  */      exit (2);    }}static voidgive_help (){  fprintf (stderr,"l:\tuse the left version\n");  fprintf (stderr,"r:\tuse the right version\n");  fprintf (stderr,"e l:\tedit then use the left version\n");  fprintf (stderr,"e r:\tedit then use the right version\n");  fprintf (stderr,"e b:\tedit then use the left and right versions concatenated\n");  fprintf (stderr,"e:\tedit a new version\n");  fprintf (stderr,"s:\tsilently include common lines\n");  fprintf (stderr,"v:\tverbosely include common lines\n");  fprintf (stderr,"q:\tquit\n");}static intskip_white (){  int c;  for (;;)    {      c = getchar ();      if (!ISSPACE (c) || c == '\n')	break;      checksigs ();    }  if (ferror (stdin))    perror_fatal ("input error");  return c;}static voidflush_line (){  int c;  while ((c = getchar ()) != '\n' && c != EOF)    ;  if (ferror (stdin))    perror_fatal ("input error");}/* interpret an edit command */static intedit (left, lenl, right, lenr, outfile)     struct line_filter *left;     int lenl;     struct line_filter *right;     int lenr;     FILE *outfile;{  for (;;)    {      int cmd0, cmd1;      int gotcmd = 0;      cmd1 = 0; /* Pacify `gcc -W'.  */      while (!gotcmd)	{	  if (putchar ('%') != '%')	    perror_fatal ("output error");	  ck_fflush (stdout);	  cmd0 = skip_white ();	  switch (cmd0)	    {	    case 'l': case 'r': case 's': case 'v': case 'q':	      if (skip_white () != '\n')		{		  give_help ();		  flush_line ();		  continue;		}	      gotcmd = 1;	      break;	    case 'e':	      cmd1 = skip_white ();	      switch (cmd1)		{		case 'l': case 'r': case 'b':		  if (skip_white () != '\n')		    {		      give_help ();		      flush_line ();		      continue;		    }		  gotcmd = 1;		  break;		case '\n':		  gotcmd = 1;		  break;		default:		  give_help ();		  flush_line ();		  continue;		}	      break;	    case EOF:	      if (feof (stdin))		{		  gotcmd = 1;		  cmd0 = 'q';		  break;		}	      /* falls through */	    default:	      flush_line ();	      /* falls through */	    case '\n':	      give_help ();	      continue;	    }	}      switch (cmd0)	{	case 'l':	  lf_copy (left, lenl, outfile);	  lf_skip (right, lenr);	  return 1;	case 'r':	  lf_copy (right, lenr, outfile);	  lf_skip (left, lenl);	  return 1;	case 's':	  suppress_common_flag = 1;	  break;	case 'v':	  suppress_common_flag = 0;	  break;	case 'q':	  return 0;	case 'e':	  {	    int tfd;	    FILE *tmp;	    if (tmpmade)	      {	        unlink (tmpname);	        tmpmade = 0;		free (tmpname);	      }	    asprintf (&tmpname, "%s/sdiff.XXXXXX",	      getenv("TMPDIR") ?: P_tmpdir);	    if (tmpname == NULL)	      perror_fatal ("temporary file name");	    tfd = mkstemp(tmpname);	    if (tfd == -1)	      perror_fatal ("temporary file name");	    tmp = fdopen (tfd, "w+");	    if (tmp == NULL)	      perror_fatal ("temporary file name"); 	    tmpmade = 1;	    if (cmd1 == 'l' || cmd1 == 'b')	      lf_copy (left, lenl, tmp);	    else	      lf_skip (left, lenl);	    if (cmd1 == 'r' || cmd1 == 'b')	      lf_copy (right, lenr, tmp);	    else	      lf_skip (right, lenr);	    ck_fflush (tmp);	    {	      int wstatus;#if ! HAVE_FORK	      char *command = xmalloc (strlen (edbin) + strlen (tmpname) + 2);	      sprintf (command, "%s %s", edbin, tmpname);	      wstatus = system (command);	      free (command);#else /* HAVE_FORK */	      pid_t pid;	      ignore_SIGINT = 1;	      checksigs ();	      pid = fork ();	      if (pid == 0)		{		  char const *argv[3];		  int i = 0;		  argv[i++] = edbin;		  argv[i++] = tmpname;		  argv[i++] = 0;		  execvp (edbin, (char **) argv);		  write (STDERR_FILENO, edbin, strlen (edbin));		  write (STDERR_FILENO, ": not found\n", 12);		  _exit (1);		}	      if (pid < 0)		perror_fatal ("fork failed");	      while (waitpid (pid, &wstatus, 0) < 0)		if (errno == EINTR)		  checksigs ();		else		  perror_fatal ("wait failed");	      ignore_SIGINT = 0;#endif /* HAVE_FORK */	      if (wstatus != 0)		fatal ("Subsidiary editor failed");	    }	    if (fseek (tmp, 0L, SEEK_SET) != 0)	      perror_fatal ("fseek");	    {	      /* SDIFF_BUFSIZE is too big for a local var		 in some compilers, so we allocate it dynamically.  */	      char *buf = xmalloc (SDIFF_BUFSIZE);	      size_t size;	      while ((size = ck_fread (buf, SDIFF_BUFSIZE, tmp)) != 0)		{		  checksigs ();		  ck_fwrite (buf, size, outfile);		}	      ck_fclose (tmp);	      free (buf);	    }	    return 1;	  }	default:	  give_help ();	  break;	}    }}/* Alternately reveal bursts of diff output and handle user commands.  */static intinteract (diff, left, right, outfile)     struct line_filter *diff;     struct line_filter *left;     struct line_filter *right;     FILE *outfile;{  for (;;)    {      char diff_help[256];      int snarfed = lf_snarf (diff, diff_help, sizeof (diff_help));      if (snarfed <= 0)	return snarfed;      checksigs ();      switch (diff_help[0])	{	case ' ':	  puts (diff_help + 1);	  break;	case 'i':	  {	    int lenl = atoi (diff_help + 1), lenr, lenmax;	    char *p = strchr (diff_help, ',');	    if (!p)	      fatal (diff_help);	    lenr = atoi (p + 1);	    lenmax = max (lenl, lenr);	    if (suppress_common_flag)	      lf_skip (diff, lenmax);	    else	      lf_copy (diff, lenmax, stdout);	    lf_copy (left, lenl, outfile);	    lf_skip (right, lenr);	    break;	  }	case 'c':	  {	    int lenl = atoi (diff_help + 1), lenr;	    char *p = strchr (diff_help, ',');	    if (!p)	      fatal (diff_help);	    lenr = atoi (p + 1);	    lf_copy (diff, max (lenl, lenr), stdout);	    if (! edit (left, lenl, right, lenr, outfile))	      return 0;	    break;	  }	default:	  fatal (diff_help);	  break;	}    }}/* temporary lossage: this is torn from gnu libc *//* Return nonzero if DIR is an existing directory.  */static intdiraccess (dir)     char const *dir;{  struct stat buf;  return stat (dir, &buf) == 0 && S_ISDIR (buf.st_mode);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -