[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     ! 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: }