#include "wmcliphist.h" #include #define RC_BUF_SIZE 256 /* automat state */ typedef enum { STATE_BEGINING, STATE_COMMENT, STATE_DIRECTIVE, STATE_VALUE, STATE_EXPRESSION_START, STATE_EXPRESSION, STATE_EXPRESSION_END, STATE_ACTION, STATE_COMMAND } STATE; GList *action_list = NULL; /* add character to buffer */ #define add_to_buff(buf, pos, chr) do { \ buf[pos++] = chr; \ buf[pos] = '\0'; \ if (pos + 1 == RC_BUF_SIZE) \ error = 7; \ } while (0) #define ismywhite(c) (c == '\t' || c == ' ') /* * returns config/data file name in user's home */ char * rcconfig_get_name(char *append) { static gchar fname[PATH_MAX]; const gchar *home; begin_func("rcconfig_get_name"); if (!(home = g_getenv("HOME"))) return_val(NULL); memset(fname, 0, PATH_MAX); snprintf(fname, PATH_MAX, "%s/.wmcliphist%s", home, append); return_val(fname); } /* * appends parsed action to action list */ int action_append(char *expr_buf, char *action_buf, char *cmd_buf) { ACTION *action; begin_func("action_append"); action = g_new0(ACTION, 1); if (regcomp(&action->expression, expr_buf, REG_EXTENDED|REG_ICASE|REG_NOSUB) != 0) { g_free(action); return_val(-101); } if (strcmp(action_buf, "exec") == 0) action->action = ACT_EXEC; else if (strcmp(action_buf, "submenu") == 0) action->action = ACT_SUBMENU; else if (strcmp(action_buf, "ignore") == 0) action->action = ACT_IGNORE; else { g_free(action); return_val(-102); } action->command = g_strdup(cmd_buf); action_list = g_list_append(action_list, action); return_val(0); } /* * read and parse rcconfig */ int rcconfig_get(char *fname) { int f_rc; char tmp[1024], c; int byte_cnt; STATE state = STATE_BEGINING; char direc_buf[RC_BUF_SIZE], expr_buf[RC_BUF_SIZE], action_buf[RC_BUF_SIZE], cmd_buf[RC_BUF_SIZE]; int buf_index = 0; int error = 0, eof = 0; int i; int line = 0; int res; begin_func("rcconfig_get"); close(open(fname, O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)); if ((f_rc = open(fname, O_RDONLY)) < 0) { fprintf(stderr, ".wmcliphistrc not found\n"); return_val(1); } i = byte_cnt = 0; while (1) { if (i == byte_cnt) { byte_cnt = read(f_rc, tmp, 1024); if (byte_cnt == -1) { fprintf(stderr, "cannot read .wmcliphistrc\n"); break; } else if (byte_cnt < 1024) { tmp[byte_cnt++] = 0; eof = 1; } i = 0; } c = tmp[i++]; switch (state) { case STATE_BEGINING: line++; if (isalnum(c)) { state = STATE_DIRECTIVE; buf_index = 0; add_to_buff(direc_buf, buf_index, c); } else if (c == '#') state = STATE_COMMENT; else if (ismywhite(c)) line--; else if (c == '\n') state = STATE_BEGINING; else error = 1; break; case STATE_COMMENT: if (c == '\n' || c == '\0') state = STATE_BEGINING; break; case STATE_DIRECTIVE: if (ismywhite(c)) { if (strcmp(direc_buf, "action") == 0) { state = STATE_EXPRESSION_START; buf_index = 0; } else if (strcmp(direc_buf, "menukey") == 0) { state = STATE_VALUE; buf_index = 0; } else if (strcmp(direc_buf, "prev_item_key") == 0) { state = STATE_VALUE; buf_index = 0; } else if (strcmp(direc_buf, "exec_item_key") == 0) { state = STATE_VALUE; buf_index = 0; } else if (strcmp(direc_buf, "keep") == 0) { state = STATE_VALUE; buf_index = 0; } else if (strcmp(direc_buf, "lcolor") == 0) { state = STATE_VALUE; buf_index = 0; } else if (strcmp(direc_buf, "clipboard") == 0) { state = STATE_VALUE; buf_index = 0; } else if (strcmp(direc_buf, "autosave") == 0) { state = STATE_VALUE; buf_index = 0; } else if (strcmp(direc_buf, "confirm_exec") == 0) { state = STATE_VALUE; buf_index = 0; } else if (strcmp(direc_buf, "exec_immediately") == 0) { state = STATE_VALUE; buf_index = 0; } else if (strcmp(direc_buf, "exec_middleclick") == 0) { state = STATE_VALUE; buf_index = 0; } else if (strcmp(direc_buf, "exec_hotkey") == 0) { state = STATE_VALUE; buf_index = 0; } else if (strcmp(direc_buf, "auto_take_up") == 0) { state = STATE_VALUE; buf_index = 0; } else { error = 8; } } else if (isalpha(c) || c == '_') { add_to_buff(direc_buf, buf_index, c); } else { error = 1; } break; case STATE_VALUE: if (c == '\n' || ismywhite(c)) { if (strcmp(direc_buf, "menukey") == 0) { memset(menukey_str, 0, 32); strncpy(menukey_str, expr_buf, 31); } else if (strcmp(direc_buf, "prev_item_key") == 0) { memset(prev_item_key_str, 0, 32); strncpy(prev_item_key_str, expr_buf, 31); } else if (strcmp(direc_buf, "exec_item_key") == 0) { memset(exec_item_key_str, 0, 32); strncpy(exec_item_key_str, expr_buf, 31); } else if (strcmp(direc_buf, "keep") == 0) { num_items_to_keep = atoi(expr_buf); } else if (strcmp(direc_buf, "lcolor") == 0) { memset(locked_color_str, 0, 32); strncpy(locked_color_str, expr_buf, 31); } else if (strcmp(direc_buf, "clipboard") == 0) { memset(clipboard_str, 0, 32); strncpy(clipboard_str, expr_buf, 31); } else if (strcmp(direc_buf, "autosave") == 0) { autosave_period = atoi(expr_buf); } else if (strcmp(direc_buf, "confirm_exec") == 0) { if (strcasecmp(expr_buf, "yes") == 0) { confirm_exec = 1; } } else if (strcmp(direc_buf, "exec_immediately") == 0) { if (strcasecmp(expr_buf, "no") == 0) { exec_immediately= 0; } } else if (strcmp(direc_buf, "exec_middleclick") == 0) { if (strcasecmp(expr_buf, "no") == 0) { exec_middleclick = 0; } } else if (strcmp(direc_buf, "exec_hotkey") == 0) { if (strcasecmp(expr_buf, "no") == 0) { exec_hotkey = 0; } } else if (strcmp(direc_buf, "auto_take_up") == 0) { if (strcasecmp(expr_buf, "no") == 0) { auto_take_up = 0; } } else error = 1; } else if (isgraph(c)) add_to_buff(expr_buf, buf_index, c); else error = 2; if (error == 0) { if (c == '\n' || c == '\0') { buf_index = 0; state = STATE_BEGINING; } else if (ismywhite(c)) { buf_index = 0; state = STATE_COMMENT; } } break; case STATE_EXPRESSION_START: if (c == '"') state = STATE_EXPRESSION; else error = 1; break; case STATE_EXPRESSION: if (c == '"') state = STATE_EXPRESSION_END; else if (c == '\n') error = 1; else add_to_buff(expr_buf, buf_index, c); break; case STATE_EXPRESSION_END: if (c != ' ' && c != '\t') error = 1; if (strcmp(direc_buf, "action") == 0) { state = STATE_ACTION; buf_index = 0; } else error = 1; break; case STATE_ACTION: if (c == ' ' || c == '\t') { state = STATE_COMMAND; buf_index = 0; } else if (c == '\0' || c == '\n') { if (strcmp(action_buf, "ignore") == 0) { state = STATE_BEGINING; buf_index = 0; *cmd_buf = '\0'; res = action_append( expr_buf, action_buf, cmd_buf); if (res < 0) error = abs(res); } else error = 1; } else if (isalpha(c)) add_to_buff(action_buf, buf_index, c); else error = 1; break; case STATE_COMMAND: if (c == '\n' || c == '\0') { state = STATE_BEGINING; buf_index = 0; res = action_append( expr_buf, action_buf, cmd_buf); if (res < 0) error = abs(res); } else add_to_buff(cmd_buf, buf_index, c); break; } if (!error && (!eof || i < byte_cnt)) continue; switch (state) { case STATE_DIRECTIVE: if (error == 7) fprintf(stderr, "Directive is too long " "(line %d)\n", line); else if (error == 8) fprintf(stderr, "Unknown directive " "(line %d)\n", line); else fprintf(stderr, "Only letters are " "allowed in directive " "name (line %d)\n", line); break; case STATE_EXPRESSION_START: case STATE_EXPRESSION: if (error == 7) fprintf(stderr, "Expression is too long " "(line %d)\n", line); else fprintf(stderr, "Expression must be " "enclosed with quotes " "\" (line %d)\n", line); break; case STATE_EXPRESSION_END: fprintf(stderr, "One space/tab and " "action must follow " "each expression" " (line %d)\n", line); break; case STATE_ACTION: if (error == 1) fprintf(stderr, "Only letters are " "allowed in action " "name (line %d)\n", line); else if (error == 101) fprintf(stderr, "Invalid expression " "(line %d)\n", line); else if (error == 7) fprintf(stderr, "Action is too long " "(line %d)\n", line); else fprintf(stderr, "Invalid action " "(line %d)\n", line); break; case STATE_VALUE: if (error == 1) fprintf(stderr, "Invalid directive " "(line %d)\n", line); else if (error == 7) fprintf(stderr, "Value is too long " "(line %d)\n", line); else fprintf(stderr, "Invalid value " "(line %d)\n", line); break; case STATE_COMMAND: if (error == 101) fprintf(stderr, "Invalid expression " "(line %d)\n", line); else if (error == 7) fprintf(stderr, "Command is too long " "(line %d)\n", line); else fprintf(stderr, "Invalid action " "(line %d)\n", line); break; case STATE_COMMENT: if (!eof) fprintf(stderr, "Unknown error " "(line %d)\n", line); else error = 0; break; case STATE_BEGINING: /* everything is OK */ error = 0; break; } break; } close(f_rc); return_val(error); } /* * free rcconfig data */ void rcconfig_free() { GList *list_node; begin_func("rcconfig_free"); list_node = action_list; while (list_node) { ACTION *action = list_node->data; g_free(action->command); regfree(&action->expression); g_free(action); list_node = list_node->next; } g_list_free(action_list); return_void(); }