[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.13

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