1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * sdiff [-l] [-s] [-w #] [-o output] file1 file2 35*7c478bd9Sstevel@tonic-gate * does side by side diff listing 36*7c478bd9Sstevel@tonic-gate * -l leftside only for identical lines 37*7c478bd9Sstevel@tonic-gate * -s silent; only print differences 38*7c478bd9Sstevel@tonic-gate * -w # width of output 39*7c478bd9Sstevel@tonic-gate * -o output interactive creation of new output commands: 40*7c478bd9Sstevel@tonic-gate * s silent; do not print identical lines 41*7c478bd9Sstevel@tonic-gate * v turn off silent 42*7c478bd9Sstevel@tonic-gate * l copy left side to output 43*7c478bd9Sstevel@tonic-gate * r copy right side to output 44*7c478bd9Sstevel@tonic-gate * e l call ed with left side 45*7c478bd9Sstevel@tonic-gate * e r call ed with right side 46*7c478bd9Sstevel@tonic-gate * e b call ed with cat of left and right 47*7c478bd9Sstevel@tonic-gate * e call ed with empty file 48*7c478bd9Sstevel@tonic-gate * q exit from program 49*7c478bd9Sstevel@tonic-gate * 50*7c478bd9Sstevel@tonic-gate * functions: 51*7c478bd9Sstevel@tonic-gate * cmd decode diff commands 52*7c478bd9Sstevel@tonic-gate * put1 output left side 53*7c478bd9Sstevel@tonic-gate * put2 output right side 54*7c478bd9Sstevel@tonic-gate * putmid output gutter 55*7c478bd9Sstevel@tonic-gate * putline output n chars to indicated file 56*7c478bd9Sstevel@tonic-gate * getlen calculate length of strings with tabs 57*7c478bd9Sstevel@tonic-gate * cmdin read and process interactive cmds 58*7c478bd9Sstevel@tonic-gate * cpp copy from file to file 59*7c478bd9Sstevel@tonic-gate * edit call ed with file 60*7c478bd9Sstevel@tonic-gate */ 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate #include <stdio.h> 63*7c478bd9Sstevel@tonic-gate #include <ctype.h> 64*7c478bd9Sstevel@tonic-gate #include <signal.h> 65*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 66*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 67*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 68*7c478bd9Sstevel@tonic-gate #include <unistd.h> 69*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 70*7c478bd9Sstevel@tonic-gate #include <locale.h> 71*7c478bd9Sstevel@tonic-gate #include <limits.h> 72*7c478bd9Sstevel@tonic-gate #include <string.h> 73*7c478bd9Sstevel@tonic-gate #include <wchar.h> 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate #define LMAX BUFSIZ 76*7c478bd9Sstevel@tonic-gate #define BMAX BUFSIZ 77*7c478bd9Sstevel@tonic-gate #define STDOUT 1 78*7c478bd9Sstevel@tonic-gate #define WGUTTER 6 79*7c478bd9Sstevel@tonic-gate #define WLEN (WGUTTER * 2 + WGUTTER + 2) 80*7c478bd9Sstevel@tonic-gate #define PROMPT '%' 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate static const char twoblanks[3] = " "; 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate static const char *DIFF = "diff -b "; 85*7c478bd9Sstevel@tonic-gate static char diffcmd[BMAX]; 86*7c478bd9Sstevel@tonic-gate static char inbuf[10]; 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate static int llen = 130; /* Default maximum line length written out */ 89*7c478bd9Sstevel@tonic-gate static int hlen; /* Half line length with space for gutter */ 90*7c478bd9Sstevel@tonic-gate static int len1; /* Calculated length of left side */ 91*7c478bd9Sstevel@tonic-gate static int nchars; /* Number of characters in left side - */ 92*7c478bd9Sstevel@tonic-gate /* used for tab expansion */ 93*7c478bd9Sstevel@tonic-gate static char change = ' '; 94*7c478bd9Sstevel@tonic-gate static int leftonly = 0; /* if set print left side only for */ 95*7c478bd9Sstevel@tonic-gate /* identical lines */ 96*7c478bd9Sstevel@tonic-gate static int silent = 0; /* if set do not print identical lines */ 97*7c478bd9Sstevel@tonic-gate static int midflg = 0; /* set after middle was output */ 98*7c478bd9Sstevel@tonic-gate static int rcode = 0; /* return code */ 99*7c478bd9Sstevel@tonic-gate 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate static char *file1; 102*7c478bd9Sstevel@tonic-gate static FILE *fdes1; 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate static char *file2; 105*7c478bd9Sstevel@tonic-gate static FILE *fdes2; 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate static FILE *diffdes; 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate static int oflag; 110*7c478bd9Sstevel@tonic-gate static char *ofile; 111*7c478bd9Sstevel@tonic-gate static FILE *odes; 112*7c478bd9Sstevel@tonic-gate 113*7c478bd9Sstevel@tonic-gate static char *ltemp; 114*7c478bd9Sstevel@tonic-gate static FILE *left; 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate static char *rtemp; 117*7c478bd9Sstevel@tonic-gate static FILE *right; 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate static FILE *tempdes; 120*7c478bd9Sstevel@tonic-gate static char *temp; 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate /* decoded diff cmd- left side from to; right side from, to */ 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate static int from1, to1, from2, to2; 125*7c478bd9Sstevel@tonic-gate 126*7c478bd9Sstevel@tonic-gate static int num1, num2; /* line count for left side file and right */ 127*7c478bd9Sstevel@tonic-gate static int tempfd = -1; 128*7c478bd9Sstevel@tonic-gate 129*7c478bd9Sstevel@tonic-gate static char *filename(char *, char *); 130*7c478bd9Sstevel@tonic-gate static char *fgetline(FILE *); 131*7c478bd9Sstevel@tonic-gate static int put1(void); 132*7c478bd9Sstevel@tonic-gate static int put2(void); 133*7c478bd9Sstevel@tonic-gate static void putline(FILE *, char *, int); 134*7c478bd9Sstevel@tonic-gate static int cmd(char *); 135*7c478bd9Sstevel@tonic-gate static int getlen(int, char *); 136*7c478bd9Sstevel@tonic-gate static void putmid(int); 137*7c478bd9Sstevel@tonic-gate static void error(char *, char *); 138*7c478bd9Sstevel@tonic-gate static void onintr(void); 139*7c478bd9Sstevel@tonic-gate static void sremove(void); 140*7c478bd9Sstevel@tonic-gate static void cmdin(void); 141*7c478bd9Sstevel@tonic-gate static void cpp(char *, FILE *, FILE *); 142*7c478bd9Sstevel@tonic-gate static void edit(char *); 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate void 145*7c478bd9Sstevel@tonic-gate main(int argc, char **argv) 146*7c478bd9Sstevel@tonic-gate { 147*7c478bd9Sstevel@tonic-gate int com; 148*7c478bd9Sstevel@tonic-gate int n1, n2, n; 149*7c478bd9Sstevel@tonic-gate char *bp; 150*7c478bd9Sstevel@tonic-gate int lfd = -1; 151*7c478bd9Sstevel@tonic-gate int rfd = -1; 152*7c478bd9Sstevel@tonic-gate 153*7c478bd9Sstevel@tonic-gate if (signal(SIGHUP, SIG_IGN) != SIG_IGN) 154*7c478bd9Sstevel@tonic-gate (void) signal((int)SIGHUP, (void (*)(int))onintr); 155*7c478bd9Sstevel@tonic-gate if (signal(SIGINT, SIG_IGN) != SIG_IGN) 156*7c478bd9Sstevel@tonic-gate (void) signal((int)SIGINT, (void (*)(int))onintr); 157*7c478bd9Sstevel@tonic-gate if (signal(SIGPIPE, SIG_IGN) != SIG_IGN) 158*7c478bd9Sstevel@tonic-gate (void) signal((int)SIGPIPE, (void (*)(int))onintr); 159*7c478bd9Sstevel@tonic-gate if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 160*7c478bd9Sstevel@tonic-gate (void) signal((int)SIGTERM, (void (*)(int))onintr); 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 163*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 164*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 165*7c478bd9Sstevel@tonic-gate #endif 166*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate while (--argc > 1 && **++argv == '-') { 169*7c478bd9Sstevel@tonic-gate switch (*++*argv) { 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate case 'w': 172*7c478bd9Sstevel@tonic-gate /* -w# instead of -w # */ 173*7c478bd9Sstevel@tonic-gate if (*++*argv) 174*7c478bd9Sstevel@tonic-gate llen = atoi(*argv); 175*7c478bd9Sstevel@tonic-gate else { 176*7c478bd9Sstevel@tonic-gate argc--; 177*7c478bd9Sstevel@tonic-gate llen = atoi(*++argv); 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate if (llen < WLEN) 180*7c478bd9Sstevel@tonic-gate error(gettext("Wrong line length %s"), *argv); 181*7c478bd9Sstevel@tonic-gate if (llen > LMAX) 182*7c478bd9Sstevel@tonic-gate llen = LMAX; 183*7c478bd9Sstevel@tonic-gate break; 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate case 'l': 186*7c478bd9Sstevel@tonic-gate leftonly++; 187*7c478bd9Sstevel@tonic-gate break; 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate case 's': 190*7c478bd9Sstevel@tonic-gate silent++; 191*7c478bd9Sstevel@tonic-gate break; 192*7c478bd9Sstevel@tonic-gate case 'o': 193*7c478bd9Sstevel@tonic-gate oflag++; 194*7c478bd9Sstevel@tonic-gate argc--; 195*7c478bd9Sstevel@tonic-gate ofile = *++argv; 196*7c478bd9Sstevel@tonic-gate break; 197*7c478bd9Sstevel@tonic-gate default: 198*7c478bd9Sstevel@tonic-gate error(gettext("Illegal argument: %s"), *argv); 199*7c478bd9Sstevel@tonic-gate } 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate if (argc != 2) { 202*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 203*7c478bd9Sstevel@tonic-gate "Usage: sdiff [-l] [-s] [-o output] [-w #] file1 file2\n")); 204*7c478bd9Sstevel@tonic-gate exit(2); 205*7c478bd9Sstevel@tonic-gate } 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gate file1 = *argv++; 208*7c478bd9Sstevel@tonic-gate file2 = *argv; 209*7c478bd9Sstevel@tonic-gate file1 = filename(file1, file2); 210*7c478bd9Sstevel@tonic-gate file2 = filename(file2, file1); 211*7c478bd9Sstevel@tonic-gate hlen = (llen - WGUTTER +1)/2; 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate if ((fdes1 = fopen(file1, "r")) == NULL) 214*7c478bd9Sstevel@tonic-gate error(gettext("Cannot open: %s"), file1); 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate if ((fdes2 = fopen(file2, "r")) == NULL) 217*7c478bd9Sstevel@tonic-gate error(gettext("Cannot open: %s"), file2); 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate if (oflag) { 220*7c478bd9Sstevel@tonic-gate if (tempfd == -1) { 221*7c478bd9Sstevel@tonic-gate temp = strdup("/tmp/sdiffXXXXXX"); 222*7c478bd9Sstevel@tonic-gate tempfd = mkstemp(temp); 223*7c478bd9Sstevel@tonic-gate if (tempfd == -1) { 224*7c478bd9Sstevel@tonic-gate error(gettext( 225*7c478bd9Sstevel@tonic-gate "Cannot open/create temp %s"), temp); 226*7c478bd9Sstevel@tonic-gate free(temp); 227*7c478bd9Sstevel@tonic-gate temp = 0; 228*7c478bd9Sstevel@tonic-gate } 229*7c478bd9Sstevel@tonic-gate } 230*7c478bd9Sstevel@tonic-gate ltemp = strdup("/tmp/sdifflXXXXXX"); 231*7c478bd9Sstevel@tonic-gate if ((lfd = mkstemp(ltemp)) == -1 || 232*7c478bd9Sstevel@tonic-gate (left = fdopen(lfd, "w")) == NULL) 233*7c478bd9Sstevel@tonic-gate error(gettext( 234*7c478bd9Sstevel@tonic-gate "Cannot open/create temp %s"), 235*7c478bd9Sstevel@tonic-gate ltemp); 236*7c478bd9Sstevel@tonic-gate rtemp = strdup("/tmp/sdiffrXXXXXX"); 237*7c478bd9Sstevel@tonic-gate if ((rfd = mkstemp(rtemp)) == -1 || 238*7c478bd9Sstevel@tonic-gate (right = fdopen(rfd, "w")) == NULL) 239*7c478bd9Sstevel@tonic-gate error(gettext( 240*7c478bd9Sstevel@tonic-gate "Cannot open/create temp file %s"), 241*7c478bd9Sstevel@tonic-gate rtemp); 242*7c478bd9Sstevel@tonic-gate if ((odes = fopen(ofile, "w")) == NULL) 243*7c478bd9Sstevel@tonic-gate error(gettext("Cannot open output %s"), ofile); 244*7c478bd9Sstevel@tonic-gate } 245*7c478bd9Sstevel@tonic-gate /* Call DIFF command */ 246*7c478bd9Sstevel@tonic-gate (void) strcpy(diffcmd, DIFF); 247*7c478bd9Sstevel@tonic-gate (void) strcat(diffcmd, file1); 248*7c478bd9Sstevel@tonic-gate (void) strcat(diffcmd, " "); 249*7c478bd9Sstevel@tonic-gate (void) strcat(diffcmd, file2); 250*7c478bd9Sstevel@tonic-gate diffdes = popen(diffcmd, "r"); 251*7c478bd9Sstevel@tonic-gate 252*7c478bd9Sstevel@tonic-gate num1 = num2 = 0; 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate /* 255*7c478bd9Sstevel@tonic-gate * Read in diff output and decode commands 256*7c478bd9Sstevel@tonic-gate * "change" is used to determine character to put in gutter 257*7c478bd9Sstevel@tonic-gate * num1 and num2 counts the number of lines in file1 and 2 258*7c478bd9Sstevel@tonic-gate */ 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate n = 0; 261*7c478bd9Sstevel@tonic-gate while ((bp = fgetline(diffdes)) != NULL) { 262*7c478bd9Sstevel@tonic-gate change = ' '; 263*7c478bd9Sstevel@tonic-gate com = cmd(bp); 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate /* 266*7c478bd9Sstevel@tonic-gate * handles all diff output that is not cmd 267*7c478bd9Sstevel@tonic-gate * lines starting with <, >, ., --- 268*7c478bd9Sstevel@tonic-gate */ 269*7c478bd9Sstevel@tonic-gate if (com == 0) 270*7c478bd9Sstevel@tonic-gate continue; 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate /* Catch up to from1 and from2 */ 273*7c478bd9Sstevel@tonic-gate rcode = 1; 274*7c478bd9Sstevel@tonic-gate n1 = from1 - num1; 275*7c478bd9Sstevel@tonic-gate n2 = from2 - num2; 276*7c478bd9Sstevel@tonic-gate n = n1 > n2 ? n2 : n1; 277*7c478bd9Sstevel@tonic-gate if (com == 'c' && n > 0) 278*7c478bd9Sstevel@tonic-gate n--; 279*7c478bd9Sstevel@tonic-gate if (silent) 280*7c478bd9Sstevel@tonic-gate (void) fputs(bp, stdout); 281*7c478bd9Sstevel@tonic-gate while (n-- > 0) { 282*7c478bd9Sstevel@tonic-gate (void) put1(); 283*7c478bd9Sstevel@tonic-gate (void) put2(); 284*7c478bd9Sstevel@tonic-gate if (!silent) 285*7c478bd9Sstevel@tonic-gate (void) putc('\n', stdout); 286*7c478bd9Sstevel@tonic-gate midflg = 0; 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate /* Process diff cmd */ 290*7c478bd9Sstevel@tonic-gate switch (com) { 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate case 'a': 293*7c478bd9Sstevel@tonic-gate change = '>'; 294*7c478bd9Sstevel@tonic-gate while (num2 < to2) { 295*7c478bd9Sstevel@tonic-gate (void) put2(); 296*7c478bd9Sstevel@tonic-gate (void) putc('\n', stdout); 297*7c478bd9Sstevel@tonic-gate midflg = 0; 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate break; 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate case 'd': 302*7c478bd9Sstevel@tonic-gate change = '<'; 303*7c478bd9Sstevel@tonic-gate while (num1 < to1) { 304*7c478bd9Sstevel@tonic-gate (void) put1(); 305*7c478bd9Sstevel@tonic-gate (void) putc('\n', stdout); 306*7c478bd9Sstevel@tonic-gate midflg = 0; 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate break; 309*7c478bd9Sstevel@tonic-gate 310*7c478bd9Sstevel@tonic-gate case 'c': 311*7c478bd9Sstevel@tonic-gate n1 = to1 - from1; 312*7c478bd9Sstevel@tonic-gate n2 = to2 - from2; 313*7c478bd9Sstevel@tonic-gate n = n1 > n2 ? n2 : n1; 314*7c478bd9Sstevel@tonic-gate change = '|'; 315*7c478bd9Sstevel@tonic-gate do { 316*7c478bd9Sstevel@tonic-gate (void) put1(); 317*7c478bd9Sstevel@tonic-gate (void) put2(); 318*7c478bd9Sstevel@tonic-gate (void) putc('\n', stdout); 319*7c478bd9Sstevel@tonic-gate midflg = 0; 320*7c478bd9Sstevel@tonic-gate } while (n--); 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate change = '<'; 323*7c478bd9Sstevel@tonic-gate while (num1 < to1) { 324*7c478bd9Sstevel@tonic-gate (void) put1(); 325*7c478bd9Sstevel@tonic-gate (void) putc('\n', stdout); 326*7c478bd9Sstevel@tonic-gate midflg = 0; 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate change = '>'; 330*7c478bd9Sstevel@tonic-gate while (num2 < to2) { 331*7c478bd9Sstevel@tonic-gate (void) put2(); 332*7c478bd9Sstevel@tonic-gate (void) putc('\n', stdout); 333*7c478bd9Sstevel@tonic-gate midflg = 0; 334*7c478bd9Sstevel@tonic-gate } 335*7c478bd9Sstevel@tonic-gate break; 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate default: 338*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 339*7c478bd9Sstevel@tonic-gate "%c: cmd not found\n"), cmd); 340*7c478bd9Sstevel@tonic-gate break; 341*7c478bd9Sstevel@tonic-gate } 342*7c478bd9Sstevel@tonic-gate 343*7c478bd9Sstevel@tonic-gate if (oflag == 1 && com != 0) { 344*7c478bd9Sstevel@tonic-gate cmdin(); 345*7c478bd9Sstevel@tonic-gate if ((left = fopen(ltemp, "w")) == NULL) 346*7c478bd9Sstevel@tonic-gate error(gettext( 347*7c478bd9Sstevel@tonic-gate "main: Cannot open temp %s"), ltemp); 348*7c478bd9Sstevel@tonic-gate if ((right = fopen(rtemp, "w")) == NULL) 349*7c478bd9Sstevel@tonic-gate error(gettext( 350*7c478bd9Sstevel@tonic-gate "main: Cannot open temp %s"), rtemp); 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate } 353*7c478bd9Sstevel@tonic-gate /* put out remainder of input files */ 354*7c478bd9Sstevel@tonic-gate 355*7c478bd9Sstevel@tonic-gate while (put1()) { 356*7c478bd9Sstevel@tonic-gate (void) put2(); 357*7c478bd9Sstevel@tonic-gate if (!silent) 358*7c478bd9Sstevel@tonic-gate (void) putc('\n', stdout); 359*7c478bd9Sstevel@tonic-gate midflg = 0; 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate if (odes) 362*7c478bd9Sstevel@tonic-gate (void) fclose(odes); 363*7c478bd9Sstevel@tonic-gate sremove(); 364*7c478bd9Sstevel@tonic-gate exit(rcode); 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate static int 368*7c478bd9Sstevel@tonic-gate put1(void) 369*7c478bd9Sstevel@tonic-gate { 370*7c478bd9Sstevel@tonic-gate /* len1 = length of left side */ 371*7c478bd9Sstevel@tonic-gate /* nchars = num of chars including tabs */ 372*7c478bd9Sstevel@tonic-gate 373*7c478bd9Sstevel@tonic-gate char *bp; 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate if ((bp = fgetline(fdes1)) != NULL) { 377*7c478bd9Sstevel@tonic-gate len1 = getlen(0, bp); 378*7c478bd9Sstevel@tonic-gate if ((!silent || change != ' ') && len1 != 0) 379*7c478bd9Sstevel@tonic-gate putline(stdout, bp, nchars); 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate if (oflag) { 382*7c478bd9Sstevel@tonic-gate /* 383*7c478bd9Sstevel@tonic-gate * put left side either to output file 384*7c478bd9Sstevel@tonic-gate * if identical to right 385*7c478bd9Sstevel@tonic-gate * or left temp file if not 386*7c478bd9Sstevel@tonic-gate */ 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate if (change == ' ') 389*7c478bd9Sstevel@tonic-gate putline(odes, bp, strlen(bp)); 390*7c478bd9Sstevel@tonic-gate else 391*7c478bd9Sstevel@tonic-gate putline(left, bp, strlen(bp)); 392*7c478bd9Sstevel@tonic-gate } 393*7c478bd9Sstevel@tonic-gate if (change != ' ') 394*7c478bd9Sstevel@tonic-gate putmid(1); 395*7c478bd9Sstevel@tonic-gate num1++; 396*7c478bd9Sstevel@tonic-gate return (1); 397*7c478bd9Sstevel@tonic-gate } else 398*7c478bd9Sstevel@tonic-gate return (0); 399*7c478bd9Sstevel@tonic-gate } 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate static int 402*7c478bd9Sstevel@tonic-gate put2(void) 403*7c478bd9Sstevel@tonic-gate { 404*7c478bd9Sstevel@tonic-gate char *bp; 405*7c478bd9Sstevel@tonic-gate 406*7c478bd9Sstevel@tonic-gate if ((bp = fgetline(fdes2)) != NULL) { 407*7c478bd9Sstevel@tonic-gate (void) getlen((hlen + WGUTTER) % 8, bp); 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate /* 410*7c478bd9Sstevel@tonic-gate * if the left and right are different they are always 411*7c478bd9Sstevel@tonic-gate * printed. 412*7c478bd9Sstevel@tonic-gate * If the left and right are identical 413*7c478bd9Sstevel@tonic-gate * right is only printed if leftonly is not specified 414*7c478bd9Sstevel@tonic-gate * or silent mode is not specified 415*7c478bd9Sstevel@tonic-gate * or the right contains other than white space (len1 !=0) 416*7c478bd9Sstevel@tonic-gate */ 417*7c478bd9Sstevel@tonic-gate if (change != ' ') { 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate /* 420*7c478bd9Sstevel@tonic-gate * put right side to right temp file only 421*7c478bd9Sstevel@tonic-gate * because left side was written to output for 422*7c478bd9Sstevel@tonic-gate * identical lines 423*7c478bd9Sstevel@tonic-gate */ 424*7c478bd9Sstevel@tonic-gate 425*7c478bd9Sstevel@tonic-gate if (oflag) 426*7c478bd9Sstevel@tonic-gate putline(right, bp, strlen(bp)); 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate if (midflg == 0) 429*7c478bd9Sstevel@tonic-gate putmid(1); 430*7c478bd9Sstevel@tonic-gate putline(stdout, bp, nchars); 431*7c478bd9Sstevel@tonic-gate } else 432*7c478bd9Sstevel@tonic-gate if (!silent && !leftonly && len1 != 0) { 433*7c478bd9Sstevel@tonic-gate if (midflg == 0) 434*7c478bd9Sstevel@tonic-gate putmid(1); 435*7c478bd9Sstevel@tonic-gate putline(stdout, bp, nchars); 436*7c478bd9Sstevel@tonic-gate } 437*7c478bd9Sstevel@tonic-gate num2++; 438*7c478bd9Sstevel@tonic-gate len1 = 0; 439*7c478bd9Sstevel@tonic-gate return (1); 440*7c478bd9Sstevel@tonic-gate } else { 441*7c478bd9Sstevel@tonic-gate len1 = 0; 442*7c478bd9Sstevel@tonic-gate return (0); 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate } 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate static void 447*7c478bd9Sstevel@tonic-gate putline(FILE *file, char *start, int num) 448*7c478bd9Sstevel@tonic-gate { 449*7c478bd9Sstevel@tonic-gate char *cp, *end; 450*7c478bd9Sstevel@tonic-gate int i, len, d_col; 451*7c478bd9Sstevel@tonic-gate wchar_t wc; 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate cp = start; 454*7c478bd9Sstevel@tonic-gate end = cp + num; 455*7c478bd9Sstevel@tonic-gate while (cp < end) { 456*7c478bd9Sstevel@tonic-gate if (isascii(*cp)) { 457*7c478bd9Sstevel@tonic-gate (void) putc(*cp++, file); 458*7c478bd9Sstevel@tonic-gate continue; 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate if ((len = end - cp) > MB_LEN_MAX) 462*7c478bd9Sstevel@tonic-gate len = MB_LEN_MAX; 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, cp, len)) <= 0) { 465*7c478bd9Sstevel@tonic-gate (void) putc(*cp++, file); 466*7c478bd9Sstevel@tonic-gate continue; 467*7c478bd9Sstevel@tonic-gate } 468*7c478bd9Sstevel@tonic-gate 469*7c478bd9Sstevel@tonic-gate if ((d_col = wcwidth(wc)) <= 0) 470*7c478bd9Sstevel@tonic-gate d_col = len; 471*7c478bd9Sstevel@tonic-gate 472*7c478bd9Sstevel@tonic-gate if ((cp + d_col) > end) 473*7c478bd9Sstevel@tonic-gate return; 474*7c478bd9Sstevel@tonic-gate 475*7c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++) 476*7c478bd9Sstevel@tonic-gate (void) putc(*cp++, file); 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate } 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate static int 481*7c478bd9Sstevel@tonic-gate cmd(char *start) 482*7c478bd9Sstevel@tonic-gate { 483*7c478bd9Sstevel@tonic-gate unsigned char *cp; 484*7c478bd9Sstevel@tonic-gate char *cps; 485*7c478bd9Sstevel@tonic-gate int com; 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate if (*start == '>' || *start == '<' || *start == '-' || *start == '.') 488*7c478bd9Sstevel@tonic-gate return (0); 489*7c478bd9Sstevel@tonic-gate 490*7c478bd9Sstevel@tonic-gate cp = (unsigned char *)start; 491*7c478bd9Sstevel@tonic-gate cps = start; 492*7c478bd9Sstevel@tonic-gate while (isdigit(*cp)) 493*7c478bd9Sstevel@tonic-gate cp++; 494*7c478bd9Sstevel@tonic-gate from1 = atoi(cps); 495*7c478bd9Sstevel@tonic-gate to1 = from1; 496*7c478bd9Sstevel@tonic-gate if (*cp == ',') { 497*7c478bd9Sstevel@tonic-gate cp++; 498*7c478bd9Sstevel@tonic-gate cps = (char *)cp; 499*7c478bd9Sstevel@tonic-gate while (isdigit(*cp)) 500*7c478bd9Sstevel@tonic-gate cp++; 501*7c478bd9Sstevel@tonic-gate to1 = atoi(cps); 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate com = *cp++; 505*7c478bd9Sstevel@tonic-gate cps = (char *)cp; 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate while (isdigit(*cp)) 508*7c478bd9Sstevel@tonic-gate cp++; 509*7c478bd9Sstevel@tonic-gate from2 = atoi(cps); 510*7c478bd9Sstevel@tonic-gate to2 = from2; 511*7c478bd9Sstevel@tonic-gate if (*cp == ',') { 512*7c478bd9Sstevel@tonic-gate cp++; 513*7c478bd9Sstevel@tonic-gate cps = (char *)cp; 514*7c478bd9Sstevel@tonic-gate while (isdigit(*cp)) 515*7c478bd9Sstevel@tonic-gate cp++; 516*7c478bd9Sstevel@tonic-gate to2 = atoi(cps); 517*7c478bd9Sstevel@tonic-gate } 518*7c478bd9Sstevel@tonic-gate return (com); 519*7c478bd9Sstevel@tonic-gate } 520*7c478bd9Sstevel@tonic-gate 521*7c478bd9Sstevel@tonic-gate static int 522*7c478bd9Sstevel@tonic-gate getlen(int startpos, char *buffer) 523*7c478bd9Sstevel@tonic-gate { 524*7c478bd9Sstevel@tonic-gate /* 525*7c478bd9Sstevel@tonic-gate * get the length of the string in buffer 526*7c478bd9Sstevel@tonic-gate * expand tabs to next multiple of 8 527*7c478bd9Sstevel@tonic-gate */ 528*7c478bd9Sstevel@tonic-gate unsigned char *cp; 529*7c478bd9Sstevel@tonic-gate int slen, tlen, len, d_col; 530*7c478bd9Sstevel@tonic-gate int notspace; 531*7c478bd9Sstevel@tonic-gate wchar_t wc; 532*7c478bd9Sstevel@tonic-gate 533*7c478bd9Sstevel@tonic-gate nchars = 0; 534*7c478bd9Sstevel@tonic-gate notspace = 0; 535*7c478bd9Sstevel@tonic-gate tlen = startpos; 536*7c478bd9Sstevel@tonic-gate for (cp = (unsigned char *)buffer; (*cp != '\n') && (*cp); cp++) { 537*7c478bd9Sstevel@tonic-gate if (*cp == '\t') { 538*7c478bd9Sstevel@tonic-gate slen = tlen; 539*7c478bd9Sstevel@tonic-gate tlen += 8 - (tlen % 8); 540*7c478bd9Sstevel@tonic-gate if (tlen >= hlen) { 541*7c478bd9Sstevel@tonic-gate tlen = slen; 542*7c478bd9Sstevel@tonic-gate break; 543*7c478bd9Sstevel@tonic-gate } 544*7c478bd9Sstevel@tonic-gate nchars++; 545*7c478bd9Sstevel@tonic-gate continue; 546*7c478bd9Sstevel@tonic-gate } 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate if (isascii(*cp)) { 549*7c478bd9Sstevel@tonic-gate slen = tlen; 550*7c478bd9Sstevel@tonic-gate tlen++; 551*7c478bd9Sstevel@tonic-gate if (tlen >= hlen) { 552*7c478bd9Sstevel@tonic-gate tlen = slen; 553*7c478bd9Sstevel@tonic-gate break; 554*7c478bd9Sstevel@tonic-gate } 555*7c478bd9Sstevel@tonic-gate if (!isspace(*cp)) 556*7c478bd9Sstevel@tonic-gate notspace = 1; 557*7c478bd9Sstevel@tonic-gate nchars++; 558*7c478bd9Sstevel@tonic-gate continue; 559*7c478bd9Sstevel@tonic-gate } 560*7c478bd9Sstevel@tonic-gate 561*7c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)cp, MB_LEN_MAX)) <= 0) { 562*7c478bd9Sstevel@tonic-gate slen = tlen; 563*7c478bd9Sstevel@tonic-gate tlen++; 564*7c478bd9Sstevel@tonic-gate if (tlen >= hlen) { 565*7c478bd9Sstevel@tonic-gate tlen = slen; 566*7c478bd9Sstevel@tonic-gate break; 567*7c478bd9Sstevel@tonic-gate } 568*7c478bd9Sstevel@tonic-gate notspace = 1; 569*7c478bd9Sstevel@tonic-gate nchars++; 570*7c478bd9Sstevel@tonic-gate continue; 571*7c478bd9Sstevel@tonic-gate } 572*7c478bd9Sstevel@tonic-gate 573*7c478bd9Sstevel@tonic-gate if ((d_col = wcwidth(wc)) <= 0) 574*7c478bd9Sstevel@tonic-gate d_col = len; 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate slen = tlen; 577*7c478bd9Sstevel@tonic-gate tlen += d_col; 578*7c478bd9Sstevel@tonic-gate if (tlen > hlen) { 579*7c478bd9Sstevel@tonic-gate tlen = slen; 580*7c478bd9Sstevel@tonic-gate break; 581*7c478bd9Sstevel@tonic-gate } 582*7c478bd9Sstevel@tonic-gate notspace = 1; 583*7c478bd9Sstevel@tonic-gate cp += len - 1; 584*7c478bd9Sstevel@tonic-gate nchars += len; 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate return (notspace ? tlen : 0); 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate 589*7c478bd9Sstevel@tonic-gate static void 590*7c478bd9Sstevel@tonic-gate putmid(int bflag) 591*7c478bd9Sstevel@tonic-gate { 592*7c478bd9Sstevel@tonic-gate int i; 593*7c478bd9Sstevel@tonic-gate 594*7c478bd9Sstevel@tonic-gate /* 595*7c478bd9Sstevel@tonic-gate * len1 set by getlen to the possibly truncated 596*7c478bd9Sstevel@tonic-gate * length of left side 597*7c478bd9Sstevel@tonic-gate * hlen is length of half line 598*7c478bd9Sstevel@tonic-gate */ 599*7c478bd9Sstevel@tonic-gate 600*7c478bd9Sstevel@tonic-gate midflg = 1; 601*7c478bd9Sstevel@tonic-gate if (bflag) { 602*7c478bd9Sstevel@tonic-gate for (i = 0; i < hlen - len1; i++) 603*7c478bd9Sstevel@tonic-gate (void) putc(' ', stdout); 604*7c478bd9Sstevel@tonic-gate } 605*7c478bd9Sstevel@tonic-gate (void) fputs(twoblanks, stdout); 606*7c478bd9Sstevel@tonic-gate (void) putc((int)change, stdout); 607*7c478bd9Sstevel@tonic-gate (void) fputs(twoblanks, stdout); 608*7c478bd9Sstevel@tonic-gate } 609*7c478bd9Sstevel@tonic-gate 610*7c478bd9Sstevel@tonic-gate static void 611*7c478bd9Sstevel@tonic-gate error(char *s1, char *s2) 612*7c478bd9Sstevel@tonic-gate { 613*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "sdiff: "); 614*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, s1, s2); 615*7c478bd9Sstevel@tonic-gate (void) putc('\n', stderr); 616*7c478bd9Sstevel@tonic-gate sremove(); 617*7c478bd9Sstevel@tonic-gate exit(2); 618*7c478bd9Sstevel@tonic-gate } 619*7c478bd9Sstevel@tonic-gate 620*7c478bd9Sstevel@tonic-gate static void 621*7c478bd9Sstevel@tonic-gate onintr(void) 622*7c478bd9Sstevel@tonic-gate { 623*7c478bd9Sstevel@tonic-gate sremove(); 624*7c478bd9Sstevel@tonic-gate exit(rcode); 625*7c478bd9Sstevel@tonic-gate } 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate static void 628*7c478bd9Sstevel@tonic-gate sremove(void) 629*7c478bd9Sstevel@tonic-gate { 630*7c478bd9Sstevel@tonic-gate if (ltemp) { 631*7c478bd9Sstevel@tonic-gate (void) unlink(ltemp); 632*7c478bd9Sstevel@tonic-gate free(ltemp); 633*7c478bd9Sstevel@tonic-gate } 634*7c478bd9Sstevel@tonic-gate if (rtemp) { 635*7c478bd9Sstevel@tonic-gate (void) unlink(rtemp); 636*7c478bd9Sstevel@tonic-gate free(rtemp); 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate if (temp) { 639*7c478bd9Sstevel@tonic-gate (void) unlink(temp); 640*7c478bd9Sstevel@tonic-gate free(temp); 641*7c478bd9Sstevel@tonic-gate } 642*7c478bd9Sstevel@tonic-gate } 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate static void 645*7c478bd9Sstevel@tonic-gate cmdin(void) 646*7c478bd9Sstevel@tonic-gate { 647*7c478bd9Sstevel@tonic-gate char *cp, *ename; 648*7c478bd9Sstevel@tonic-gate int notacc; 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate (void) fclose(left); 651*7c478bd9Sstevel@tonic-gate (void) fclose(right); 652*7c478bd9Sstevel@tonic-gate notacc = 1; 653*7c478bd9Sstevel@tonic-gate while (notacc) { 654*7c478bd9Sstevel@tonic-gate (void) putc(PROMPT, stdout); 655*7c478bd9Sstevel@tonic-gate if ((cp = fgets(inbuf, 10, stdin)) == NULL) { 656*7c478bd9Sstevel@tonic-gate (void) putc('\n', stdout); 657*7c478bd9Sstevel@tonic-gate break; 658*7c478bd9Sstevel@tonic-gate } 659*7c478bd9Sstevel@tonic-gate switch (*cp) { 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate case 's': 662*7c478bd9Sstevel@tonic-gate silent = 1; 663*7c478bd9Sstevel@tonic-gate break; 664*7c478bd9Sstevel@tonic-gate 665*7c478bd9Sstevel@tonic-gate case 'v': 666*7c478bd9Sstevel@tonic-gate silent = 0; 667*7c478bd9Sstevel@tonic-gate break; 668*7c478bd9Sstevel@tonic-gate 669*7c478bd9Sstevel@tonic-gate case 'q': 670*7c478bd9Sstevel@tonic-gate sremove(); 671*7c478bd9Sstevel@tonic-gate exit(rcode); 672*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 673*7c478bd9Sstevel@tonic-gate break; 674*7c478bd9Sstevel@tonic-gate 675*7c478bd9Sstevel@tonic-gate case 'l': 676*7c478bd9Sstevel@tonic-gate cpp(ltemp, left, odes); 677*7c478bd9Sstevel@tonic-gate notacc = 0; 678*7c478bd9Sstevel@tonic-gate break; 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate case 'r': 681*7c478bd9Sstevel@tonic-gate cpp(rtemp, right, odes); 682*7c478bd9Sstevel@tonic-gate notacc = 0; 683*7c478bd9Sstevel@tonic-gate break; 684*7c478bd9Sstevel@tonic-gate 685*7c478bd9Sstevel@tonic-gate case 'e': 686*7c478bd9Sstevel@tonic-gate while (*++cp == ' ') 687*7c478bd9Sstevel@tonic-gate ; 688*7c478bd9Sstevel@tonic-gate switch (*cp) { 689*7c478bd9Sstevel@tonic-gate case 'l': 690*7c478bd9Sstevel@tonic-gate case '<': 691*7c478bd9Sstevel@tonic-gate notacc = 0; 692*7c478bd9Sstevel@tonic-gate ename = ltemp; 693*7c478bd9Sstevel@tonic-gate edit(ename); 694*7c478bd9Sstevel@tonic-gate break; 695*7c478bd9Sstevel@tonic-gate 696*7c478bd9Sstevel@tonic-gate case 'r': 697*7c478bd9Sstevel@tonic-gate case '>': 698*7c478bd9Sstevel@tonic-gate notacc = 0; 699*7c478bd9Sstevel@tonic-gate ename = rtemp; 700*7c478bd9Sstevel@tonic-gate edit(ename); 701*7c478bd9Sstevel@tonic-gate break; 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate case 'b': 704*7c478bd9Sstevel@tonic-gate case '|': 705*7c478bd9Sstevel@tonic-gate if ((tempdes = fopen(temp, "w")) == NULL) 706*7c478bd9Sstevel@tonic-gate error(gettext( 707*7c478bd9Sstevel@tonic-gate "Cannot open temp file %s"), 708*7c478bd9Sstevel@tonic-gate temp); 709*7c478bd9Sstevel@tonic-gate cpp(ltemp, left, tempdes); 710*7c478bd9Sstevel@tonic-gate cpp(rtemp, right, tempdes); 711*7c478bd9Sstevel@tonic-gate (void) fclose(tempdes); 712*7c478bd9Sstevel@tonic-gate notacc = 0; 713*7c478bd9Sstevel@tonic-gate ename = temp; 714*7c478bd9Sstevel@tonic-gate edit(ename); 715*7c478bd9Sstevel@tonic-gate break; 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate case '\n': 718*7c478bd9Sstevel@tonic-gate if ((tempdes = fopen(temp, "w")) == NULL) 719*7c478bd9Sstevel@tonic-gate error(gettext( 720*7c478bd9Sstevel@tonic-gate "Cannot open temp file %s"), 721*7c478bd9Sstevel@tonic-gate temp); 722*7c478bd9Sstevel@tonic-gate (void) fclose(tempdes); 723*7c478bd9Sstevel@tonic-gate notacc = 0; 724*7c478bd9Sstevel@tonic-gate ename = temp; 725*7c478bd9Sstevel@tonic-gate edit(ename); 726*7c478bd9Sstevel@tonic-gate break; 727*7c478bd9Sstevel@tonic-gate default: 728*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 729*7c478bd9Sstevel@tonic-gate "Illegal command %s reenter\n"), 730*7c478bd9Sstevel@tonic-gate cp); 731*7c478bd9Sstevel@tonic-gate break; 732*7c478bd9Sstevel@tonic-gate } 733*7c478bd9Sstevel@tonic-gate if (notacc == 0) 734*7c478bd9Sstevel@tonic-gate cpp(ename, tempdes, odes); 735*7c478bd9Sstevel@tonic-gate break; 736*7c478bd9Sstevel@tonic-gate 737*7c478bd9Sstevel@tonic-gate default: 738*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 739*7c478bd9Sstevel@tonic-gate "Illegal command reenter\n")); 740*7c478bd9Sstevel@tonic-gate break; 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate } 743*7c478bd9Sstevel@tonic-gate } 744*7c478bd9Sstevel@tonic-gate 745*7c478bd9Sstevel@tonic-gate static void 746*7c478bd9Sstevel@tonic-gate cpp(char *from, FILE *fromdes, FILE *todes) 747*7c478bd9Sstevel@tonic-gate { 748*7c478bd9Sstevel@tonic-gate char tempbuf[BMAX + 1]; 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate if ((fromdes = fopen(from, "r")) == NULL) 751*7c478bd9Sstevel@tonic-gate error(gettext( 752*7c478bd9Sstevel@tonic-gate "cpp: Cannot open %s"), from); 753*7c478bd9Sstevel@tonic-gate while ((fgets(tempbuf, BMAX, fromdes) != NULL)) 754*7c478bd9Sstevel@tonic-gate (void) fputs(tempbuf, todes); 755*7c478bd9Sstevel@tonic-gate (void) fclose(fromdes); 756*7c478bd9Sstevel@tonic-gate } 757*7c478bd9Sstevel@tonic-gate 758*7c478bd9Sstevel@tonic-gate static void 759*7c478bd9Sstevel@tonic-gate edit(char *file) 760*7c478bd9Sstevel@tonic-gate { 761*7c478bd9Sstevel@tonic-gate int i; 762*7c478bd9Sstevel@tonic-gate pid_t pid; 763*7c478bd9Sstevel@tonic-gate void (*oldintr)(int); 764*7c478bd9Sstevel@tonic-gate 765*7c478bd9Sstevel@tonic-gate switch (pid = fork()) { 766*7c478bd9Sstevel@tonic-gate case (pid_t)-1: 767*7c478bd9Sstevel@tonic-gate error(gettext("Cannot fork"), NULL); 768*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 769*7c478bd9Sstevel@tonic-gate break; 770*7c478bd9Sstevel@tonic-gate case (pid_t)0: 771*7c478bd9Sstevel@tonic-gate (void) execl("/usr/bin/ed", "ed", file, NULL); 772*7c478bd9Sstevel@tonic-gate } 773*7c478bd9Sstevel@tonic-gate 774*7c478bd9Sstevel@tonic-gate oldintr = signal(SIGINT, SIG_IGN); /* ignore interrupts in ed */ 775*7c478bd9Sstevel@tonic-gate while (pid != wait(&i)) 776*7c478bd9Sstevel@tonic-gate ; 777*7c478bd9Sstevel@tonic-gate /* restore previous interrupt proc */ 778*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, oldintr); 779*7c478bd9Sstevel@tonic-gate } 780*7c478bd9Sstevel@tonic-gate 781*7c478bd9Sstevel@tonic-gate static char * 782*7c478bd9Sstevel@tonic-gate filename(char *pa1, char *pa2) 783*7c478bd9Sstevel@tonic-gate { 784*7c478bd9Sstevel@tonic-gate int c; 785*7c478bd9Sstevel@tonic-gate char *a1, *b1, *a2; 786*7c478bd9Sstevel@tonic-gate struct stat stbuf; 787*7c478bd9Sstevel@tonic-gate a1 = pa1; 788*7c478bd9Sstevel@tonic-gate a2 = pa2; 789*7c478bd9Sstevel@tonic-gate if (stat(a1, &stbuf) != -1 && ((stbuf.st_mode&S_IFMT) == S_IFDIR)) { 790*7c478bd9Sstevel@tonic-gate b1 = pa1 = (char *)malloc(strlen(a1) + strlen(a2) + 2); 791*7c478bd9Sstevel@tonic-gate while (*b1++ = *a1++); 792*7c478bd9Sstevel@tonic-gate b1[-1] = '/'; 793*7c478bd9Sstevel@tonic-gate a1 = b1; 794*7c478bd9Sstevel@tonic-gate while (*a1++ = *a2++) 795*7c478bd9Sstevel@tonic-gate if (*a2 && *a2 != '/' && a2[-1] == '/') 796*7c478bd9Sstevel@tonic-gate a1 = b1; 797*7c478bd9Sstevel@tonic-gate } else if (a1[0] == '-' && a1[1] == 0 && temp == 0) { 798*7c478bd9Sstevel@tonic-gate if (fstat(fileno(stdin), &stbuf) == -1) 799*7c478bd9Sstevel@tonic-gate error(gettext("Cannot process stdin"), NULL); 800*7c478bd9Sstevel@tonic-gate pa1 = temp = strdup("/tmp/sdiffXXXXXX"); 801*7c478bd9Sstevel@tonic-gate if ((tempfd = mkstemp(temp)) == -1 || 802*7c478bd9Sstevel@tonic-gate (tempdes = fdopen(tempfd, "w")) == NULL) 803*7c478bd9Sstevel@tonic-gate error(gettext("Cannot open/create temp %s"), 804*7c478bd9Sstevel@tonic-gate temp); 805*7c478bd9Sstevel@tonic-gate while ((c = getc(stdin)) != EOF) 806*7c478bd9Sstevel@tonic-gate (void) putc(c, tempdes); 807*7c478bd9Sstevel@tonic-gate (void) fclose(tempdes); 808*7c478bd9Sstevel@tonic-gate } 809*7c478bd9Sstevel@tonic-gate return (pa1); 810*7c478bd9Sstevel@tonic-gate } 811*7c478bd9Sstevel@tonic-gate 812*7c478bd9Sstevel@tonic-gate /* 813*7c478bd9Sstevel@tonic-gate * like fgets, but reads upto and including a newline, 814*7c478bd9Sstevel@tonic-gate * the data is stored in a reusable dynamic buffer that grows to fit 815*7c478bd9Sstevel@tonic-gate * the largest line in the file, the buffer is NULL terminated 816*7c478bd9Sstevel@tonic-gate * returns a pointer to the dynamic buffer. 817*7c478bd9Sstevel@tonic-gate */ 818*7c478bd9Sstevel@tonic-gate static char * 819*7c478bd9Sstevel@tonic-gate fgetline(FILE *fp) 820*7c478bd9Sstevel@tonic-gate { 821*7c478bd9Sstevel@tonic-gate static char *bp = NULL; 822*7c478bd9Sstevel@tonic-gate static int blen = 0; 823*7c478bd9Sstevel@tonic-gate int sl; 824*7c478bd9Sstevel@tonic-gate 825*7c478bd9Sstevel@tonic-gate if (bp == NULL) { 826*7c478bd9Sstevel@tonic-gate /* allocate it for the first time */ 827*7c478bd9Sstevel@tonic-gate bp = (char *)malloc(BUFSIZ); 828*7c478bd9Sstevel@tonic-gate if (bp == NULL) 829*7c478bd9Sstevel@tonic-gate error(gettext("fgetline: malloc failed"), NULL); 830*7c478bd9Sstevel@tonic-gate blen = BUFSIZ; 831*7c478bd9Sstevel@tonic-gate } 832*7c478bd9Sstevel@tonic-gate 833*7c478bd9Sstevel@tonic-gate /* check for error or nothing read */ 834*7c478bd9Sstevel@tonic-gate if (fgets(bp, blen, fp) == NULL) 835*7c478bd9Sstevel@tonic-gate return (NULL); 836*7c478bd9Sstevel@tonic-gate 837*7c478bd9Sstevel@tonic-gate if (feof(fp)) 838*7c478bd9Sstevel@tonic-gate return (bp); 839*7c478bd9Sstevel@tonic-gate 840*7c478bd9Sstevel@tonic-gate while ((sl = strlen(bp)) == blen-1 && *(bp+blen-2) != '\n') { 841*7c478bd9Sstevel@tonic-gate /* still more data, grow the buffer */ 842*7c478bd9Sstevel@tonic-gate blen *= 2; 843*7c478bd9Sstevel@tonic-gate bp = (char *)realloc(bp, blen); 844*7c478bd9Sstevel@tonic-gate if (bp == NULL) 845*7c478bd9Sstevel@tonic-gate error(gettext("fgetline: realloc failed"), NULL); 846*7c478bd9Sstevel@tonic-gate /* continue reading and add to end of buffer */ 847*7c478bd9Sstevel@tonic-gate (void) fgets(bp+sl, blen-sl, fp); 848*7c478bd9Sstevel@tonic-gate } 849*7c478bd9Sstevel@tonic-gate return (bp); 850*7c478bd9Sstevel@tonic-gate } 851