[BACK]Return to util.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / patch

Annotation of src/usr.bin/patch/util.c, Revision 1.1.1.1

1.1       deraadt     1: #ifndef lint
                      2: static char rcsid[] = "$Id: util.c,v 1.3 1993/12/07 10:36:16 mycroft Exp $";
                      3: #endif /* not lint */
                      4:
                      5: #include "EXTERN.h"
                      6: #include "common.h"
                      7: #include "INTERN.h"
                      8: #include "util.h"
                      9: #include "backupfile.h"
                     10:
                     11: void my_exit();
                     12:
                     13: /* Rename a file, copying it if necessary. */
                     14:
                     15: int
                     16: move_file(from,to)
                     17: char *from, *to;
                     18: {
                     19:     char bakname[512];
                     20:     Reg1 char *s;
                     21:     Reg2 int i;
                     22:     Reg3 int fromfd;
                     23:
                     24:     /* to stdout? */
                     25:
                     26:     if (strEQ(to, "-")) {
                     27: #ifdef DEBUGGING
                     28:        if (debug & 4)
                     29:            say2("Moving %s to stdout.\n", from);
                     30: #endif
                     31:        fromfd = open(from, 0);
                     32:        if (fromfd < 0)
                     33:            pfatal2("internal error, can't reopen %s", from);
                     34:        while ((i=read(fromfd, buf, sizeof buf)) > 0)
                     35:            if (write(1, buf, i) != 1)
                     36:                pfatal1("write failed");
                     37:        Close(fromfd);
                     38:        return 0;
                     39:     }
                     40:
                     41:     if (origprae) {
                     42:        Strcpy(bakname, origprae);
                     43:        Strcat(bakname, to);
                     44:     } else {
                     45: #ifndef NODIR
                     46:        char *backupname = find_backup_file_name(to);
                     47:        if (backupname == (char *) 0)
                     48:            fatal1("out of memory\n");
                     49:        Strcpy(bakname, backupname);
                     50:        free(backupname);
                     51: #else /* NODIR */
                     52:        Strcpy(bakname, to);
                     53:        Strcat(bakname, simple_backup_suffix);
                     54: #endif /* NODIR */
                     55:     }
                     56:
                     57:     if (stat(to, &filestat) == 0) {    /* output file exists */
                     58:        dev_t to_device = filestat.st_dev;
                     59:        ino_t to_inode  = filestat.st_ino;
                     60:        char *simplename = bakname;
                     61:
                     62:        for (s=bakname; *s; s++) {
                     63:            if (*s == '/')
                     64:                simplename = s+1;
                     65:        }
                     66:        /* Find a backup name that is not the same file.
                     67:           Change the first lowercase char into uppercase;
                     68:           if that isn't sufficient, chop off the first char and try again.  */
                     69:        while (stat(bakname, &filestat) == 0 &&
                     70:                to_device == filestat.st_dev && to_inode == filestat.st_ino) {
                     71:            /* Skip initial non-lowercase chars.  */
                     72:            for (s=simplename; *s && !islower(*s); s++) ;
                     73:            if (*s)
                     74:                *s = toupper(*s);
                     75:            else
                     76:                Strcpy(simplename, simplename+1);
                     77:        }
                     78:        while (unlink(bakname) >= 0) ;  /* while() is for benefit of Eunice */
                     79: #ifdef DEBUGGING
                     80:        if (debug & 4)
                     81:            say3("Moving %s to %s.\n", to, bakname);
                     82: #endif
                     83:        if (link(to, bakname) < 0) {
                     84:            /* Maybe `to' is a symlink into a different file system.
                     85:               Copying replaces the symlink with a file; using rename
                     86:               would be better.  */
                     87:            Reg4 int tofd;
                     88:            Reg5 int bakfd;
                     89:
                     90:            bakfd = creat(bakname, 0666);
                     91:            if (bakfd < 0) {
                     92:                say4("Can't backup %s, output is in %s: %s\n", to, from,
                     93:                     strerror(errno));
                     94:                return -1;
                     95:            }
                     96:            tofd = open(to, 0);
                     97:            if (tofd < 0)
                     98:                pfatal2("internal error, can't open %s", to);
                     99:            while ((i=read(tofd, buf, sizeof buf)) > 0)
                    100:                if (write(bakfd, buf, i) != i)
                    101:                    pfatal1("write failed");
                    102:            Close(tofd);
                    103:            Close(bakfd);
                    104:        }
                    105:        while (unlink(to) >= 0) ;
                    106:     }
                    107: #ifdef DEBUGGING
                    108:     if (debug & 4)
                    109:        say3("Moving %s to %s.\n", from, to);
                    110: #endif
                    111:     if (link(from, to) < 0) {          /* different file system? */
                    112:        Reg4 int tofd;
                    113:
                    114:        tofd = creat(to, 0666);
                    115:        if (tofd < 0) {
                    116:            say4("Can't create %s, output is in %s: %s\n",
                    117:              to, from, strerror(errno));
                    118:            return -1;
                    119:        }
                    120:        fromfd = open(from, 0);
                    121:        if (fromfd < 0)
                    122:            pfatal2("internal error, can't reopen %s", from);
                    123:        while ((i=read(fromfd, buf, sizeof buf)) > 0)
                    124:            if (write(tofd, buf, i) != i)
                    125:                pfatal1("write failed");
                    126:        Close(fromfd);
                    127:        Close(tofd);
                    128:     }
                    129:     Unlink(from);
                    130:     return 0;
                    131: }
                    132:
                    133: /* Copy a file. */
                    134:
                    135: void
                    136: copy_file(from,to)
                    137: char *from, *to;
                    138: {
                    139:     Reg3 int tofd;
                    140:     Reg2 int fromfd;
                    141:     Reg1 int i;
                    142:
                    143:     tofd = creat(to, 0666);
                    144:     if (tofd < 0)
                    145:        pfatal2("can't create %s", to);
                    146:     fromfd = open(from, 0);
                    147:     if (fromfd < 0)
                    148:        pfatal2("internal error, can't reopen %s", from);
                    149:     while ((i=read(fromfd, buf, sizeof buf)) > 0)
                    150:        if (write(tofd, buf, i) != i)
                    151:            pfatal2("write to %s failed", to);
                    152:     Close(fromfd);
                    153:     Close(tofd);
                    154: }
                    155:
                    156: /* Allocate a unique area for a string. */
                    157:
                    158: char *
                    159: savestr(s)
                    160: Reg1 char *s;
                    161: {
                    162:     Reg3 char *rv;
                    163:     Reg2 char *t;
                    164:
                    165:     if (!s)
                    166:        s = "Oops";
                    167:     t = s;
                    168:     while (*t++);
                    169:     rv = malloc((MEM) (t - s));
                    170:     if (rv == Nullch) {
                    171:        if (using_plan_a)
                    172:            out_of_mem = TRUE;
                    173:        else
                    174:            fatal1("out of memory\n");
                    175:     }
                    176:     else {
                    177:        t = rv;
                    178:        while (*t++ = *s++);
                    179:     }
                    180:     return rv;
                    181: }
                    182:
                    183: #if defined(lint) && defined(CANVARARG)
                    184:
                    185: /*VARARGS ARGSUSED*/
                    186: say(pat) char *pat; { ; }
                    187: /*VARARGS ARGSUSED*/
                    188: fatal(pat) char *pat; { ; }
                    189: /*VARARGS ARGSUSED*/
                    190: pfatal(pat) char *pat; { ; }
                    191: /*VARARGS ARGSUSED*/
                    192: ask(pat) char *pat; { ; }
                    193:
                    194: #else
                    195:
                    196: /* Vanilla terminal output (buffered). */
                    197:
                    198: void
                    199: say(pat,arg1,arg2,arg3)
                    200: char *pat;
                    201: long arg1,arg2,arg3;
                    202: {
                    203:     fprintf(stderr, pat, arg1, arg2, arg3);
                    204:     Fflush(stderr);
                    205: }
                    206:
                    207: /* Terminal output, pun intended. */
                    208:
                    209: void                           /* very void */
                    210: fatal(pat,arg1,arg2,arg3)
                    211: char *pat;
                    212: long arg1,arg2,arg3;
                    213: {
                    214:     fprintf(stderr, "patch: **** ");
                    215:     fprintf(stderr, pat, arg1, arg2, arg3);
                    216:     my_exit(1);
                    217: }
                    218:
                    219: /* Say something from patch, something from the system, then silence . . . */
                    220:
                    221: void                           /* very void */
                    222: pfatal(pat,arg1,arg2,arg3)
                    223: char *pat;
                    224: long arg1,arg2,arg3;
                    225: {
                    226:     int errnum = errno;
                    227:
                    228:     fprintf(stderr, "patch: **** ");
                    229:     fprintf(stderr, pat, arg1, arg2, arg3);
                    230:     fprintf(stderr, ": %s\n", strerror(errnum));
                    231:     my_exit(1);
                    232: }
                    233:
                    234: /* Get a response from the user, somehow or other. */
                    235:
                    236: void
                    237: ask(pat,arg1,arg2,arg3)
                    238: char *pat;
                    239: long arg1,arg2,arg3;
                    240: {
                    241:     int ttyfd;
                    242:     int r;
                    243:     bool tty2 = isatty(2);
                    244:
                    245:     Sprintf(buf, pat, arg1, arg2, arg3);
                    246:     Fflush(stderr);
                    247:     write(2, buf, strlen(buf));
                    248:     if (tty2) {                                /* might be redirected to a file */
                    249:        r = read(2, buf, sizeof buf);
                    250:     }
                    251:     else if (isatty(1)) {              /* this may be new file output */
                    252:        Fflush(stdout);
                    253:        write(1, buf, strlen(buf));
                    254:        r = read(1, buf, sizeof buf);
                    255:     }
                    256:     else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {
                    257:                                        /* might be deleted or unwriteable */
                    258:        write(ttyfd, buf, strlen(buf));
                    259:        r = read(ttyfd, buf, sizeof buf);
                    260:        Close(ttyfd);
                    261:     }
                    262:     else if (isatty(0)) {              /* this is probably patch input */
                    263:        Fflush(stdin);
                    264:        write(0, buf, strlen(buf));
                    265:        r = read(0, buf, sizeof buf);
                    266:     }
                    267:     else {                             /* no terminal at all--default it */
                    268:        buf[0] = '\n';
                    269:        r = 1;
                    270:     }
                    271:     if (r <= 0)
                    272:        buf[0] = 0;
                    273:     else
                    274:        buf[r] = '\0';
                    275:     if (!tty2)
                    276:        say1(buf);
                    277: }
                    278: #endif /* lint */
                    279:
                    280: /* How to handle certain events when not in a critical region. */
                    281:
                    282: void
                    283: set_signals(reset)
                    284: int reset;
                    285: {
                    286: #ifndef lint
                    287: #ifdef VOIDSIG
                    288:     static void (*hupval)(),(*intval)();
                    289: #else
                    290:     static int (*hupval)(),(*intval)();
                    291: #endif
                    292:
                    293:     if (!reset) {
                    294:        hupval = signal(SIGHUP, SIG_IGN);
                    295:        if (hupval != SIG_IGN)
                    296: #ifdef VOIDSIG
                    297:            hupval = my_exit;
                    298: #else
                    299:            hupval = (int(*)())my_exit;
                    300: #endif
                    301:        intval = signal(SIGINT, SIG_IGN);
                    302:        if (intval != SIG_IGN)
                    303: #ifdef VOIDSIG
                    304:            intval = my_exit;
                    305: #else
                    306:            intval = (int(*)())my_exit;
                    307: #endif
                    308:     }
                    309:     Signal(SIGHUP, hupval);
                    310:     Signal(SIGINT, intval);
                    311: #endif
                    312: }
                    313:
                    314: /* How to handle certain events when in a critical region. */
                    315:
                    316: void
                    317: ignore_signals()
                    318: {
                    319: #ifndef lint
                    320:     Signal(SIGHUP, SIG_IGN);
                    321:     Signal(SIGINT, SIG_IGN);
                    322: #endif
                    323: }
                    324:
                    325: /* Make sure we'll have the directories to create a file.
                    326:    If `striplast' is TRUE, ignore the last element of `filename'.  */
                    327:
                    328: void
                    329: makedirs(filename,striplast)
                    330: Reg1 char *filename;
                    331: bool striplast;
                    332: {
                    333:     char tmpbuf[256];
                    334:     Reg2 char *s = tmpbuf;
                    335:     char *dirv[20];            /* Point to the NULs between elements.  */
                    336:     Reg3 int i;
                    337:     Reg4 int dirvp = 0;                /* Number of finished entries in dirv. */
                    338:
                    339:     /* Copy `filename' into `tmpbuf' with a NUL instead of a slash
                    340:        between the directories.  */
                    341:     while (*filename) {
                    342:        if (*filename == '/') {
                    343:            filename++;
                    344:            dirv[dirvp++] = s;
                    345:            *s++ = '\0';
                    346:        }
                    347:        else {
                    348:            *s++ = *filename++;
                    349:        }
                    350:     }
                    351:     *s = '\0';
                    352:     dirv[dirvp] = s;
                    353:     if (striplast)
                    354:        dirvp--;
                    355:     if (dirvp < 0)
                    356:        return;
                    357:
                    358:     strcpy(buf, "mkdir");
                    359:     s = buf;
                    360:     for (i=0; i<=dirvp; i++) {
                    361:        struct stat sbuf;
                    362:
                    363:        if (stat(tmpbuf, &sbuf) && errno == ENOENT) {
                    364:            while (*s) s++;
                    365:            *s++ = ' ';
                    366:            strcpy(s, tmpbuf);
                    367:        }
                    368:        *dirv[i] = '/';
                    369:     }
                    370:     if (s != buf)
                    371:        system(buf);
                    372: }
                    373:
                    374: /* Make filenames more reasonable. */
                    375:
                    376: char *
                    377: fetchname(at,strip_leading,assume_exists)
                    378: char *at;
                    379: int strip_leading;
                    380: int assume_exists;
                    381: {
                    382:     char *fullname;
                    383:     char *name;
                    384:     Reg1 char *t;
                    385:     char tmpbuf[200];
                    386:     int sleading = strip_leading;
                    387:
                    388:     if (!at)
                    389:        return Nullch;
                    390:     while (isspace(*at))
                    391:        at++;
                    392: #ifdef DEBUGGING
                    393:     if (debug & 128)
                    394:        say4("fetchname %s %d %d\n",at,strip_leading,assume_exists);
                    395: #endif
                    396:     if (strnEQ(at, "/dev/null", 9))    /* so files can be created by diffing */
                    397:        return Nullch;                  /*   against /dev/null. */
                    398:     name = fullname = t = savestr(at);
                    399:
                    400:     /* Strip off up to `sleading' leading slashes and null terminate.  */
                    401:     for (; *t && !isspace(*t); t++)
                    402:        if (*t == '/')
                    403:            if (--sleading >= 0)
                    404:                name = t+1;
                    405:     *t = '\0';
                    406:
                    407:     /* If no -p option was given (957 is the default value!),
                    408:        we were given a relative pathname,
                    409:        and the leading directories that we just stripped off all exist,
                    410:        put them back on.  */
                    411:     if (strip_leading == 957 && name != fullname && *fullname != '/') {
                    412:        name[-1] = '\0';
                    413:        if (stat(fullname, &filestat) == 0 && S_ISDIR (filestat.st_mode)) {
                    414:            name[-1] = '/';
                    415:            name=fullname;
                    416:        }
                    417:     }
                    418:
                    419:     name = savestr(name);
                    420:     free(fullname);
                    421:
                    422:     if (stat(name, &filestat) && !assume_exists) {
                    423:        char *filebase = basename(name);
                    424:        int pathlen = filebase - name;
                    425:
                    426:        /* Put any leading path into `tmpbuf'.  */
                    427:        strncpy(tmpbuf, name, pathlen);
                    428:
                    429: #define try(f, a1, a2) (Sprintf(tmpbuf + pathlen, f, a1, a2), stat(tmpbuf, &filestat) == 0)
                    430:        if (   try("RCS/%s%s", filebase, RCSSUFFIX)
                    431:            || try("RCS/%s"  , filebase,         0)
                    432:            || try(    "%s%s", filebase, RCSSUFFIX)
                    433:            || try("SCCS/%s%s", SCCSPREFIX, filebase)
                    434:            || try(     "%s%s", SCCSPREFIX, filebase))
                    435:          return name;
                    436:        free(name);
                    437:        name = Nullch;
                    438:     }
                    439:
                    440:     return name;
                    441: }