static int drop_root(void) { struct passwd *pw; struct group * gr; int r; //Edison modify username 20131023 char dut_user[128]; memset(dut_user, 0, 128); strncpy(dut_user, nvram_safe_get("http_username"), 128); if (!(pw = getpwnam(dut_user))) { avahi_log_error( "Failed to find user '%s'.",dut_user); return -1; } if (!(gr = getgrnam(AVAHI_GROUP))) { avahi_log_error( "Failed to find group '"AVAHI_GROUP"'."); return -1; } avahi_log_info("Found user '%s' (UID %lu) and group '"AVAHI_GROUP"' (GID %lu).",dut_user ,(unsigned long) pw->pw_uid, (unsigned long) gr->gr_gid); if (initgroups(dut_user, gr->gr_gid) != 0) { avahi_log_error("Failed to change group list: %s", strerror(errno)); return -1; } #if defined(HAVE_SETRESGID) r = setresgid(gr->gr_gid, gr->gr_gid, gr->gr_gid); #elif defined(HAVE_SETEGID) if ((r = setgid(gr->gr_gid)) >= 0) r = setegid(gr->gr_gid); #elif defined(HAVE_SETREGID) r = setregid(gr->gr_gid, gr->gr_gid); #else #error "No API to drop privileges" #endif if (r < 0) { avahi_log_error("Failed to change GID: %s", strerror(errno)); return -1; } #if defined(HAVE_SETRESUID) r = setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid); #elif defined(HAVE_SETEUID) if ((r = setuid(pw->pw_uid)) >= 0) r = seteuid(pw->pw_uid); #elif defined(HAVE_SETREUID) r = setreuid(pw->pw_uid, pw->pw_uid); #else #error "No API to drop privileges" #endif if (r < 0) { avahi_log_error("Failed to change UID: %s", strerror(errno)); return -1; } set_env("USER", pw->pw_name); set_env("LOGNAME", pw->pw_name); set_env("HOME", pw->pw_dir); avahi_log_info("Successfully dropped root privileges."); return 0; }
int main(int ac, char **av) { int lc; char *msg; struct stat buf, buf1; pid_t pid, pid1; struct passwd *ltpuser1; struct passwd *ltpuser2; int rval, status; /* * parse standard options */ if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) { tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg); } /* * perform global setup for test */ setup(); /* * check looping state if -i option given */ for (lc = 0; TEST_LOOPING(lc); lc++) { tst_count = 0; /* check the inherited group ID */ /* * first, fork the first child, set to ltpuser1's uid and gid, * create a directory, with S_ISGID bit set */ ltpuser1 = my_getpwnam(user1name); sprintf(tstdir1, "tstdir1.%d", getpid()); if ((pid = FORK_OR_VFORK()) < 0) { tst_brkm(TFAIL, cleanup, "fork() failed"); } if (pid == 0) { /* first child */ rval = setregid(ltpuser1->pw_gid, ltpuser1->pw_gid); if (rval < 0) { perror("setregid"); tst_resm(TFAIL, "setregid failed to " "to set the real gid to %d and " "effective gid to %d", ltpuser1->pw_gid, ltpuser1->pw_gid); exit(1); } /* being ltupuser1 */ rval = setreuid(ltpuser1->pw_uid, ltpuser1->pw_uid); if (rval < 0) { perror("setreuid"); tst_resm(TFAIL, "setreuid failed to " "to set the real uid to %d and " "effective uid to %d", ltpuser1->pw_uid, ltpuser1->pw_uid); exit(1); } /* * create a direcoty with S_ISGID bit set * and the group ID is ltpuser1 */ if (mkdir(tstdir1, PERMS) != 0) { perror("mkdir"); tst_resm(TFAIL, "mkdir() failed to create" " a directory with Set " " group ID turn on "); exit(1); } if (stat(tstdir1, &buf1) == -1) { perror("stat"); tst_resm(TFAIL, "failed to stat the new directory" "in mkdir()"); exit(1); } if (chmod(tstdir1, buf1.st_mode | S_ISGID) != 0) { perror("chmod"); tst_resm(TFAIL, "failed to set S_ISGID bit"); exit(1); } /* Successfully create the parent directory */ exit(0); } wait(&status); if (WEXITSTATUS(status) != 0) { tst_brkm(TFAIL, cleanup, "Test to attempt to make a directory" " inherits group ID FAILED "); } /* * fork the second child process, set to ltpuser2's uid and gid * create a sub directory under the directory * just created by child process 1 * check the group ID of the sub directory * should inherit from parent directory */ ltpuser2 = my_getpwnam(user2name); sprintf(tstdir2, "%s/tstdir2.%d", tstdir1, getpid()); if ((pid1 = FORK_OR_VFORK()) < 0) { perror("fork failed"); tst_brkm(TFAIL, cleanup, "fork() failed"); } else if (pid1 == 0) { /* second child */ /* being user ltpuser2 */ rval = setregid(ltpuser2->pw_gid, ltpuser2->pw_gid); if (rval < 0) { tst_resm(TFAIL, "setregid failed to " "to set the real gid to %d and " "effective gid to %d", ltpuser2->pw_gid, ltpuser2->pw_gid); perror("setregid"); exit(1); } rval = setreuid(ltpuser2->pw_uid, ltpuser2->pw_uid); if (rval < 0) { tst_resm(TFAIL, "setreuid failed to " "to set the real uid to %d and " "effective uid to %d", ltpuser2->pw_uid, ltpuser2->pw_uid); perror("setreuid"); exit(1); } /* * create a sub direcoty * under the directory just created * by ltpuser1 */ if (mkdir(tstdir2, PERMS) != 0) { tst_resm(TFAIL, "mkdir() failed to create" " a directory %s under %s ", tstdir2, tstdir1); exit(1); } /* * check the group ID * should not be the same as the current processs's * since parent directory is set with S_ISGID bit */ if (stat(tstdir2, &buf) == -1) { tst_resm(TFAIL, "failed to stat the new directory" "in mkdir()"); exit(1); } if (stat(tstdir1, &buf1) == -1) { tst_resm(TFAIL, "failed to stat the new directory" "in mkdir()"); exit(1); } if (buf.st_gid != buf1.st_gid) { tst_resm(TFAIL, "mkdir() FAILED to inherit " " the group ID %d from parent " " directory %d", buf.st_gid, buf1.st_gid); exit(1); } /* check the S_ISGID bit */ if (!(buf.st_mode & S_ISGID)) { tst_resm(TFAIL, "mkdir() FAILED to inherit " " the S_ISGID bit from parent " " directory"); exit(1); } /* PASS */ exit(0); } waitpid(pid1, &status, 0); if (WEXITSTATUS(status) == 0) { tst_resm(TPASS, "Test to attempt to make a directory" " inherits group ID SUCCEEDED "); } else { tst_resm(TFAIL, "Test to attempt to make a directory" " inherits group ID FAILED"); cleanup(); } } /* * cleanup and exit */ cleanup(); tst_exit(); }
static int change_user(void) { struct passwd *pw; struct group * gr; int r; /* This function is called only in system-wide mode. It creates a * runtime dir in /var/run/ with proper UID/GID and drops privs * afterwards. */ if (!(pw = getpwnam(PA_SYSTEM_USER))) { pa_log(_("Failed to find user '%s'."), PA_SYSTEM_USER); return -1; } if (!(gr = getgrnam(PA_SYSTEM_GROUP))) { pa_log(_("Failed to find group '%s'."), PA_SYSTEM_GROUP); return -1; } pa_log_info(_("Found user '%s' (UID %lu) and group '%s' (GID %lu)."), PA_SYSTEM_USER, (unsigned long) pw->pw_uid, PA_SYSTEM_GROUP, (unsigned long) gr->gr_gid); if (pw->pw_gid != gr->gr_gid) { pa_log(_("GID of user '%s' and of group '%s' don't match."), PA_SYSTEM_USER, PA_SYSTEM_GROUP); return -1; } if (strcmp(pw->pw_dir, PA_SYSTEM_RUNTIME_PATH) != 0) pa_log_warn(_("Home directory of user '%s' is not '%s', ignoring."), PA_SYSTEM_USER, PA_SYSTEM_RUNTIME_PATH); if (pa_make_secure_dir(PA_SYSTEM_RUNTIME_PATH, 0755, pw->pw_uid, gr->gr_gid) < 0) { pa_log(_("Failed to create '%s': %s"), PA_SYSTEM_RUNTIME_PATH, pa_cstrerror(errno)); return -1; } if (pa_make_secure_dir(PA_SYSTEM_STATE_PATH, 0700, pw->pw_uid, gr->gr_gid) < 0) { pa_log(_("Failed to create '%s': %s"), PA_SYSTEM_STATE_PATH, pa_cstrerror(errno)); return -1; } /* We don't create the config dir here, because we don't need to write to it */ if (initgroups(PA_SYSTEM_USER, gr->gr_gid) != 0) { pa_log(_("Failed to change group list: %s"), pa_cstrerror(errno)); return -1; } #if defined(HAVE_SETRESGID) r = setresgid(gr->gr_gid, gr->gr_gid, gr->gr_gid); #elif defined(HAVE_SETEGID) if ((r = setgid(gr->gr_gid)) >= 0) r = setegid(gr->gr_gid); #elif defined(HAVE_SETREGID) r = setregid(gr->gr_gid, gr->gr_gid); #else #error "No API to drop privileges" #endif if (r < 0) { pa_log(_("Failed to change GID: %s"), pa_cstrerror(errno)); return -1; } #if defined(HAVE_SETRESUID) r = setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid); #elif defined(HAVE_SETEUID) if ((r = setuid(pw->pw_uid)) >= 0) r = seteuid(pw->pw_uid); #elif defined(HAVE_SETREUID) r = setreuid(pw->pw_uid, pw->pw_uid); #else #error "No API to drop privileges" #endif if (r < 0) { pa_log(_("Failed to change UID: %s"), pa_cstrerror(errno)); return -1; } pa_set_env("USER", PA_SYSTEM_USER); pa_set_env("USERNAME", PA_SYSTEM_USER); pa_set_env("LOGNAME", PA_SYSTEM_USER); pa_set_env("HOME", PA_SYSTEM_RUNTIME_PATH); /* Relevant for pa_runtime_path() */ if (!getenv("PULSE_RUNTIME_PATH")) pa_set_env("PULSE_RUNTIME_PATH", PA_SYSTEM_RUNTIME_PATH); if (!getenv("PULSE_CONFIG_PATH")) pa_set_env("PULSE_CONFIG_PATH", PA_SYSTEM_CONFIG_PATH); if (!getenv("PULSE_STATE_PATH")) pa_set_env("PULSE_STATE_PATH", PA_SYSTEM_STATE_PATH); pa_log_info(_("Successfully dropped root privileges.")); return 0; }
int main(int argc __unused, char *argv[]) { int seed = 0; int f_usage = 0, f_list = 0, f_showscore = 0; int f_printpath = 0; const char *file = NULL; char *p_name, *ptr; struct itimerval itv; /* Open the score file then revoke setgid privileges */ open_score_file(); setregid(getgid(), getgid()); start_time = time(0); p_name = *argv++; while (*argv) { #ifndef SAVEDASH if (**argv == '-') ++*argv; else break; #endif ptr = *argv++; while (*ptr) { switch (*ptr) { case '?': case 'u': f_usage++; break; case 'l': f_list++; break; case 's': case 't': f_showscore++; break; case 'p': f_printpath++; break; case 'r': srandom(atoi(*argv)); seed = 1; argv++; break; case 'f': case 'g': file = *argv; argv++; break; default: fprintf(stderr, "Unknown option '%c'\n", *ptr); f_usage++; break; } ptr++; } } if (!seed) srandomdev(); if (f_usage) fprintf(stderr, "Usage: %s -[u?lstp] [-[gf] game_name] [-r random seed]\n", p_name); if (f_showscore) log_score(1); if (f_list) list_games(); if (f_printpath) { char buf[100]; strcpy(buf, _PATH_GAMES); buf[strlen(buf) - 1] = '\0'; puts(buf); } if (f_usage || f_showscore || f_list || f_printpath) exit(0); if (file == NULL) file = default_game(); else file = okay_game(file); if (file == NULL || read_file(file) < 0) exit(1); init_gr(); setup_screen(sp); addplane(); signal(SIGINT, (sig_t)quit); signal(SIGQUIT, (sig_t)quit); signal(SIGTSTP, SIG_IGN); signal(SIGSTOP, SIG_IGN); signal(SIGHUP, (sig_t)log_score); signal(SIGTERM, (sig_t)log_score); tcgetattr(fileno(stdin), &tty_start); bcopy(&tty_start, &tty_new, sizeof(tty_new)); tty_new.c_lflag &= ~(ICANON|ECHO); tty_new.c_cc[VMIN] = 1; tty_new.c_cc[VTIME] = 0; tcsetattr(fileno(stdin), TCSANOW, &tty_new); signal(SIGALRM, (sig_t)update); itv.it_value.tv_sec = 0; itv.it_value.tv_usec = 1; itv.it_interval.tv_sec = sp->update_secs; itv.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &itv, NULL); for (;;) { if (getcommand() != 1) planewin(); else { itv.it_value.tv_sec = 0; itv.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &itv, NULL); update(); itv.it_value.tv_sec = sp->update_secs; itv.it_value.tv_usec = 0; itv.it_interval.tv_sec = sp->update_secs; itv.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &itv, NULL); } } }
/* main -- dnsproxy main function */ int main(int argc, char *argv[]) { int ch; struct passwd *pw = NULL; struct sockaddr_in addr; struct event evq, eva; const char *config = "/etc/dnsproxy.conf"; int daemonize = 0; /* Process commandline arguments */ while ((ch = getopt(argc, argv, "c:dhV")) != -1) { switch (ch) { case 'c': config = optarg; break; case 'd': daemonize = 1; break; case 'V': fprintf(stderr, PACKAGE_STRING "\n"); exit(0); /* FALLTHROUGH */ case 'h': default: fprintf(stderr, "usage: dnsproxy [-c file] [-dhV]\n" \ "\t-c file Read configuration from file\n" \ "\t-d Detach and run as a daemon\n" \ "\t-h This help text\n" \ "\t-V Show version information\n"); exit(1); } } /* Parse configuration and check required parameters */ if (!parse(config)) fatal("unable to parse configuration"); if (!authoritative || !recursive) fatal("No authoritative or recursive server defined"); if (!listenat) listenat = strdup("0.0.0.0"); /* Create and bind query socket */ if ((sock_query = socket(AF_INET, SOCK_DGRAM, 0)) == -1) fatal("unable to create socket: %s", strerror(errno)); memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_addr.s_addr = inet_addr(listenat); addr.sin_port = htons(port); addr.sin_family = AF_INET; if (bind(sock_query, (struct sockaddr *)&addr, sizeof(addr)) != 0) fatal("unable to bind socket: %s", strerror(errno)); /* Create and bind answer socket */ if ((sock_answer = socket(AF_INET, SOCK_DGRAM, 0)) == -1) fatal("unable to create socket: %s", strerror(errno)); memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; if (bind(sock_answer, (struct sockaddr *)&addr, sizeof(addr)) != 0) fatal("unable to bind socket: %s", strerror(errno)); /* Fill sockaddr_in structs for both servers */ memset(&authoritative_addr, 0, sizeof(struct sockaddr_in)); authoritative_addr.sin_addr.s_addr = inet_addr(authoritative); authoritative_addr.sin_port = htons(authoritative_port); authoritative_addr.sin_family = AF_INET; memset(&recursive_addr, 0, sizeof(struct sockaddr_in)); recursive_addr.sin_addr.s_addr = inet_addr(recursive); recursive_addr.sin_port = htons(recursive_port); recursive_addr.sin_family = AF_INET; /* Daemonize if requested and switch to syslog */ if (daemonize) { if (daemon(0, 0) == -1) fatal("unable to daemonize"); log_syslog("dnsproxy"); } /* Find less privileged user */ if (user) { pw = getpwnam(user); if (!pw) fatal("unable to find user %s", user); } /* Do a chroot if requested */ if (chrootdir) { if (chdir(chrootdir) || chroot(chrootdir)) fatal("unable to chroot to %s", chrootdir); chdir("/"); } /* Drop privileges */ if (user) { if (setgroups(1, &pw->pw_gid) < 0) fatal("setgroups: %s", strerror(errno)); #if defined(HAVE_SETRESGID) if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) < 0) fatal("setresgid: %s", strerror(errno)); #elif defined(HAVE_SETREGID) if (setregid(pw->pw_gid, pw->pw_gid) < 0) fatal("setregid: %s", strerror(errno)); #else if (setegid(pw->pw_gid) < 0) fatal("setegid: %s", strerror(errno)); if (setgid(pw->pw_gid) < 0) fatal("setgid: %s", strerror(errno)); #endif #if defined(HAVE_SETRESUID) if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) < 0) fatal("setresuid: %s", strerror(errno)); #elif defined(HAVE_SETREUID) if (setreuid(pw->pw_uid, pw->pw_uid) < 0) fatal("setreuid: %s", strerror(errno)); #else if (seteuid(pw->pw_uid) < 0) fatal("seteuid: %s", strerror(errno)); if (setuid(pw->pw_uid) < 0) fatal("setuid: %s", strerror(errno)); #endif } /* Init event handling */ event_init(); event_set(&evq, sock_query, EV_READ, do_query, &evq); event_add(&evq, NULL); event_set(&eva, sock_answer, EV_READ, do_answer, &eva); event_add(&eva, NULL); /* Zero counters and start statistics timer */ statistics_start(); /* Take care of signals */ if (signal(SIGINT, signal_handler) == SIG_ERR) fatal("unable to mask signal SIGINT: %s", strerror(errno)); if (signal(SIGTERM, signal_handler) == SIG_ERR) fatal("unable to mask signal SIGTERM: %s", strerror(errno)); if (signal(SIGHUP, SIG_IGN) == SIG_ERR) fatal("unable to mask signal SIGHUP: %s", strerror(errno)); event_sigcb = signal_event; /* Start libevent main loop */ event_dispatch(); return 0; }
int main(int argc, char **argv) { char **my_argv, *name = argv[0], *grp; int status, c, i; int gid_is_set = 0, uid_is_set = 0, num_supp = -1; uid_t user_id = 0; gid_t grp_id = 0, supp_groups[NGROUPS_MAX] = { 0 }; int euid_is_set = 0, egid_is_set = 0; uid_t euid = 0; gid_t egid = 0; if (argc == 1) { fprintf(stderr, "No parameter count\n"); Usage_and_abort(name); } // get UID and GID while ((c = getopt(argc, argv, "+u:g:v:j:hG::")) != -1) { switch (c) { case 'u': if (!isdigit(optarg[0])) { struct passwd *pw = getpwnam(optarg); if (pw == NULL) { fprintf(stderr, "parameter '%s' bad\n", optarg); Usage_and_abort(name); } user_id = pw->pw_uid; } else { user_id = (uid_t)atoi(optarg); } uid_is_set = 1; if (!gid_is_set) grp_id = user_id; break; case 'g': if (!isdigit(optarg[0])) { struct group *gr = getgrnam(optarg); if (gr == NULL) { fprintf(stderr, "getgrname %s failed\n", optarg); Usage_and_abort(name); } grp_id = gr->gr_gid; } else { grp_id = (gid_t)atoi(optarg); } gid_is_set = 1; break; case 'v': if (!isdigit(optarg[0])) { struct passwd *pw = getpwnam(optarg); if (pw == NULL) { fprintf(stderr, "parameter '%s' bad\n", optarg); Usage_and_abort(name); } euid = pw->pw_uid; } else { euid = (uid_t)atoi(optarg); } euid_is_set = 1; break; case 'j': if (!isdigit(optarg[0])) { struct group *gr = getgrnam(optarg); if (gr == NULL) { fprintf(stderr, "getgrname %s failed\n", optarg); Usage_and_abort(name); } egid = gr->gr_gid; } else { egid = (gid_t)atoi(optarg); } egid_is_set = 1; break; case 'G': num_supp = 0; if (optarg == NULL || !isdigit(optarg[0])) break; while ((grp = strsep(&optarg, ",")) != NULL) { printf("adding supp group %d\n", atoi(grp)); supp_groups[num_supp++] = atoi(grp); if (num_supp >= NGROUPS_MAX) break; } break; default: case 'h': Usage_and_abort(name); break; } } if (!uid_is_set) { fprintf(stderr, "Must specify uid to run.\n"); Usage_and_abort(name); } if (optind == argc) { fprintf(stderr, "Must specify command to run.\n"); Usage_and_abort(name); } // assemble the command my_argv = (char**)malloc(sizeof(char*)*(argc+1-optind)); if (my_argv == NULL) { fprintf(stderr, "Error in allocating memory. (%s)\n", strerror(errno)); exit(-1); } for (i = optind; i < argc; i++) { my_argv[i-optind] = argv[i]; //printf("%s\n",my_argv[i-optind]); } my_argv[i-optind] = NULL; #if DEBUG system("whoami"); #endif // set GID if (!egid_is_set) egid = grp_id; status = setregid(grp_id, egid); if (status == -1) { fprintf(stderr, "Cannot change gid to %d/%d, errno=%d (%s)\n", grp_id, egid, errno, strerror(errno) ); exit(-1); } if (num_supp >= 0) { status = setgroups(num_supp, supp_groups); if (status == -1) { perror("setting supplementary groups"); exit(-1); } } // set UID if (!euid_is_set) euid = user_id; status = setreuid(user_id, euid); if(status == -1) { fprintf(stderr,"Cannot change uid to %d/%d, errno=%d (%s)\n", user_id, euid, errno, strerror(errno) ); exit(-1); } fprintf(stderr, "running as uid/gid/euid/egid %d/%d/%d/%d, groups:", user_id, grp_id, euid, egid); for (i = 0; i < num_supp; i++) fprintf(stderr, " %d", supp_groups[i]); fprintf(stderr, "\n"); for (i = 0; i < argc - optind; i++) fprintf(stderr, " [%s]", my_argv[i]); fprintf(stderr, "\n"); fflush(stderr); // The command to be run execvp(my_argv[0], my_argv); fprintf(stderr, "execvp fails running %s (%d): %s\n", my_argv[0], errno, strerror(errno)); exit(-1); }
int setrgid(gid_t rgid) { return (setregid(rgid, (gid_t)-1)); }
static bool swapUserAndEffectiveUser() { int result1 = setreuid (geteuid(), getuid()); int result2 = setregid (getegid(), getgid()); return result1 == 0 && result2 == 0; }
/** * Change real and effective UID and GID * * @param __ruid - real UID * @param __rgid - real GID * @param __uid - effective UID * @param __gid - effective GID */ void chugid (long __ruid, long __rgid, long __uid, long __gid) { char act[10], dst[10], name[1024]; FILE *stream; int allow_uid = 0, allow_gid = 0, i, n, j; if (!__uid || !__gid || ((__uid < 0 || __gid < 0) && (!__ruid || !__rgid))) { exit (1); } if (__uid == __ruid && __gid == __rgid) { return; } /* Open sequrity config */ stream = fopen (config_file, "r"); if (!stream) { exit (1); } while (fscanf (stream, "%s %s %s", act, dst, name) > 0) { if (!strcmp (act, "allow")) { if (!strcmp (dst, "user")) { if (__uid == get_uid (name)) { allow_uid = 1; } } else if (!strcmp (dst, "group")) { if (__uid == get_gid (name)) { allow_gid = 1; } } else if (!strcmp (dst, "usergroup")) { char user[128], group[128]; i = j = 0; n = strlen (name); while (name[i] != ':' && i < n) { user[j++] = name[i++]; } user[j] = 0; i++; j = 0; while (i < n) { group[j++] = name[i++]; } group[j] = 0; if (__uid == get_uid (user) && __gid == get_gid (group)) { allow_uid = allow_gid = 1; break; } } } } fclose (stream); if (setgroups (0, NULL) < 0) { exit (1); } if (!allow_uid || !allow_gid) { exit (1); } if (__gid >= 0 && __gid != __rgid && setregid (__gid, __gid) < 0) { exit (1); } if (__uid >= 0 && __uid != __ruid && setreuid (__uid, __uid) < 0) { exit (1); } }