[BACK]Return to cmd-string.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/cmd-string.c, Revision 1.1

1.1     ! nicm        1: /* $OpenBSD$ */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            14:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
        !            15:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
        !            16:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            17:  */
        !            18:
        !            19: #include <sys/types.h>
        !            20:
        !            21: #include <errno.h>
        !            22: #include <stdio.h>
        !            23: #include <string.h>
        !            24: #include <stdlib.h>
        !            25:
        !            26: #include "tmux.h"
        !            27:
        !            28: /*
        !            29:  * Parse a command from a string.
        !            30:  */
        !            31:
        !            32: int    cmd_string_getc(const char *, size_t *);
        !            33: void   cmd_string_ungetc(const char *, size_t *);
        !            34: char   *cmd_string_string(const char *, size_t *, char, int);
        !            35: char   *cmd_string_variable(const char *, size_t *);
        !            36:
        !            37: int
        !            38: cmd_string_getc(const char *s, size_t *p)
        !            39: {
        !            40:        if (s[*p] == '\0')
        !            41:                return (EOF);
        !            42:        return (s[(*p)++]);
        !            43: }
        !            44:
        !            45: void
        !            46: cmd_string_ungetc(unused const char *s, size_t *p)
        !            47: {
        !            48:        (*p)--;
        !            49: }
        !            50:
        !            51: /*
        !            52:  * Parse command string. Returns -1 on error. If returning -1, cause is error
        !            53:  * string, or NULL for empty command.
        !            54:  */
        !            55: int
        !            56: cmd_string_parse(const char *s, struct cmd_list **cmdlist, char **cause)
        !            57: {
        !            58:        size_t          p;
        !            59:        int             ch, argc, rval, have_arg;
        !            60:        char          **argv, *buf, *t, *u;
        !            61:        size_t          len;
        !            62:
        !            63:        if ((t = strchr(s, ' ')) == NULL && (t = strchr(s, '\t')) == NULL)
        !            64:                t = strchr(s, '\0');
        !            65:        if ((u = strchr(s, '=')) != NULL && u < t) {
        !            66:                if (putenv((char *) s) != 0) {
        !            67:                        xasprintf(cause, "assignment failed: %s", s);
        !            68:                        return (-1);
        !            69:                }
        !            70:                *cmdlist = NULL;
        !            71:                return (0);
        !            72:        }
        !            73:
        !            74:        argv = NULL;
        !            75:        argc = 0;
        !            76:
        !            77:        buf = NULL;
        !            78:        len = 0;
        !            79:
        !            80:        have_arg = 0;
        !            81:
        !            82:        *cause = NULL;
        !            83:
        !            84:        *cmdlist = NULL;
        !            85:        rval = -1;
        !            86:
        !            87:        p = 0;
        !            88:        for (;;) {
        !            89:                ch = cmd_string_getc(s, &p);
        !            90:                switch (ch) {
        !            91:                case '\'':
        !            92:                        if ((t = cmd_string_string(s, &p, '\'', 0)) == NULL)
        !            93:                                goto error;
        !            94:                        buf = xrealloc(buf, 1, len + strlen(t) + 1);
        !            95:                        strlcpy(buf + len, t, strlen(t) + 1);
        !            96:                        len += strlen(t);
        !            97:                        xfree(t);
        !            98:
        !            99:                        have_arg = 1;
        !           100:                        break;
        !           101:                case '"':
        !           102:                        if ((t = cmd_string_string(s, &p, '"', 1)) == NULL)
        !           103:                                goto error;
        !           104:                        buf = xrealloc(buf, 1, len + strlen(t) + 1);
        !           105:                        strlcpy(buf + len, t, strlen(t) + 1);
        !           106:                        len += strlen(t);
        !           107:                        xfree(t);
        !           108:
        !           109:                        have_arg = 1;
        !           110:                        break;
        !           111:                case '$':
        !           112:                        if ((t = cmd_string_variable(s, &p)) == NULL)
        !           113:                                goto error;
        !           114:                        buf = xrealloc(buf, 1, len + strlen(t) + 1);
        !           115:                        strlcpy(buf + len, t, strlen(t) + 1);
        !           116:                        len += strlen(t);
        !           117:
        !           118:                        have_arg = 1;
        !           119:                        break;
        !           120:                case '#':
        !           121:                        /* Comment: discard rest of line. */
        !           122:                        while ((ch = cmd_string_getc(s, &p)) != EOF)
        !           123:                                ;
        !           124:                        /* FALLTHROUGH */
        !           125:                case EOF:
        !           126:                case ' ':
        !           127:                case '\t':
        !           128:                        if (have_arg) {
        !           129:                                buf = xrealloc(buf, 1, len + 1);
        !           130:                                buf[len] = '\0';
        !           131:
        !           132:                                argv = xrealloc(argv, argc + 1, sizeof *argv);
        !           133:                                argv[argc++] = buf;
        !           134:
        !           135:                                buf = NULL;
        !           136:                                len = 0;
        !           137:
        !           138:                                have_arg = 0;
        !           139:                        }
        !           140:
        !           141:                        if (ch != EOF)
        !           142:                                break;
        !           143:                        if (argc == 0)
        !           144:                                goto out;
        !           145:
        !           146:                        *cmdlist = cmd_list_parse(argc, argv, cause);
        !           147:                        if (*cmdlist == NULL)
        !           148:                                goto out;
        !           149:
        !           150:                        do
        !           151:                                xfree(argv[argc - 1]);
        !           152:                        while (--argc > 0);
        !           153:
        !           154:                        rval = 0;
        !           155:                        goto out;
        !           156:                default:
        !           157:                        if (len >= SIZE_MAX - 2)
        !           158:                                goto error;
        !           159:
        !           160:                        buf = xrealloc(buf, 1, len + 1);
        !           161:                        buf[len++] = ch;
        !           162:
        !           163:                        have_arg = 1;
        !           164:                        break;
        !           165:                }
        !           166:        }
        !           167:
        !           168: error:
        !           169:        xasprintf(cause, "invalid or unknown command: %s", s);
        !           170:
        !           171: out:
        !           172:        if (buf != NULL)
        !           173:                xfree(buf);
        !           174:
        !           175:        while (--argc >= 0)
        !           176:                xfree(argv[argc]);
        !           177:        if (argv != NULL)
        !           178:                xfree(argv);
        !           179:
        !           180:        return (rval);
        !           181: }
        !           182:
        !           183: char *
        !           184: cmd_string_string(const char *s, size_t *p, char endch, int esc)
        !           185: {
        !           186:        int     ch;
        !           187:        char   *buf, *t;
        !           188:        size_t  len;
        !           189:
        !           190:         buf = NULL;
        !           191:        len = 0;
        !           192:
        !           193:         while ((ch = cmd_string_getc(s, p)) != endch) {
        !           194:                 switch (ch) {
        !           195:                case EOF:
        !           196:                        goto error;
        !           197:                 case '\\':
        !           198:                        if (!esc)
        !           199:                                break;
        !           200:                         switch (ch = cmd_string_getc(s, p)) {
        !           201:                        case EOF:
        !           202:                                goto error;
        !           203:                         case 'r':
        !           204:                                 ch = '\r';
        !           205:                                 break;
        !           206:                         case 'n':
        !           207:                                 ch = '\n';
        !           208:                                 break;
        !           209:                         case 't':
        !           210:                                 ch = '\t';
        !           211:                                 break;
        !           212:                         }
        !           213:                         break;
        !           214:                case '$':
        !           215:                        if (!esc)
        !           216:                                break;
        !           217:                        if ((t = cmd_string_variable(s, p)) == NULL)
        !           218:                                goto error;
        !           219:                        buf = xrealloc(buf, 1, len + strlen(t) + 1);
        !           220:                        strlcpy(buf + len, t, strlen(t) + 1);
        !           221:                        len += strlen(t);
        !           222:                        continue;
        !           223:                 }
        !           224:
        !           225:                if (len >= SIZE_MAX - 2)
        !           226:                        goto error;
        !           227:                buf = xrealloc(buf, 1, len + 1);
        !           228:                 buf[len++] = ch;
        !           229:         }
        !           230:
        !           231:        buf = xrealloc(buf, 1, len + 1);
        !           232:        buf[len] = '\0';
        !           233:        return (buf);
        !           234:
        !           235: error:
        !           236:        if (buf != NULL)
        !           237:                xfree(buf);
        !           238:        return (NULL);
        !           239: }
        !           240:
        !           241: char *
        !           242: cmd_string_variable(const char *s, size_t *p)
        !           243: {
        !           244:        int     ch, fch;
        !           245:        char   *buf, *t;
        !           246:        size_t  len;
        !           247:
        !           248: #define cmd_string_first(ch) ((ch) == '_' || \
        !           249:        ((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z'))
        !           250: #define cmd_string_other(ch) ((ch) == '_' || \
        !           251:        ((ch) >= 'a' && (ch) <= 'z') || ((ch) >= 'A' && (ch) <= 'Z') || \
        !           252:        ((ch) >= '0' && (ch) <= '9'))
        !           253:
        !           254:         buf = NULL;
        !           255:        len = 0;
        !           256:
        !           257:        fch = EOF;
        !           258:        switch (ch = cmd_string_getc(s, p)) {
        !           259:        case EOF:
        !           260:                goto error;
        !           261:        case '{':
        !           262:                fch = '{';
        !           263:
        !           264:                ch = cmd_string_getc(s, p);
        !           265:                if (!cmd_string_first(ch))
        !           266:                        goto error;
        !           267:                /* FALLTHROUGH */
        !           268:        default:
        !           269:                if (!cmd_string_first(ch)) {
        !           270:                        xasprintf(&t, "$%c", ch);
        !           271:                        return (t);
        !           272:                }
        !           273:
        !           274:                buf = xrealloc(buf, 1, len + 1);
        !           275:                buf[len++] = ch;
        !           276:
        !           277:                for (;;) {
        !           278:                        ch = cmd_string_getc(s, p);
        !           279:                        if (ch == EOF || !cmd_string_other(ch))
        !           280:                                break;
        !           281:                        else {
        !           282:                                if (len >= SIZE_MAX - 3)
        !           283:                                        goto error;
        !           284:                                buf = xrealloc(buf, 1, len + 1);
        !           285:                                buf[len++] = ch;
        !           286:                        }
        !           287:                }
        !           288:        }
        !           289:
        !           290:        if (fch == '{' && ch != '}')
        !           291:                goto error;
        !           292:        if (ch != EOF && fch != '{')
        !           293:                cmd_string_ungetc(s, p); /* ch */
        !           294:
        !           295:        buf = xrealloc(buf, 1, len + 1);
        !           296:        buf[len] = '\0';
        !           297:
        !           298:        if ((t = getenv(buf)) == NULL) {
        !           299:                xfree(buf);
        !           300:                return (xstrdup(""));
        !           301:        }
        !           302:        xfree(buf);
        !           303:        return (xstrdup(t));
        !           304:
        !           305: error:
        !           306:        if (buf != NULL)
        !           307:                xfree(buf);
        !           308:        return (NULL);
        !           309: }