4 * TOMOYO Linux's utilities.
6 * Copyright (C) 2005-2010 NTT DATA CORPORATION
8 * Version: 1.8.0 2010/11/11
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License v2 as published by the
12 * Free Software Foundation.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 * You should have received a copy of the GNU General Public License along with
20 * this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "editpolicy.h"
28 static char *gpet_line = NULL;
33 extern int ccs_persistent_fd;
35 struct ccs_path_group_entry *ccs_path_group_list = NULL;
36 int ccs_path_group_list_len = 0;
37 struct ccs_generic_acl *ccs_generic_acl_list = NULL;
38 int ccs_generic_acl_list_count = 0;
40 static const char *ccs_policy_dir = NULL;
41 static _Bool ccs_offline_mode = false;
42 static _Bool ccs_readonly_mode = false;
43 static unsigned int ccs_refresh_interval = 0;
44 static _Bool ccs_need_reload = false;
45 static const char *ccs_policy_file = NULL;
46 static const char *ccs_list_caption = NULL;
47 static char *ccs_current_domain = NULL;
48 static unsigned int ccs_current_pid = 0;
49 static int ccs_current_screen = CCS_SCREEN_DOMAIN_LIST;
50 static struct ccs_transition_control_entry *ccs_transition_control_list = NULL;
51 static int ccs_transition_control_list_len = 0;
52 static int ccs_profile_sort_type = 0;
53 static int ccs_unnumbered_domain_count = 0;
54 static int ccs_window_width = 0;
55 static int ccs_window_height = 0;
56 static int ccs_current_item_index[CCS_MAXSCREEN];
57 int ccs_current_y[CCS_MAXSCREEN];
58 int ccs_list_item_count[CCS_MAXSCREEN];
59 static int ccs_body_lines = 0;
60 static int ccs_max_eat_col[CCS_MAXSCREEN];
61 static int ccs_eat_col = 0;
62 static int ccs_max_col = 0;
63 static int ccs_list_indent = 0;
64 static int ccs_acl_sort_type = 0;
65 static char *ccs_last_error = NULL;
69 static void ccs_sigalrm_handler(int sig);
70 static const char *ccs_get_last_name(const struct ccs_domain_policy *dp, const int index);
71 static _Bool ccs_keeper_domain(struct ccs_domain_policy *dp, const int index);
72 static _Bool ccs_initializer_source(struct ccs_domain_policy *dp, const int index);
73 static _Bool ccs_initializer_target(struct ccs_domain_policy *dp, const int index);
74 static _Bool ccs_domain_unreachable(struct ccs_domain_policy *dp, const int index);
75 static _Bool ccs_deleted_domain(struct ccs_domain_policy *dp, const int index);
76 static const struct ccs_transition_control_entry *ccs_transition_control(const struct ccs_path_info *domainname, const char *program);
77 static int ccs_generic_acl_compare(const void *a, const void *b);
78 static int ccs_generic_acl_compare0(const void *a, const void *b);
79 static int ccs_string_acl_compare(const void *a, const void *b);
80 static int ccs_profile_entry_compare(const void *a, const void *b);
81 static void ccs_read_generic_policy(void);
82 static int ccs_add_transition_control_entry(const char *domainname, const char *program, const u8 type);
83 static int ccs_add_transition_control_policy(char *data, const u8 type);
84 static int ccs_add_path_group_entry(const char *group_name, const char *member_name, const _Bool is_delete);
85 static int ccs_add_path_group_policy(char *data, const _Bool is_delete);
86 static void ccs_assign_dis(struct ccs_domain_policy *dp, const struct ccs_path_info *domainname, const char *program);
87 static int ccs_domainname_attribute_compare(const void *a, const void *b);
88 static void ccs_read_domain_and_exception_policy(struct ccs_domain_policy *dp);
89 static void ccs_show_current(struct ccs_domain_policy *dp);
90 static const char *ccs_eat(const char *str);
91 static int ccs_show_domain_line(struct ccs_domain_policy *dp, const int index);
92 static int ccs_show_acl_line(const int index, const int list_indent);
93 static int ccs_show_profile_line(const int index);
94 static int ccs_show_literal_line(const int index);
95 static int ccs_show_meminfo_line(const int index);
96 static void ccs_show_list(struct ccs_domain_policy *dp);
97 static void ccs_resize_window(void);
98 static void ccs_up_arrow_key(struct ccs_domain_policy *dp);
99 static void ccs_down_arrow_key(struct ccs_domain_policy *dp);
100 static void ccs_page_up_key(struct ccs_domain_policy *dp);
101 static void ccs_page_down_key(struct ccs_domain_policy *dp);
102 static void ccs_adjust_cursor_pos(const int item_count);
103 static void ccs_set_cursor_pos(const int index);
104 static int ccs_count(const unsigned char *array, const int len);
105 static int ccs_count2(const struct ccs_generic_acl *array, int len);
106 static _Bool ccs_select_item(struct ccs_domain_policy *dp, const int index);
107 static int ccs_generic_acl_compare(const void *a, const void *b);
108 static void ccs_delete_entry(struct ccs_domain_policy *dp, const int index);
109 static void ccs_add_entry(struct ccs_readline_data *rl);
110 static void ccs_find_entry(struct ccs_domain_policy *dp, _Bool input, _Bool forward, const int current, struct ccs_readline_data *rl);
111 static void ccs_set_profile(struct ccs_domain_policy *dp, const int current);
112 static void ccs_set_level(struct ccs_domain_policy *dp, const int current);
113 static void ccs_set_quota(struct ccs_domain_policy *dp, const int current);
114 static int ccs_select_window(struct ccs_domain_policy *dp, const int current);
115 static _Bool ccs_show_command_key(const int screen, const _Bool readonly);
116 static int ccs_generic_list_loop(struct ccs_domain_policy *dp);
117 static void ccs_copy_file(const char *source, const char *dest);
118 static FILE *ccs_editpolicy_open_write(const char *filename);
120 /* Utility Functions */
122 static void ccs_copy_file(const char *source, const char *dest)
124 FILE *fp_in = fopen(source, "r");
125 FILE *fp_out = fp_in ? ccs_editpolicy_open_write(dest) : NULL;
126 while (fp_in && fp_out) {
127 int c = fgetc(fp_in);
138 static const char *ccs_get_last_name(const struct ccs_domain_policy *dp,
141 const char *cp0 = ccs_domain_name(dp, index);
142 const char *cp1 = strrchr(cp0, ' ');
148 static int ccs_count(const unsigned char *array, const int len)
152 for (i = 0; i < len; i++)
158 static int ccs_count2(const struct ccs_generic_acl *array, int len)
162 for (i = 0; i < len; i++)
163 if (array[i].selected)
168 static int ccs_count3(const struct ccs_task_entry *array, int len)
172 for (i = 0; i < len; i++)
173 if (array[i].selected)
178 static _Bool ccs_keeper_domain(struct ccs_domain_policy *dp, const int index)
180 return dp->list[index].is_dk;
183 static _Bool ccs_initializer_source(struct ccs_domain_policy *dp, const int index)
185 return dp->list[index].is_dis;
188 static _Bool ccs_initializer_target(struct ccs_domain_policy *dp, const int index)
190 return dp->list[index].is_dit;
193 static _Bool ccs_domain_unreachable(struct ccs_domain_policy *dp, const int index)
195 return dp->list[index].is_du;
198 static _Bool ccs_deleted_domain(struct ccs_domain_policy *dp, const int index)
200 return dp->list[index].is_dd;
203 static int ccs_generic_acl_compare0(const void *a, const void *b)
205 const struct ccs_generic_acl *a0 = (struct ccs_generic_acl *) a;
206 const struct ccs_generic_acl *b0 = (struct ccs_generic_acl *) b;
207 const char *a1 = ccs_directives[a0->directive].alias;
208 const char *b1 = ccs_directives[b0->directive].alias;
209 const char *a2 = a0->operand;
210 const char *b2 = b0->operand;
211 const int ret = strcmp(a1, b1);
214 return strcmp(a2, b2);
217 static int ccs_string_acl_compare(const void *a, const void *b)
219 const struct ccs_generic_acl *a0 = (struct ccs_generic_acl *) a;
220 const struct ccs_generic_acl *b0 = (struct ccs_generic_acl *) b;
221 const char *a1 = a0->operand;
222 const char *b1 = b0->operand;
223 return strcmp(a1, b1);
226 static int ccs_add_transition_control_policy(char *data, const u8 type)
228 char *domainname = strstr(data, " from ");
232 } else if (type == CCS_TRANSITION_CONTROL_NO_KEEP ||
233 type == CCS_TRANSITION_CONTROL_KEEP) {
237 return ccs_add_transition_control_entry(domainname, data, type);
240 static int ccs_add_path_group_policy(char *data, const _Bool is_delete)
242 char *cp = strchr(data, ' ');
246 return ccs_add_path_group_entry(data, cp, is_delete);
249 static void ccs_assign_dis(struct ccs_domain_policy *dp,
250 const struct ccs_path_info *domainname,
253 const struct ccs_transition_control_entry *d_t =
254 ccs_transition_control(domainname, program);
255 if (d_t && d_t->type == CCS_TRANSITION_CONTROL_INITIALIZE) {
259 line = ccs_shprintf("%s %s", domainname->name, program);
260 ccs_normalize_line(line);
261 source = ccs_assign_domain(dp, line, true, false);
264 line = ccs_shprintf(CCS_ROOT_NAME " %s", program);
265 dp->list[source].target_domainname = strdup(line);
266 if (!dp->list[source].target_domainname)
272 static int ccs_domainname_attribute_compare(const void *a, const void *b)
274 const struct ccs_domain_info *a0 = a;
275 const struct ccs_domain_info *b0 = b;
276 const int k = strcmp(a0->domainname->name, b0->domainname->name);
277 if ((k > 0) || (!k && !a0->is_dis && b0->is_dis))
282 static const char *ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {
283 [CCS_TRANSITION_CONTROL_INITIALIZE] = "initialize_domain ",
284 [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",
285 [CCS_TRANSITION_CONTROL_KEEP] = "keep_domain ",
286 [CCS_TRANSITION_CONTROL_NO_KEEP] = "no_keep_domain ",
289 static int ccs_find_target_domain(struct ccs_domain_policy *dp, const int index)
291 return ccs_find_domain(dp, dp->list[index].target_domainname, false, false);
294 static int ccs_show_domain_line(struct ccs_domain_policy *dp, const int index)
297 const struct ccs_transition_control_entry *transition_control;
300 const int number = dp->list[index].number;
302 const bool is_dis = ccs_initializer_source(dp, index);
303 const bool is_deleted = ccs_deleted_domain(dp, index);
305 printw("%c%4d:", dp->list_selected[index] ? '&' : ' ', number);
306 if (dp->list[index].profile_assigned)
307 printw("%3u", dp->list[index].profile);
310 printw(" %c%c%c ", ccs_keeper_domain(dp, index) ? '#' : ' ',
311 ccs_initializer_target(dp, index) ? '*' : ' ',
312 ccs_domain_unreachable(dp, index) ? '!' : ' ');
316 sp = ccs_domain_name(dp, index);
318 const char *cp = strchr(sp, ' ');
321 printw("%s", ccs_eat(" "));
326 printw("%s", ccs_eat("( "));
329 printw("%s", ccs_eat(sp));
330 tmp_col += strlen(sp);
332 printw("%s", ccs_eat(" )"));
335 transition_control = dp->list[index].d_t;
336 if (!transition_control || is_dis)
337 goto no_transition_control;
339 line = ccs_shprintf(" ( %s%s from %s )",
340 ccs_transition_type[transition_control->type],
341 transition_control->program ?
342 transition_control->program->name : "any",
343 transition_control->domainname ?
344 transition_control->domainname->name : "any");
345 printw("%s", ccs_eat(line));
346 tmp_col += strlen(line);
349 no_transition_control:
353 redirect_index = ccs_find_target_domain(dp, index);
354 if (redirect_index >= 0)
355 line = ccs_shprintf(" ( -> %d )", dp->list[redirect_index].number);
357 line = ccs_shprintf(" ( -> Not Found )");
358 printw("%s", ccs_eat(line));
359 tmp_col += strlen(line);
365 static int ccs_show_acl_line(const int index, const int list_indent)
367 u16 directive = ccs_generic_acl_list[index].directive;
368 const char *cp1 = ccs_directives[directive].alias;
369 const char *cp2 = ccs_generic_acl_list[index].operand;
370 int len = list_indent - ccs_directives[directive].alias_len;
372 ccs_generic_acl_list[index].selected ? '&' : ' ',
373 index, ccs_eat(cp1));
375 printw("%s", ccs_eat(" "));
376 printw("%s", ccs_eat(cp2));
377 return strlen(cp1) + strlen(cp2) + 8 + list_indent;
380 static int ccs_show_profile_line(const int index)
382 const char *cp = ccs_generic_acl_list[index].operand;
383 const u16 profile = ccs_generic_acl_list[index].directive;
386 snprintf(number, sizeof(number) - 1, "%3u-", profile);
387 printw("%c%4d: %s", ccs_generic_acl_list[index].selected ? '&' : ' ',
388 index, ccs_eat(number));
389 printw("%s ", ccs_eat(cp));
390 return strlen(number) + strlen(cp) + 8;
393 static int ccs_show_literal_line(const int index)
395 const char *cp = ccs_generic_acl_list[index].operand;
397 ccs_generic_acl_list[index].selected ? '&' : ' ',
399 return strlen(cp) + 8;
402 static int ccs_show_meminfo_line(const int index)
405 unsigned int now = 0;
406 unsigned int quota = -1;
407 const char *data = ccs_generic_acl_list[index].operand;
409 if (sscanf(data, "Policy: %u (Quota: %u)", &now, "a) >= 1)
410 line = ccs_shprintf("Memory used for policy = %10u bytes "
411 "(Quota: %10u bytes)", now, quota);
412 else if (sscanf(data, "Audit logs: %u (Quota: %u)", &now, "a) >= 1)
413 line = ccs_shprintf("Memory used for audit logs = %10u bytes "
414 "(Quota: %10u bytes)", now, quota);
415 else if (sscanf(data, "Query lists: %u (Quota: %u)", &now, "a) >= 1)
416 line = ccs_shprintf("Memory used for query lists = %10u bytes "
417 "(Quota: %10u bytes)", now, quota);
418 else if (sscanf(data, "Total: %u", &now) == 1)
419 line = ccs_shprintf("Total memory in use = %10u bytes",
421 else if (sscanf(data, "Shared: %u (Quota: %u)", &now, "a) >= 1)
422 line = ccs_shprintf("Memory for string data = %10u bytes "
423 "Quota = %10u bytes", now, quota);
424 else if (sscanf(data, "Private: %u (Quota: %u)", &now, "a) >= 1)
425 line = ccs_shprintf("Memory for numeric data = %10u bytes "
426 "Quota = %10u bytes", now, quota);
427 else if (sscanf(data, "Dynamic: %u (Quota: %u)", &now, "a) >= 1)
428 line = ccs_shprintf("Memory for temporary data = %10u bytes "
429 "Quota = %10u bytes", now, quota);
431 line = ccs_shprintf("%s", data);
433 printw("%s", ccs_eat(line));
439 static int ccs_domain_sort_type = 0;
441 static _Bool ccs_show_command_key(const int screen, const _Bool readonly)
445 printw("Commands available for this screen are:\n\n");
446 printw("Q/q Quit this editor.\n");
447 printw("R/r Refresh to the latest information.\n");
449 case CCS_SCREEN_MEMINFO_LIST:
452 printw("F/f Find first.\n");
453 printw("N/n Find next.\n");
454 printw("P/p Find previous.\n");
456 printw("W/w Switch to selected screen.\n");
457 /* printw("Tab Switch to next screen.\n"); */
459 case CCS_SCREEN_MEMINFO_LIST:
462 printw("Insert Copy an entry at the cursor position to "
463 "history buffer.\n");
464 printw("Space Invert selection state of an entry at "
465 "the cursor position.\n");
466 printw("C/c Copy selection state of an entry at "
467 "the cursor position to all entries below the cursor "
471 case CCS_SCREEN_DOMAIN_LIST:
472 if (ccs_domain_sort_type) {
473 printw("S/s Set profile number of selected "
475 printw("Enter Edit ACLs of a process at the "
476 "cursor position.\n");
479 printw("A/a Add a new domain.\n");
480 printw("D/d Delete selected domains.\n");
481 printw("S/s Set profile number of "
482 "selected domains.\n");
484 printw("Enter Edit ACLs of a domain at the "
485 "cursor position.\n");
488 case CCS_SCREEN_MEMINFO_LIST:
490 printw("S/s Set memory quota of selected "
493 case CCS_SCREEN_PROFILE_LIST:
495 printw("S/s Set mode of selected items.\n");
499 case CCS_SCREEN_EXCEPTION_LIST:
500 case CCS_SCREEN_ACL_LIST:
501 case CCS_SCREEN_MANAGER_LIST:
503 printw("A/a Add a new entry.\n");
504 printw("D/d Delete selected entries.\n");
508 case CCS_SCREEN_PROFILE_LIST:
510 printw("A/a Define a new profile.\n");
513 case CCS_SCREEN_ACL_LIST:
514 printw("O/o Set selection state to other entries "
515 "included in an entry at the cursor position.\n");
517 case CCS_SCREEN_PROFILE_LIST:
518 printw("@ Switch sort type.\n");
520 case CCS_SCREEN_DOMAIN_LIST:
521 if (!ccs_offline_mode)
522 printw("@ Switch domain/process list.\n");
524 printw("Arrow-keys and PageUp/PageDown/Home/End keys "
526 printw("Press '?' to escape from this help.\n");
530 if (c == '?' || c == EOF)
532 if (c == 'Q' || c == 'q')
540 static void ccs_close_write(FILE *fp)
542 if (ccs_network_mode) {
550 static void ccs_set_error(const char *filename)
553 const int len = strlen(filename) + 128;
554 ccs_last_error = realloc(ccs_last_error, len);
557 memset(ccs_last_error, 0, len);
558 snprintf(ccs_last_error, len - 1, "Can't open %s .", filename);
560 free(ccs_last_error);
561 ccs_last_error = NULL;
565 static FILE *ccs_editpolicy_open_write(const char *filename)
567 if (ccs_network_mode) {
568 FILE *fp = ccs_open_write(filename);
570 ccs_set_error(filename);
572 } else if (ccs_offline_mode) {
575 if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd)) {
576 fprintf(stderr, "socketpair()\n");
579 if (shutdown(fd[0], SHUT_RD))
581 memset(request, 0, sizeof(request));
582 snprintf(request, sizeof(request) - 1, "POST %s", filename);
583 ccs_send_fd(request, &fd[1]);
584 return fdopen(fd[0], "w");
591 if (ccs_readonly_mode)
593 fp = ccs_open_write(filename);
595 ccs_set_error(filename);
600 static FILE *ccs_editpolicy_open_read(const char *filename)
602 if (ccs_network_mode) {
603 return ccs_open_read(filename);
604 } else if (ccs_offline_mode) {
608 if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd)) {
609 fprintf(stderr, "socketpair()\n");
612 if (shutdown(fd[0], SHUT_WR))
614 fp = fdopen(fd[0], "r");
617 memset(request, 0, sizeof(request));
618 snprintf(request, sizeof(request) - 1, "GET %s", filename);
619 ccs_send_fd(request, &fd[1]);
626 return fopen(filename, "r");
630 static int ccs_open2(const char *filename, int mode)
632 const int fd = open(filename, mode);
633 if (fd == EOF && errno != ENOENT)
634 ccs_set_error(filename);
638 static void ccs_sigalrm_handler(int sig)
640 ccs_need_reload = true;
641 alarm(ccs_refresh_interval);
644 static const char *ccs_eat(const char *str)
646 while (*str && ccs_eat_col) {
653 static const struct ccs_transition_control_entry *ccs_transition_control
654 (const struct ccs_path_info *domainname, const char *program)
658 struct ccs_path_info last_name;
659 last_name.name = strrchr(domainname->name, ' ');
663 last_name.name = domainname->name;
664 ccs_fill_path_info(&last_name);
665 for (type = 0; type < CCS_MAX_TRANSITION_TYPE; type++) {
667 for (i = 0; i < ccs_transition_control_list_len; i++) {
668 struct ccs_transition_control_entry *ptr
669 = &ccs_transition_control_list[i];
670 if (ptr->type != type)
672 if (ptr->domainname) {
673 if (!ptr->is_last_name) {
674 if (ccs_pathcmp(ptr->domainname,
678 if (ccs_pathcmp(ptr->domainname,
683 if (ptr->program && strcmp(ptr->program->name, program))
685 if (type == CCS_TRANSITION_CONTROL_NO_INITIALIZE) {
687 * Do not check for initialize_domain if
688 * no_initialize_domain matched.
690 type = CCS_TRANSITION_CONTROL_NO_KEEP;
693 if (type == CCS_TRANSITION_CONTROL_INITIALIZE ||
694 type == CCS_TRANSITION_CONTROL_KEEP)
703 static int ccs_profile_entry_compare(const void *a, const void *b)
705 const struct ccs_generic_acl *a0 = (struct ccs_generic_acl *) a;
706 const struct ccs_generic_acl *b0 = (struct ccs_generic_acl *) b;
707 const char *a1 = a0->operand;
708 const char *b1 = b0->operand;
709 const int a2 = a0->directive;
710 const int b2 = b0->directive;
711 if (a2 >= 256 || b2 >= 256) {
713 static const char *global[5] = {
715 "PREFERENCE::audit=",
716 "PREFERENCE::learning=",
717 "PREFERENCE::permissive=",
718 "PREFERENCE::enforcing="
720 for (i = 0; i < 5; i++) {
721 if (!strncmp(a1, global[i], strlen(global[i])))
723 if (!strncmp(b1, global[i], strlen(global[i])))
727 if (ccs_profile_sort_type == 0) {
729 return strcmp(a1, b1);
733 const int a3 = strcspn(a1, "=");
734 const int b3 = strcspn(b1, "=");
735 const int c = strncmp(a1, b1, a3 >= b3 ? b3 : a3);
745 static void ccs_read_generic_policy(void)
749 while (ccs_generic_acl_list_count)
751 ccs_generic_acl_list[--ccs_generic_acl_list_count].operand);
752 if (ccs_current_screen == CCS_SCREEN_ACL_LIST) {
753 if (ccs_network_mode)
754 /* We can read after write. */
755 fp = ccs_editpolicy_open_write(ccs_policy_file);
756 else if (!ccs_offline_mode)
757 /* Don't set error message if failed. */
758 fp = fopen(ccs_policy_file, "r+");
760 if (ccs_domain_sort_type)
761 fprintf(fp, "select pid=%u\n", ccs_current_pid);
763 fprintf(fp, "select domain=%s\n",
765 if (ccs_network_mode)
771 fp = ccs_editpolicy_open_read(ccs_policy_file);
773 ccs_set_error(ccs_policy_file);
778 char *line = ccs_freadline(fp);
783 if (ccs_current_screen == CCS_SCREEN_ACL_LIST) {
784 if (ccs_domain_def(line)) {
785 flag = !strcmp(line, ccs_current_domain);
788 if (!flag || !line[0] ||
789 !strncmp(line, "use_profile ", 12))
795 switch (ccs_current_screen) {
796 case CCS_SCREEN_EXCEPTION_LIST:
797 case CCS_SCREEN_ACL_LIST:
798 directive = ccs_find_directive(true, line);
799 if (directive == CCS_DIRECTIVE_NONE)
802 case CCS_SCREEN_PROFILE_LIST:
803 cp = strchr(line, '-');
806 directive = atoi(line);
807 memmove(line, cp, strlen(cp) + 1);
809 directive = (u16) -1;
812 directive = CCS_DIRECTIVE_NONE;
815 ccs_generic_acl_list = realloc(ccs_generic_acl_list,
816 (ccs_generic_acl_list_count + 1) *
817 sizeof(struct ccs_generic_acl));
818 if (!ccs_generic_acl_list)
823 ccs_generic_acl_list[ccs_generic_acl_list_count].directive = directive;
824 ccs_generic_acl_list[ccs_generic_acl_list_count].selected = 0;
825 ccs_generic_acl_list[ccs_generic_acl_list_count++].operand = cp;
829 switch (ccs_current_screen) {
830 case CCS_SCREEN_ACL_LIST:
831 qsort(ccs_generic_acl_list, ccs_generic_acl_list_count,
832 sizeof(struct ccs_generic_acl), ccs_generic_acl_compare);
834 case CCS_SCREEN_EXCEPTION_LIST:
835 qsort(ccs_generic_acl_list, ccs_generic_acl_list_count,
836 sizeof(struct ccs_generic_acl), ccs_generic_acl_compare0);
838 case CCS_SCREEN_PROFILE_LIST:
839 qsort(ccs_generic_acl_list, ccs_generic_acl_list_count,
840 sizeof(struct ccs_generic_acl), ccs_profile_entry_compare);
843 qsort(ccs_generic_acl_list, ccs_generic_acl_list_count,
844 sizeof(struct ccs_generic_acl), ccs_string_acl_compare);
848 static int ccs_add_transition_control_entry(const char *domainname,
853 struct ccs_transition_control_entry *ptr;
854 _Bool is_last_name = false;
855 if (program && strcmp(program, "any")) {
856 if (!ccs_correct_path(program))
859 if (domainname && strcmp(domainname, "any")) {
860 if (!ccs_correct_domain(domainname)) {
861 if (!ccs_correct_path(domainname))
866 vp = realloc(ccs_transition_control_list,
867 (ccs_transition_control_list_len + 1) *
868 sizeof(struct ccs_transition_control_entry));
871 ccs_transition_control_list = vp;
872 ptr = &ccs_transition_control_list[ccs_transition_control_list_len++];
873 memset(ptr, 0, sizeof(struct ccs_transition_control_entry));
874 if (program && strcmp(program, "any")) {
875 ptr->program = ccs_savename(program);
879 if (domainname && strcmp(domainname, "any")) {
880 ptr->domainname = ccs_savename(domainname);
881 if (!ptr->domainname)
885 ptr->is_last_name = is_last_name;
889 static int ccs_add_path_group_entry(const char *group_name, const char *member_name,
890 const _Bool is_delete)
892 const struct ccs_path_info *saved_group_name;
893 const struct ccs_path_info *saved_member_name;
896 struct ccs_path_group_entry *group = NULL;
897 if (!ccs_correct_word(group_name) || !ccs_correct_word(member_name))
899 saved_group_name = ccs_savename(group_name);
900 saved_member_name = ccs_savename(member_name);
901 if (!saved_group_name || !saved_member_name)
903 for (i = 0; i < ccs_path_group_list_len; i++) {
904 group = &ccs_path_group_list[i];
905 if (saved_group_name != group->group_name)
907 for (j = 0; j < group->member_name_len; j++) {
908 if (group->member_name[j] != saved_member_name)
912 while (j < group->member_name_len - 1)
913 group->member_name[j] =
914 group->member_name[j + 1];
915 group->member_name_len--;
922 if (i == ccs_path_group_list_len) {
923 ccs_path_group_list = realloc(ccs_path_group_list,
924 (ccs_path_group_list_len + 1) *
925 sizeof(struct ccs_path_group_entry));
926 if (!ccs_path_group_list)
928 group = &ccs_path_group_list[ccs_path_group_list_len++];
929 memset(group, 0, sizeof(struct ccs_path_group_entry));
930 group->group_name = saved_group_name;
932 group->member_name = realloc(group->member_name,
933 (group->member_name_len + 1)
934 * sizeof(const struct ccs_path_info *));
935 if (!group->member_name)
937 group->member_name[group->member_name_len++] = saved_member_name;
941 static void ccs_read_domain_and_exception_policy(struct ccs_domain_policy *dp)
948 static char **ccs_jump_list = NULL;
949 static int ccs_jump_list_len = 0;
950 while (ccs_jump_list_len)
951 free(ccs_jump_list[--ccs_jump_list_len]);
952 ccs_clear_domain_policy(dp);
953 ccs_transition_control_list_len = 0;
954 while (ccs_path_group_list_len)
955 free(ccs_path_group_list[--ccs_path_group_list_len].member_name);
957 while (ccs_address_group_list_len)
958 free(ccs_address_group_list[--ccs_address_group_list_len].member_name);
960 ccs_address_group_list_len = 0;
961 ccs_number_group_list_len = 0;
962 ccs_assign_domain(dp, CCS_ROOT_NAME, false, false);
964 /* Load all domain list. */
966 if (ccs_network_mode)
967 /* We can read after write. */
968 fp = ccs_editpolicy_open_write(ccs_policy_file);
969 else if (!ccs_offline_mode)
970 /* Don't set error message if failed. */
971 fp = fopen(ccs_policy_file, "r+");
973 fprintf(fp, "select execute\n");
974 if (ccs_network_mode)
979 fp = ccs_editpolicy_open_read(CCS_PROC_POLICY_DOMAIN_POLICY);
981 ccs_set_error(CCS_PROC_POLICY_DOMAIN_POLICY);
987 char *line = ccs_freadline(fp);
988 unsigned int profile;
991 if (ccs_domain_def(line)) {
992 index = ccs_assign_domain(dp, line, false, false);
994 } else if (index == EOF) {
997 if (ccs_str_starts(line, "task auto_execute_handler ") ||
998 ccs_str_starts(line, "task denied_execute_handler ") ||
999 ccs_str_starts(line, "file execute ")) {
1000 char *cp = strchr(line, ' ');
1003 if (*line == '@' || ccs_correct_path(line))
1004 ccs_add_string_entry(dp, line, index);
1005 } else if (ccs_str_starts(line,
1006 "task auto_domain_transition ") ||
1007 ccs_str_starts(line,
1008 "task manual_domain_transition ")) {
1009 static char domainname[4096];
1013 for (i = 0; line[i]; i++)
1014 if (line[i] == ' ' && line[i + 1] != '/') {
1018 if (!ccs_correct_domain(line))
1020 ccs_jump_list = realloc(ccs_jump_list,
1021 (ccs_jump_list_len + 1)
1024 ccs_out_of_memory();
1025 ccs_jump_list[ccs_jump_list_len] = strdup(line);
1026 if (!ccs_jump_list[ccs_jump_list_len])
1027 ccs_out_of_memory();
1028 ccs_jump_list_len++;
1029 m = strrchr(line, ' ');
1034 snprintf(domainname, sizeof(domainname) - 1, "%s %s",
1035 ccs_domain_name(dp, index), m);
1036 domainname[sizeof(domainname) - 1] = '\0';
1037 ccs_normalize_line(domainname);
1038 source = ccs_assign_domain(dp, domainname, true, false);
1040 ccs_out_of_memory();
1041 dp->list[source].target_domainname = strdup(line);
1042 if (!dp->list[source].target_domainname)
1043 ccs_out_of_memory();
1044 } else if (sscanf(line, "use_profile %u", &profile) == 1) {
1045 dp->list[index].profile = (u8) profile;
1046 dp->list[index].profile_assigned = 1;
1047 } else if (sscanf(line, "use_group %u", &profile) == 1) {
1048 dp->list[index].group = (u8) profile;
1055 max_index = dp->list_len;
1057 /* Load domain_initializer list, domain_keeper list. */
1058 fp = ccs_editpolicy_open_read(CCS_PROC_POLICY_EXCEPTION_POLICY);
1060 ccs_set_error(CCS_PROC_POLICY_EXCEPTION_POLICY);
1066 char *line = ccs_freadline(fp);
1069 if (ccs_str_starts(line, "initialize_domain "))
1070 ccs_add_transition_control_policy(line, CCS_TRANSITION_CONTROL_INITIALIZE);
1071 else if (ccs_str_starts(line, "no_initialize_domain "))
1072 ccs_add_transition_control_policy(line, CCS_TRANSITION_CONTROL_NO_INITIALIZE);
1073 else if (ccs_str_starts(line, "keep_domain "))
1074 ccs_add_transition_control_policy(line, CCS_TRANSITION_CONTROL_KEEP);
1075 else if (ccs_str_starts(line, "no_keep_domain "))
1076 ccs_add_transition_control_policy(line, CCS_TRANSITION_CONTROL_NO_KEEP);
1077 else if (ccs_str_starts(line, "path_group "))
1078 ccs_add_path_group_policy(line, false);
1079 else if (ccs_str_starts(line, "address_group "))
1080 ccs_add_address_group_policy(line, false);
1081 else if (ccs_str_starts(line, "number_group "))
1082 ccs_add_number_group_policy(line, false);
1083 else if (sscanf(line, "acl_group %u", &group) == 1
1085 char *cp = strchr(line + 10, ' ');
1088 if (ccs_str_starts(line,
1089 "task auto_execute_handler ") ||
1090 ccs_str_starts(line,
1091 "task denied_execute_handler ") ||
1092 ccs_str_starts(line, "file execute ")) {
1093 cp = strchr(line, ' ');
1096 if (*line == '@' || ccs_correct_path(line)) {
1097 for (index = 0; index < max_index;
1099 if (dp->list[index].group
1101 ccs_add_string_entry(dp, line, index);
1110 /* Find unreachable domains. */
1111 for (index = 0; index < max_index; index++) {
1114 line = ccs_shprintf("%s", ccs_domain_name(dp, index));
1116 const struct ccs_transition_control_entry *d_t;
1117 struct ccs_path_info parent;
1118 char *cp = strrchr(line, ' ');
1123 ccs_fill_path_info(&parent);
1124 d_t = ccs_transition_control(&parent, cp);
1127 /* Initializer under <kernel> is reachable. */
1128 if (d_t->type == CCS_TRANSITION_CONTROL_INITIALIZE &&
1129 parent.total_len == CCS_ROOT_NAME_LEN)
1131 dp->list[index].d_t = d_t;
1135 if (dp->list[index].d_t)
1136 dp->list[index].is_du = true;
1139 /* Find domain initializer target domains. */
1140 for (index = 0; index < max_index; index++) {
1141 char *cp = strchr(ccs_domain_name(dp, index), ' ');
1142 if (!cp || strchr(cp + 1, ' '))
1144 for (i = 0; i < ccs_transition_control_list_len; i++) {
1145 struct ccs_transition_control_entry *ptr
1146 = &ccs_transition_control_list[i];
1147 if (ptr->type != CCS_TRANSITION_CONTROL_INITIALIZE)
1149 if (ptr->program && strcmp(ptr->program->name, cp + 1))
1151 dp->list[index].is_dit = true;
1155 /* Find domain keeper domains. */
1156 for (index = 0; index < max_index; index++) {
1157 for (i = 0; i < ccs_transition_control_list_len; i++) {
1158 struct ccs_transition_control_entry *ptr
1159 = &ccs_transition_control_list[i];
1161 if (ptr->type != CCS_TRANSITION_CONTROL_KEEP)
1163 if (!ptr->is_last_name) {
1164 if (ptr->domainname &&
1165 ccs_pathcmp(ptr->domainname,
1166 dp->list[index].domainname))
1168 dp->list[index].is_dk = true;
1171 cp = strrchr(dp->list[index].domainname->name,
1173 if (!cp || (ptr->domainname->name &&
1174 strcmp(ptr->domainname->name, cp + 1)))
1176 dp->list[index].is_dk = true;
1180 /* Create domain initializer source domains. */
1181 for (index = 0; index < max_index; index++) {
1182 const struct ccs_path_info *domainname
1183 = dp->list[index].domainname;
1184 const struct ccs_path_info **string_ptr
1185 = dp->list[index].string_ptr;
1186 const int max_count = dp->list[index].string_count;
1187 /* Don't create source domain under <kernel> because
1188 they will become ccs_target domains. */
1189 if (domainname->total_len == CCS_ROOT_NAME_LEN)
1191 for (i = 0; i < max_count; i++) {
1192 const struct ccs_path_info *cp = string_ptr[i];
1193 struct ccs_path_group_entry *group;
1194 if (cp->name[0] != '@') {
1195 ccs_assign_dis(dp, domainname, cp->name);
1198 group = ccs_find_path_group(cp->name + 1);
1201 for (j = 0; j < group->member_name_len; j++) {
1202 cp = group->member_name[j];
1203 ccs_assign_dis(dp, domainname, cp->name);
1208 /* Create domain jump target domains. */
1209 for (i = 0; i < ccs_jump_list_len; i++) {
1210 int index = ccs_find_domain(dp, ccs_jump_list[i], false, false);
1212 dp->list[index].is_dit = true;
1215 //max_index = dp->list_len;
1217 /* Create missing parent domains. */
1218 for (index = 0; index < max_index; index++) {
1221 line = ccs_shprintf("%s", ccs_domain_name(dp, index));
1223 char *cp = strrchr(line, ' ');
1227 if (ccs_find_domain(dp, line, false, false) != EOF)
1229 if (ccs_assign_domain(dp, line, false, true) == EOF)
1230 ccs_out_of_memory();
1235 /* Sort by domain name. */
1236 qsort(dp->list, dp->list_len, sizeof(struct ccs_domain_info),
1237 ccs_domainname_attribute_compare);
1239 /* Assign domain numbers. */
1243 ccs_unnumbered_domain_count = 0;
1244 for (index = 0; index < dp->list_len; index++) {
1245 if (ccs_deleted_domain(dp, index) ||
1246 ccs_initializer_source(dp, index)) {
1247 dp->list[index].number = -1;
1248 ccs_unnumbered_domain_count++;
1250 dp->list[index].number = number++;
1255 dp->list_selected = realloc(dp->list_selected, dp->list_len);
1256 if (dp->list_len && !dp->list_selected)
1257 ccs_out_of_memory();
1258 memset(dp->list_selected, 0, dp->list_len);
1261 static int ccs_show_process_line(const int index)
1266 printw("%c%4d:%3u ", ccs_task_list[index].selected ? '&' : ' ', index,
1267 ccs_task_list[index].profile);
1269 for (i = 0; i < ccs_task_list[index].depth - 1; i++) {
1270 printw("%s", ccs_eat(" "));
1274 line = ccs_shprintf("%s%s (%u) %s", ccs_task_list[index].depth ?
1275 " +- " : "", ccs_task_list[index].name,
1276 ccs_task_list[index].pid, ccs_task_list[index].domain);
1277 printw("%s", ccs_eat(line));
1278 tmp_col += strlen(line);
1283 static void ccs_show_list(struct ccs_domain_policy *dp)
1285 const int offset = ccs_current_item_index[ccs_current_screen];
1288 if (ccs_current_screen == CCS_SCREEN_DOMAIN_LIST)
1289 ccs_list_item_count[CCS_SCREEN_DOMAIN_LIST] = ccs_domain_sort_type ?
1290 ccs_task_list_len : dp->list_len;
1292 ccs_list_item_count[ccs_current_screen] = ccs_generic_acl_list_count;
1295 if (ccs_window_height < CCS_HEADER_LINES + 1) {
1296 printw("Please enlarge window.");
1302 ccs_editpolicy_color_change(ccs_editpolicy_color_head(ccs_current_screen), true);
1303 if (ccs_current_screen == CCS_SCREEN_DOMAIN_LIST) {
1304 if (ccs_domain_sort_type) {
1305 printw("<<< Process State Viewer >>>"
1306 " %d process%s '?' for help",
1307 ccs_task_list_len, ccs_task_list_len > 1 ? "es" : "");
1309 int i = ccs_list_item_count[CCS_SCREEN_DOMAIN_LIST]
1310 - ccs_unnumbered_domain_count;
1311 printw("<<< Domain Transition Editor >>>"
1312 " %d domain%c '?' for help",
1313 i, i > 1 ? 's' : ' ');
1316 int i = ccs_list_item_count[ccs_current_screen];
1318 " %d entr%s '?' for help", ccs_list_caption,
1319 i, i > 1 ? "ies" : "y");
1322 ccs_editpolicy_color_change(ccs_editpolicy_color_head(ccs_current_screen), false);
1323 ccs_eat_col = ccs_max_eat_col[ccs_current_screen];
1325 if (ccs_current_screen == CCS_SCREEN_ACL_LIST) {
1328 line = ccs_shprintf("%s", ccs_eat(ccs_current_domain));
1329 ccs_editpolicy_attr_change(A_REVERSE, true); /* add color */
1332 ccs_editpolicy_attr_change(A_REVERSE, false); /* add color */
1335 ccs_list_indent = 0;
1336 switch (ccs_current_screen) {
1337 case CCS_SCREEN_EXCEPTION_LIST:
1338 case CCS_SCREEN_ACL_LIST:
1339 for (i = 0; i < ccs_list_item_count[ccs_current_screen]; i++) {
1340 const u16 directive = ccs_generic_acl_list[i].directive;
1341 const int len = ccs_directives[directive].alias_len;
1342 if (len > ccs_list_indent)
1343 ccs_list_indent = len;
1347 for (i = 0; i < ccs_body_lines; i++) {
1348 const int index = offset + i;
1349 ccs_eat_col = ccs_max_eat_col[ccs_current_screen];
1350 if (index >= ccs_list_item_count[ccs_current_screen])
1352 move(CCS_HEADER_LINES + i, 0);
1353 switch (ccs_current_screen) {
1354 case CCS_SCREEN_DOMAIN_LIST:
1355 if (!ccs_domain_sort_type)
1356 tmp_col = ccs_show_domain_line(dp, index);
1358 tmp_col = ccs_show_process_line(index);
1360 case CCS_SCREEN_EXCEPTION_LIST:
1361 case CCS_SCREEN_ACL_LIST:
1362 tmp_col = ccs_show_acl_line(index, ccs_list_indent);
1364 case CCS_SCREEN_PROFILE_LIST:
1365 tmp_col = ccs_show_profile_line(index);
1367 case CCS_SCREEN_MEMINFO_LIST:
1368 tmp_col = ccs_show_meminfo_line(index);
1371 tmp_col = ccs_show_literal_line(index);
1375 tmp_col -= ccs_window_width;
1376 if (tmp_col > ccs_max_col)
1377 ccs_max_col = tmp_col;
1379 ccs_show_current(dp);
1382 static void ccs_resize_window(void)
1384 getmaxyx(stdscr, ccs_window_height, ccs_window_width);
1385 ccs_body_lines = ccs_window_height - CCS_HEADER_LINES;
1386 if (ccs_body_lines <= ccs_current_y[ccs_current_screen])
1387 ccs_current_y[ccs_current_screen] = ccs_body_lines - 1;
1388 if (ccs_current_y[ccs_current_screen] < 0)
1389 ccs_current_y[ccs_current_screen] = 0;
1392 static void ccs_up_arrow_key(struct ccs_domain_policy *dp)
1394 if (ccs_current_y[ccs_current_screen] > 0) {
1395 ccs_current_y[ccs_current_screen]--;
1396 ccs_show_current(dp);
1397 } else if (ccs_current_item_index[ccs_current_screen] > 0) {
1398 ccs_current_item_index[ccs_current_screen]--;
1403 static void ccs_down_arrow_key(struct ccs_domain_policy *dp)
1405 if (ccs_current_y[ccs_current_screen] < ccs_body_lines - 1) {
1406 if (ccs_current_item_index[ccs_current_screen]
1407 + ccs_current_y[ccs_current_screen]
1408 < ccs_list_item_count[ccs_current_screen] - 1) {
1409 ccs_current_y[ccs_current_screen]++;
1410 ccs_show_current(dp);
1412 } else if (ccs_current_item_index[ccs_current_screen]
1413 + ccs_current_y[ccs_current_screen]
1414 < ccs_list_item_count[ccs_current_screen] - 1) {
1415 ccs_current_item_index[ccs_current_screen]++;
1420 static void ccs_page_up_key(struct ccs_domain_policy *dp)
1422 int p0 = ccs_current_item_index[ccs_current_screen];
1423 int p1 = ccs_current_y[ccs_current_screen];
1425 if (p0 + p1 > ccs_body_lines) {
1426 p0 -= ccs_body_lines;
1429 } else if (p0 + p1 > 0) {
1435 refresh = (ccs_current_item_index[ccs_current_screen] != p0);
1436 ccs_current_item_index[ccs_current_screen] = p0;
1437 ccs_current_y[ccs_current_screen] = p1;
1441 ccs_show_current(dp);
1444 static void ccs_page_down_key(struct ccs_domain_policy *dp)
1446 int ccs_count = ccs_list_item_count[ccs_current_screen] - 1;
1447 int p0 = ccs_current_item_index[ccs_current_screen];
1448 int p1 = ccs_current_y[ccs_current_screen];
1450 if (p0 + p1 + ccs_body_lines < ccs_count) {
1451 p0 += ccs_body_lines;
1452 } else if (p0 + p1 < ccs_count) {
1453 while (p0 + p1 < ccs_count) {
1454 if (p1 + 1 < ccs_body_lines)
1462 refresh = (ccs_current_item_index[ccs_current_screen] != p0);
1463 ccs_current_item_index[ccs_current_screen] = p0;
1464 ccs_current_y[ccs_current_screen] = p1;
1468 ccs_show_current(dp);
1471 int ccs_editpolicy_get_current(void)
1473 int ccs_count = ccs_list_item_count[ccs_current_screen];
1474 const int p0 = ccs_current_item_index[ccs_current_screen];
1475 const int p1 = ccs_current_y[ccs_current_screen];
1478 if (p0 + p1 < 0 || p0 + p1 >= ccs_count) {
1479 fprintf(stderr, "ERROR: ccs_current_item_index=%d ccs_current_y=%d\n",
1486 static void ccs_show_current(struct ccs_domain_policy *dp)
1488 if (ccs_current_screen == CCS_SCREEN_DOMAIN_LIST && !ccs_domain_sort_type) {
1490 const int index = ccs_editpolicy_get_current();
1492 ccs_eat_col = ccs_max_eat_col[ccs_current_screen];
1493 line = ccs_shprintf("%s", ccs_eat(ccs_domain_name(dp, index)));
1494 if (ccs_window_width < strlen(line))
1495 line[ccs_window_width] = '\0';
1498 ccs_editpolicy_attr_change(A_REVERSE, true); /* add color */
1500 ccs_editpolicy_attr_change(A_REVERSE, false); /* add color */
1503 move(CCS_HEADER_LINES + ccs_current_y[ccs_current_screen], 0);
1504 ccs_editpolicy_line_draw(ccs_current_screen); /* add color */
1508 static void ccs_adjust_cursor_pos(const int item_count)
1510 if (item_count == 0) {
1511 ccs_current_item_index[ccs_current_screen] = 0;
1512 ccs_current_y[ccs_current_screen] = 0;
1514 while (ccs_current_item_index[ccs_current_screen]
1515 + ccs_current_y[ccs_current_screen] >= item_count) {
1516 if (ccs_current_y[ccs_current_screen] > 0)
1517 ccs_current_y[ccs_current_screen]--;
1518 else if (ccs_current_item_index[ccs_current_screen] > 0)
1519 ccs_current_item_index[ccs_current_screen]--;
1524 static void ccs_set_cursor_pos(const int index)
1526 while (index < ccs_current_y[ccs_current_screen]
1527 + ccs_current_item_index[ccs_current_screen]) {
1528 if (ccs_current_y[ccs_current_screen] > 0)
1529 ccs_current_y[ccs_current_screen]--;
1531 ccs_current_item_index[ccs_current_screen]--;
1533 while (index > ccs_current_y[ccs_current_screen]
1534 + ccs_current_item_index[ccs_current_screen]) {
1535 if (ccs_current_y[ccs_current_screen] < ccs_body_lines - 1)
1536 ccs_current_y[ccs_current_screen]++;
1538 ccs_current_item_index[ccs_current_screen]++;
1542 static _Bool ccs_select_item(struct ccs_domain_policy *dp, const int index)
1548 if (ccs_current_screen == CCS_SCREEN_DOMAIN_LIST) {
1549 if (!ccs_domain_sort_type) {
1550 if (ccs_deleted_domain(dp, index) ||
1551 ccs_initializer_source(dp, index))
1553 dp->list_selected[index] ^= 1;
1555 ccs_task_list[index].selected ^= 1;
1558 ccs_generic_acl_list[index].selected ^= 1;
1560 getyx(stdscr, y, x);
1561 ccs_editpolicy_sttr_save(); /* add color */
1563 ccs_editpolicy_sttr_restore(); /* add color */
1568 static int ccs_generic_acl_compare(const void *a, const void *b)
1570 const struct ccs_generic_acl *a0 = (struct ccs_generic_acl *) a;
1571 const struct ccs_generic_acl *b0 = (struct ccs_generic_acl *) b;
1572 const char *a1 = ccs_directives[a0->directive].alias;
1573 const char *b1 = ccs_directives[b0->directive].alias;
1574 const char *a2 = a0->operand;
1575 const char *b2 = b0->operand;
1576 if (ccs_acl_sort_type == 0) {
1577 const int ret = strcmp(a1, b1);
1580 return strcmp(a2, b2);
1582 const int ret = strcmp(a2, b2);
1585 return strcmp(a1, b1);
1589 static void ccs_delete_entry(struct ccs_domain_policy *dp, const int index)
1594 ccs_editpolicy_color_change(CCS_DISP_ERR, true); /* add color */
1595 if (ccs_current_screen == CCS_SCREEN_DOMAIN_LIST) {
1596 c = ccs_count(dp->list_selected, dp->list_len);
1597 if (!c && index < dp->list_len)
1598 c = ccs_select_item(dp, index);
1600 printw("Select domain using Space key first.");
1602 printw("Delete selected domain%s? ('Y'es/'N'o)",
1605 c = ccs_count2(ccs_generic_acl_list, ccs_generic_acl_list_count);
1607 c = ccs_select_item(dp, index);
1609 printw("Select entry using Space key first.");
1611 printw("Delete selected entr%s? ('Y'es/'N'o)",
1612 c > 1 ? "ies" : "y");
1614 ccs_editpolicy_color_change(CCS_DISP_ERR, false); /* add color */
1621 } while (!(c == 'Y' || c == 'y' || c == 'N' || c == 'n' || c == EOF));
1622 ccs_resize_window();
1623 if (c != 'Y' && c != 'y') {
1628 if (ccs_current_screen == CCS_SCREEN_DOMAIN_LIST) {
1630 FILE *fp = ccs_editpolicy_open_write(CCS_PROC_POLICY_DOMAIN_POLICY);
1633 for (i = 1; i < dp->list_len; i++) {
1634 if (!dp->list_selected[i])
1636 fprintf(fp, "delete %s\n", ccs_domain_name(dp, i));
1638 ccs_close_write(fp);
1641 FILE *fp = ccs_editpolicy_open_write(ccs_policy_file);
1644 if (ccs_current_screen == CCS_SCREEN_ACL_LIST) {
1645 if (ccs_domain_sort_type)
1646 fprintf(fp, "select pid=%u\n", ccs_current_pid);
1648 fprintf(fp, "select domain=%s\n",
1649 ccs_current_domain);
1651 for (i = 0; i < ccs_generic_acl_list_count; i++) {
1653 if (!ccs_generic_acl_list[i].selected)
1655 directive = ccs_generic_acl_list[i].directive;
1656 fprintf(fp, "delete %s %s\n",
1657 ccs_directives[directive].original,
1658 ccs_generic_acl_list[i].operand);
1660 ccs_close_write(fp);
1664 static void ccs_add_entry(struct ccs_readline_data *rl)
1669 ccs_editpolicy_attr_change(A_BOLD, true); /* add color */
1670 line = ccs_readline(ccs_window_height - 1, 0, "Enter new entry> ",
1671 rl->history, rl->count, 128000, 8);
1672 ccs_editpolicy_attr_change(A_BOLD, false); /* add color */
1673 if (!line || !*line)
1675 rl->count = ccs_add_history(line, rl->history, rl->count, rl->max);
1679 fp = ccs_editpolicy_open_write(ccs_policy_file);
1682 switch (ccs_current_screen) {
1684 case CCS_SCREEN_DOMAIN_LIST:
1685 if (!ccs_correct_domain(line)) {
1686 const int len = strlen(line) + 128;
1687 ccs_last_error = realloc(ccs_last_error, len);
1688 if (!ccs_last_error)
1689 ccs_out_of_memory();
1690 memset(ccs_last_error, 0, len);
1691 snprintf(ccs_last_error, len - 1,
1692 "%s is an invalid domainname.", line);
1696 case CCS_SCREEN_ACL_LIST:
1697 if (ccs_domain_sort_type)
1698 fprintf(fp, "select pid=%u\n", ccs_current_pid);
1700 fprintf(fp, "select domain=%s\n", ccs_current_domain);
1702 case CCS_SCREEN_EXCEPTION_LIST:
1703 directive = ccs_find_directive(false, line);
1704 if (directive != CCS_DIRECTIVE_NONE)
1706 ccs_directives[directive].original);
1708 case CCS_SCREEN_PROFILE_LIST:
1709 if (!strchr(line, '='))
1710 fprintf(fp, "%s-COMMENT=\n", line);
1713 fprintf(fp, "%s\n", line);
1714 ccs_close_write(fp);
1719 static void ccs_find_entry(struct ccs_domain_policy *dp, _Bool input, _Bool forward,
1720 const int current, struct ccs_readline_data *rl)
1722 int index = current;
1728 ccs_editpolicy_attr_change(A_BOLD, true); /* add color */
1729 line = ccs_readline(ccs_window_height - 1, 0, "Search> ",
1730 rl->history, rl->count, 128000, 8);
1731 ccs_editpolicy_attr_change(A_BOLD, false); /* add color */
1732 if (!line || !*line)
1734 rl->count = ccs_add_history(line, rl->history, rl->count, rl->max);
1735 free(rl->search_buffer[ccs_current_screen]);
1736 rl->search_buffer[ccs_current_screen] = line;
1744 if (++index >= ccs_list_item_count[ccs_current_screen])
1750 if (ccs_current_screen == CCS_SCREEN_DOMAIN_LIST) {
1751 if (ccs_domain_sort_type)
1752 cp = ccs_task_list[index].name;
1754 cp = ccs_get_last_name(dp, index);
1755 } else if (ccs_current_screen == CCS_SCREEN_PROFILE_LIST) {
1756 cp = ccs_shprintf("%u-%s",
1757 ccs_generic_acl_list[index].directive,
1758 ccs_generic_acl_list[index].operand);
1760 const u16 directive = ccs_generic_acl_list[index].directive;
1761 cp = ccs_shprintf("%s %s", ccs_directives[directive].alias,
1762 ccs_generic_acl_list[index].operand);
1764 if (!strstr(cp, rl->search_buffer[ccs_current_screen]))
1766 ccs_set_cursor_pos(index);
1775 static void ccs_set_profile(struct ccs_domain_policy *dp, const int current)
1781 if (!ccs_domain_sort_type) {
1782 if (!ccs_count(dp->list_selected, dp->list_len) &&
1783 !ccs_select_item(dp, current)) {
1785 printw("Select domain using Space key first.");
1791 if (!ccs_count3(ccs_task_list, ccs_task_list_len) &&
1792 !ccs_select_item(dp, current)) {
1794 printw("Select processes using Space key first.");
1800 ccs_editpolicy_attr_change(A_BOLD, true); /* add color */
1801 line = ccs_readline(ccs_window_height - 1, 0, "Enter profile number> ",
1803 ccs_editpolicy_attr_change(A_BOLD, false); /* add color */
1807 if (!line || !*line)
1809 fp = ccs_editpolicy_open_write(CCS_PROC_POLICY_DOMAIN_POLICY);
1812 if (!ccs_domain_sort_type) {
1813 for (index = 0; index < dp->list_len; index++) {
1814 if (!dp->list_selected[index])
1816 fprintf(fp, "select domain=%s\n" "use_profile %s\n",
1817 ccs_domain_name(dp, index), line);
1820 for (index = 0; index < ccs_task_list_len; index++) {
1821 if (!ccs_task_list[index].selected)
1823 fprintf(fp, "select pid=%u\n" "use_profile %s\n",
1824 ccs_task_list[index].pid, line);
1827 ccs_close_write(fp);
1832 static void ccs_set_level(struct ccs_domain_policy *dp, const int current)
1838 if (!ccs_count2(ccs_generic_acl_list, ccs_generic_acl_list_count))
1839 ccs_select_item(dp, current);
1840 ccs_editpolicy_attr_change(A_BOLD, true); /* add color */
1841 ccs_initial_readline_data = NULL;
1842 for (index = 0; index < ccs_generic_acl_list_count; index++) {
1844 if (!ccs_generic_acl_list[index].selected)
1846 cp = strchr(ccs_generic_acl_list[index].operand, '=');
1849 ccs_initial_readline_data = cp + 1;
1852 line = ccs_readline(ccs_window_height - 1, 0, "Enter new value> ",
1853 NULL, 0, 128000, 1);
1854 ccs_initial_readline_data = NULL;
1855 ccs_editpolicy_attr_change(A_BOLD, false); /* add color */
1859 if (!line || !*line)
1861 fp = ccs_editpolicy_open_write(CCS_PROC_POLICY_PROFILE);
1864 for (index = 0; index < ccs_generic_acl_list_count; index++) {
1868 if (!ccs_generic_acl_list[index].selected)
1871 buf = ccs_shprintf("%s", ccs_generic_acl_list[index].operand);
1872 cp = strchr(buf, '=');
1875 directive = ccs_generic_acl_list[index].directive;
1876 if (directive < 256)
1877 fprintf(fp, "%u-", directive);
1878 fprintf(fp, "%s=%s\n", buf, line);
1881 ccs_close_write(fp);
1886 static void ccs_set_quota(struct ccs_domain_policy *dp, const int current)
1892 if (!ccs_count2(ccs_generic_acl_list, ccs_generic_acl_list_count))
1893 ccs_select_item(dp, current);
1894 ccs_editpolicy_attr_change(A_BOLD, true); /* add color */
1895 line = ccs_readline(ccs_window_height - 1, 0, "Enter new value> ",
1897 ccs_editpolicy_attr_change(A_BOLD, false); /* add color */
1901 if (!line || !*line)
1903 fp = ccs_editpolicy_open_write(CCS_PROC_POLICY_MEMINFO);
1906 for (index = 0; index < ccs_generic_acl_list_count; index++) {
1909 if (!ccs_generic_acl_list[index].selected)
1912 buf = ccs_shprintf("%s", ccs_generic_acl_list[index].operand);
1913 cp = strchr(buf, ':');
1916 fprintf(fp, "%s: %s\n", buf, line);
1919 ccs_close_write(fp);
1924 static _Bool ccs_select_acl_window(struct ccs_domain_policy *dp, const int current,
1925 const _Bool may_refresh)
1927 if (ccs_current_screen != CCS_SCREEN_DOMAIN_LIST || current == EOF)
1929 ccs_current_pid = 0;
1930 if (ccs_domain_sort_type) {
1931 ccs_current_pid = ccs_task_list[current].pid;
1932 } else if (ccs_initializer_source(dp, current)) {
1936 redirect_index = ccs_find_target_domain(dp, current);
1937 if (redirect_index == EOF)
1939 ccs_current_item_index[ccs_current_screen]
1940 = redirect_index - ccs_current_y[ccs_current_screen];
1941 while (ccs_current_item_index[ccs_current_screen] < 0) {
1942 ccs_current_item_index[ccs_current_screen]++;
1943 ccs_current_y[ccs_current_screen]--;
1947 } else if (ccs_deleted_domain(dp, current)) {
1950 free(ccs_current_domain);
1951 if (ccs_domain_sort_type)
1952 ccs_current_domain = strdup(ccs_task_list[current].domain);
1954 ccs_current_domain = strdup(ccs_domain_name(dp, current));
1955 if (!ccs_current_domain)
1956 ccs_out_of_memory();
1960 static int ccs_select_window(struct ccs_domain_policy *dp, const int current)
1963 printw("Press one of below keys to switch window.\n\n");
1964 printw("e <<< Exception Policy Editor >>>\n");
1965 printw("d <<< Domain Transition Editor >>>\n");
1966 if (ccs_current_screen == CCS_SCREEN_DOMAIN_LIST && current != EOF &&
1967 !ccs_initializer_source(dp, current) &&
1968 !ccs_deleted_domain(dp, current))
1969 printw("a <<< Domain Policy Editor >>>\n");
1970 printw("p <<< Profile Editor >>>\n");
1971 printw("m <<< Manager Policy Editor >>>\n");
1972 if (!ccs_offline_mode) {
1973 /* printw("i <<< Interactive Enforcing Mode >>>\n"); */
1974 printw("u <<< Memory Usage >>>\n");
1976 printw("q Quit this editor.\n");
1980 int c = ccs_getch2();
1981 if (c == 'E' || c == 'e')
1982 return CCS_SCREEN_EXCEPTION_LIST;
1983 if (c == 'D' || c == 'd')
1984 return CCS_SCREEN_DOMAIN_LIST;
1985 if (c == 'A' || c == 'a')
1986 if (ccs_select_acl_window(dp, current, false))
1987 return CCS_SCREEN_ACL_LIST;
1988 if (c == 'P' || c == 'p')
1989 return CCS_SCREEN_PROFILE_LIST;
1990 if (c == 'M' || c == 'm')
1991 return CCS_SCREEN_MANAGER_LIST;
1992 if (!ccs_offline_mode) {
1994 if (c == 'I' || c == 'i')
1995 return CCS_SCREEN_QUERY_LIST;
1997 if (c == 'U' || c == 'u')
1998 return CCS_SCREEN_MEMINFO_LIST;
2000 if (c == 'Q' || c == 'q')
2001 return CCS_MAXSCREEN;
2003 return CCS_MAXSCREEN;
2007 static void ccs_copy_mark_state(struct ccs_domain_policy *dp, const int current)
2010 if (ccs_current_screen == CCS_SCREEN_DOMAIN_LIST) {
2011 if (ccs_domain_sort_type) {
2012 const u8 selected = ccs_task_list[current].selected;
2013 for (index = current; index < ccs_task_list_len; index++)
2014 ccs_task_list[index].selected = selected;
2016 const u8 selected = dp->list_selected[current];
2017 if (ccs_deleted_domain(dp, current) ||
2018 ccs_initializer_source(dp, current))
2020 for (index = current;
2021 index < dp->list_len; index++) {
2022 if (ccs_deleted_domain(dp, index) ||
2023 ccs_initializer_source(dp, index))
2025 dp->list_selected[index] = selected;
2029 const u8 selected = ccs_generic_acl_list[current].selected;
2030 for (index = current; index < ccs_generic_acl_list_count; index++)
2031 ccs_generic_acl_list[index].selected = selected;
2036 static void ccs_copy_to_history(struct ccs_domain_policy *dp, const int current,
2037 struct ccs_readline_data *rl)
2043 switch (ccs_current_screen) {
2045 case CCS_SCREEN_DOMAIN_LIST:
2046 line = ccs_domain_name(dp, current);
2048 case CCS_SCREEN_EXCEPTION_LIST:
2049 case CCS_SCREEN_ACL_LIST:
2050 directive = ccs_generic_acl_list[current].directive;
2051 line = ccs_shprintf("%s %s", ccs_directives[directive].alias,
2052 ccs_generic_acl_list[current].operand);
2054 case CCS_SCREEN_MEMINFO_LIST:
2058 line = ccs_shprintf("%s", ccs_generic_acl_list[current].operand);
2060 rl->count = ccs_add_history(line, rl->history, rl->count, rl->max);
2064 static int ccs_generic_list_loop(struct ccs_domain_policy *dp)
2066 static struct ccs_readline_data rl;
2067 static int saved_current_y[CCS_MAXSCREEN];
2068 static int saved_current_item_index[CCS_MAXSCREEN];
2069 static _Bool first = true;
2071 memset(&rl, 0, sizeof(rl));
2073 rl.history = malloc(rl.max * sizeof(const char *));
2074 memset(saved_current_y, 0, sizeof(saved_current_y));
2075 memset(saved_current_item_index, 0,
2076 sizeof(saved_current_item_index));
2079 if (ccs_current_screen == CCS_SCREEN_EXCEPTION_LIST) {
2080 ccs_policy_file = CCS_PROC_POLICY_EXCEPTION_POLICY;
2081 ccs_list_caption = "Exception Policy Editor";
2082 } else if (ccs_current_screen == CCS_SCREEN_ACL_LIST) {
2083 ccs_policy_file = CCS_PROC_POLICY_DOMAIN_POLICY;
2084 ccs_list_caption = "Domain Policy Editor";
2085 } else if (ccs_current_screen == CCS_SCREEN_QUERY_LIST) {
2086 ccs_policy_file = CCS_PROC_POLICY_QUERY;
2087 ccs_list_caption = "Interactive Enforcing Mode";
2088 } else if (ccs_current_screen == CCS_SCREEN_PROFILE_LIST) {
2089 ccs_policy_file = CCS_PROC_POLICY_PROFILE;
2090 ccs_list_caption = "Profile Editor";
2091 } else if (ccs_current_screen == CCS_SCREEN_MANAGER_LIST) {
2092 ccs_policy_file = CCS_PROC_POLICY_MANAGER;
2093 ccs_list_caption = "Manager Policy Editor";
2094 } else if (ccs_current_screen == CCS_SCREEN_MEMINFO_LIST) {
2095 ccs_policy_file = CCS_PROC_POLICY_MEMINFO;
2096 ccs_list_caption = "Memory Usage";
2098 ccs_policy_file = CCS_PROC_POLICY_DOMAIN_POLICY;
2099 /* ccs_list_caption = "Domain Transition Editor"; */
2101 ccs_current_item_index[ccs_current_screen]
2102 = saved_current_item_index[ccs_current_screen];
2103 ccs_current_y[ccs_current_screen] = saved_current_y[ccs_current_screen];
2105 if (ccs_current_screen == CCS_SCREEN_DOMAIN_LIST) {
2106 if (ccs_domain_sort_type == 0) {
2107 ccs_read_domain_and_exception_policy(dp);
2108 ccs_adjust_cursor_pos(dp->list_len);
2110 ccs_read_process_list(true);
2111 ccs_adjust_cursor_pos(ccs_task_list_len);
2114 ccs_read_generic_policy();
2115 ccs_adjust_cursor_pos(ccs_generic_acl_list_count);
2122 if (ccs_last_error) {
2124 printw("ERROR: %s", ccs_last_error);
2127 free(ccs_last_error);
2128 ccs_last_error = NULL;
2131 const int current = ccs_editpolicy_get_current();
2132 const int c = ccs_getch2();
2133 saved_current_item_index[ccs_current_screen]
2134 = ccs_current_item_index[ccs_current_screen];
2135 saved_current_y[ccs_current_screen] = ccs_current_y[ccs_current_screen];
2136 if (c == 'q' || c == 'Q')
2137 return CCS_MAXSCREEN;
2138 if ((c == '\r' || c == '\n') &&
2139 ccs_current_screen == CCS_SCREEN_ACL_LIST)
2140 return CCS_SCREEN_DOMAIN_LIST;
2142 if (ccs_current_screen == CCS_SCREEN_DOMAIN_LIST)
2143 return CCS_SCREEN_EXCEPTION_LIST;
2145 return CCS_SCREEN_DOMAIN_LIST;
2147 if (ccs_need_reload) {
2148 ccs_need_reload = false;
2152 continue; /* Ignore invalid key. */
2155 ccs_resize_window();
2159 ccs_up_arrow_key(dp);
2162 ccs_down_arrow_key(dp);
2165 ccs_page_up_key(dp);
2168 ccs_page_down_key(dp);
2171 ccs_select_item(dp, current);
2177 ccs_copy_mark_state(dp, current);
2182 if (ccs_current_screen != CCS_SCREEN_MEMINFO_LIST)
2183 ccs_find_entry(dp, true, true, current, &rl);
2187 if (ccs_current_screen == CCS_SCREEN_MEMINFO_LIST)
2189 if (!rl.search_buffer[ccs_current_screen])
2190 ccs_find_entry(dp, true, false, current, &rl);
2192 ccs_find_entry(dp, false, false, current, &rl);
2196 if (ccs_current_screen == CCS_SCREEN_MEMINFO_LIST)
2198 if (!rl.search_buffer[ccs_current_screen])
2199 ccs_find_entry(dp, true, true, current, &rl);
2201 ccs_find_entry(dp, false, true, current, &rl);
2205 if (ccs_readonly_mode)
2207 switch (ccs_current_screen) {
2208 case CCS_SCREEN_DOMAIN_LIST:
2209 if (ccs_domain_sort_type)
2211 case CCS_SCREEN_EXCEPTION_LIST:
2212 case CCS_SCREEN_ACL_LIST:
2213 case CCS_SCREEN_MANAGER_LIST:
2214 ccs_delete_entry(dp, current);
2220 if (ccs_readonly_mode)
2222 switch (ccs_current_screen) {
2223 case CCS_SCREEN_DOMAIN_LIST:
2224 if (ccs_domain_sort_type)
2226 case CCS_SCREEN_EXCEPTION_LIST:
2227 case CCS_SCREEN_ACL_LIST:
2228 case CCS_SCREEN_PROFILE_LIST:
2229 case CCS_SCREEN_MANAGER_LIST:
2236 if (ccs_select_acl_window(dp, current, true))
2237 return CCS_SCREEN_ACL_LIST;
2241 if (ccs_readonly_mode)
2243 switch (ccs_current_screen) {
2244 case CCS_SCREEN_DOMAIN_LIST:
2245 ccs_set_profile(dp, current);
2247 case CCS_SCREEN_PROFILE_LIST:
2248 ccs_set_level(dp, current);
2250 case CCS_SCREEN_MEMINFO_LIST:
2251 ccs_set_quota(dp, current);
2259 if (!ccs_max_eat_col[ccs_current_screen])
2261 ccs_max_eat_col[ccs_current_screen]--;
2264 ccs_max_eat_col[ccs_current_screen]++;
2267 ccs_max_eat_col[ccs_current_screen] = 0;
2270 ccs_max_eat_col[ccs_current_screen] = ccs_max_col;
2273 ccs_copy_to_history(dp, current, &rl);
2277 if (ccs_current_screen == CCS_SCREEN_ACL_LIST) {
2278 ccs_editpolicy_try_optimize(dp, current,
2279 ccs_current_screen);
2284 if (ccs_current_screen == CCS_SCREEN_ACL_LIST) {
2285 ccs_acl_sort_type = (ccs_acl_sort_type + 1) % 2;
2287 } else if (ccs_current_screen == CCS_SCREEN_PROFILE_LIST) {
2288 ccs_profile_sort_type = (ccs_profile_sort_type + 1) % 2;
2290 } else if (ccs_current_screen == CCS_SCREEN_DOMAIN_LIST &&
2291 !ccs_offline_mode) {
2292 ccs_domain_sort_type = (ccs_domain_sort_type + 1) % 2;
2298 return ccs_select_window(dp, current);
2300 if (ccs_show_command_key(ccs_current_screen, ccs_readonly_mode))
2302 return CCS_MAXSCREEN;
2308 static _Bool ccs_save_to_file(const char *src, const char *dest)
2310 FILE *proc_fp = ccs_editpolicy_open_read(src);
2311 FILE *file_fp = fopen(dest, "w");
2313 fprintf(stderr, "Can't open %s\n", dest);
2318 int c = fgetc(proc_fp);
2328 #ifdef __GPET /* gpet */
2329 int gpet_main(void);
2330 int ccs_main(int argc, char *argv[])
2332 int main(int argc, char *argv[])
2335 struct ccs_domain_policy dp = { NULL, 0, NULL };
2336 struct ccs_domain_policy bp = { NULL, 0, NULL };
2337 memset(ccs_current_y, 0, sizeof(ccs_current_y));
2338 memset(ccs_current_item_index, 0, sizeof(ccs_current_item_index));
2339 memset(ccs_list_item_count, 0, sizeof(ccs_list_item_count));
2340 memset(ccs_max_eat_col, 0, sizeof(ccs_max_eat_col));
2343 for (i = 1; i < argc; i++) {
2344 char *ptr = argv[i];
2345 char *cp = strchr(ptr, ':');
2347 if (ccs_network_mode || ccs_offline_mode)
2349 ccs_policy_dir = ptr;
2350 ccs_offline_mode = true;
2353 if (ccs_network_mode || ccs_offline_mode)
2355 ccs_network_ip = inet_addr(ptr);
2356 ccs_network_port = htons(atoi(cp));
2357 ccs_network_mode = true;
2358 if (!ccs_check_remote_host())
2360 } else if (!strcmp(ptr, "e"))
2361 ccs_current_screen = CCS_SCREEN_EXCEPTION_LIST;
2362 else if (!strcmp(ptr, "d"))
2363 ccs_current_screen = CCS_SCREEN_DOMAIN_LIST;
2364 else if (!strcmp(ptr, "p"))
2365 ccs_current_screen = CCS_SCREEN_PROFILE_LIST;
2366 else if (!strcmp(ptr, "m"))
2367 ccs_current_screen = CCS_SCREEN_MANAGER_LIST;
2368 else if (!strcmp(ptr, "u"))
2369 ccs_current_screen = CCS_SCREEN_MEMINFO_LIST;
2370 else if (!strcmp(ptr, "readonly"))
2371 ccs_readonly_mode = true;
2372 else if (sscanf(ptr, "refresh=%u", &ccs_refresh_interval)
2375 printf("Usage: %s [e|d|p|m|u] [readonly] "
2376 "[refresh=interval] "
2377 "[{policy_dir|remote_ip:remote_port}]\n",
2383 ccs_editpolicy_init_keyword_map();
2384 if (ccs_offline_mode) {
2385 int fd[2] = { EOF, EOF };
2386 if (chdir(ccs_policy_dir)) {
2387 printf("Directory %s doesn't exist.\n",
2391 if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd)) {
2392 fprintf(stderr, "socketpair()\n");
2398 ccs_persistent_fd = fd[1];
2399 ccs_editpolicy_offline_daemon();
2402 fprintf(stderr, "fork()\n");
2406 ccs_persistent_fd = fd[0];
2407 ccs_copy_file(CCS_DISK_POLICY_EXCEPTION_POLICY,
2408 CCS_PROC_POLICY_EXCEPTION_POLICY);
2409 ccs_copy_file(CCS_DISK_POLICY_DOMAIN_POLICY, CCS_PROC_POLICY_DOMAIN_POLICY);
2410 ccs_copy_file(CCS_DISK_POLICY_PROFILE, CCS_PROC_POLICY_PROFILE);
2411 ccs_copy_file(CCS_DISK_POLICY_MANAGER, CCS_PROC_POLICY_MANAGER);
2412 } else if (!ccs_network_mode) {
2413 if (chdir(CCS_PROC_POLICY_DIR)) {
2415 "You can't use this editor for this kernel.\n");
2418 if (!ccs_readonly_mode) {
2419 const int fd1 = ccs_open2(CCS_PROC_POLICY_EXCEPTION_POLICY,
2421 const int fd2 = ccs_open2(CCS_PROC_POLICY_DOMAIN_POLICY,
2423 if ((fd1 != EOF && write(fd1, "", 0) != 0) ||
2424 (fd2 != EOF && write(fd2, "", 0) != 0)) {
2426 "You need to register this program to "
2427 "%s to run this program.\n",
2428 CCS_PROC_POLICY_MANAGER);
2440 ccs_editpolicy_color_init();
2444 intrflush(stdscr, FALSE);
2445 keypad(stdscr, TRUE);
2446 getmaxyx(stdscr, ccs_window_height, ccs_window_width);
2447 if (ccs_refresh_interval) {
2448 signal(SIGALRM, ccs_sigalrm_handler);
2449 alarm(ccs_refresh_interval);
2452 while (ccs_current_screen < CCS_MAXSCREEN) {
2453 ccs_resize_window();
2454 ccs_current_screen = ccs_generic_list_loop(&dp);
2462 if (ccs_offline_mode && !ccs_readonly_mode) {
2464 time_t now = time(NULL);
2465 const char *filename = ccs_make_filename("exception_policy",
2467 if (ccs_save_to_file(CCS_PROC_POLICY_EXCEPTION_POLICY,
2469 if (ccs_identical_file("exception_policy.conf",
2473 unlink("exception_policy.conf");
2474 ret_ignored = symlink(filename,
2475 "exception_policy.conf");
2478 ccs_clear_domain_policy(&dp);
2479 filename = ccs_make_filename("domain_policy", now);
2480 if (ccs_save_to_file(CCS_PROC_POLICY_DOMAIN_POLICY,
2482 if (ccs_identical_file("domain_policy.conf",
2486 unlink("domain_policy.conf");
2487 ret_ignored = symlink(filename,
2488 "domain_policy.conf");
2491 filename = ccs_make_filename("profile", now);
2492 if (ccs_save_to_file(CCS_PROC_POLICY_PROFILE, filename)) {
2493 if (ccs_identical_file("profile.conf", filename)) {
2496 unlink("profile.conf");
2497 ret_ignored = symlink(filename,
2501 filename = ccs_make_filename("manager", now);
2502 if (ccs_save_to_file(CCS_PROC_POLICY_MANAGER, filename)) {
2503 if (ccs_identical_file("manager.conf", filename)) {
2506 unlink("manager.conf");
2507 ret_ignored = symlink(filename,
2512 ccs_clear_domain_policy(&bp);
2513 ccs_clear_domain_policy(&dp);
2518 #include "../interface.inc"