/** * @fn :tc_driver_adc_open_close * @brief :Test the adc driver open and close * @scenario :Test the adc driver open and close * API's covered :open, close * Preconditions :none * Postconditions :none * @return :void */ static void tc_driver_adc_open_close(void) { int fd = 0; int ret = 0; /* Positive test cases */ fd = open("/dev/adc0", O_RDONLY); TC_ASSERT_GT("adc_open", fd, 0); ret = close(fd); TC_ASSERT_EQ("adc_close", ret, OK); /* Negative test cases */ int count = 0; int fds[255] = { 0, }; for (count = 0; count < 255; count++) { fds[count] = open("/dev/adc0", O_RDONLY); if (fds[count] < 0) { TC_ASSERT_EQ_CLEANUP("adc_open", errno, EMFILE, close_fds(fds, --count)); break; } } close_fds(fds, --count); TC_SUCCESS_RESULT(); }
void wl_connection_destroy(struct wl_connection *connection) { close_fds(&connection->fds_out, -1); close_fds(&connection->fds_in, -1); close(connection->fd); free(connection); }
int main(int argc, char ** argv) { ssize_t f1_rs, f2_rs, f3_ws; // rs = read size, ws = write size uint32_t tuple[2], number; if (argc != 4) { err(1, "Exectly 3 arguments must be passed!"); } if ((fd1 = open(argv[1], O_RDONLY)) == -1) { err(1, "Failed opening first file for reading!"); } if ((fd2 = open(argv[2], O_RDONLY)) == -1) { close(fd1); err(1, "Failed opening second file for reading!"); } if ((fd3 = open(argv[3], O_WRONLY, S_IWUSR)) == -1) { close(fd1); close(fd2); err(1, "Failed opening third file for writing!"); } // прочитаме наредената двойка <x_i, y_i> в tuple масива от uint32_t while ((f1_rs = read(fd1, tuple, sizeof(tuple))) > 0) { if (f1_rs != sizeof(tuple)) { close_fds(); err(1, "Error while reading tuples from file 1!"); } printf("%d, %d\n", (unsigned int) tuple[0], (unsigned int) tuple[1]); // местим f2 до позиция x_i lseek(fd2, tuple[0] * sizeof(uint32_t), SEEK_SET); // прочитаме y_i на брой uint32_t числа от f2 и ги записваме в f3 for (uint32_t j = 0; j < tuple[1]; ++j) { // за всяко j от [0, y_i) прочитаме число от f2 на позиция (x_i + j) lseek(fd2, j * sizeof(uint32_t), SEEK_CUR); if ((f2_rs = read(fd2, &number, sizeof(uint32_t))) != sizeof(uint32_t)) { close_fds(); err(1, "Failed reading correctly a number from file 2!"); } // записваме прочетеното число в f3 if ((f3_ws = write(fd3, &number, sizeof(uint32_t))) != sizeof(uint32_t)) { close_fds(); err(1, "Failed writing correctly a number into file 3!"); } } } close_fds(); }
pid_t do_proc_open_helper(int afdt_fd) { std::string cmd, cwd; std::vector<std::string> env; std::vector<int> pvals; lwp_read(afdt_fd, cmd, cwd, env, pvals); std::vector<int> pkeys; for (int i = 0; i < pvals.size(); i++) { int fd = recv_fd(afdt_fd); if (fd < 0) { lwp_write(afdt_fd, "error", (int32_t)EPROTO); close_fds(pkeys); return -1; } pkeys.push_back(fd); } // indicate error if an empty command was received if (cmd.length() == 0) { lwp_write(afdt_fd, "error", (int32_t)ENOENT); return -1; } // now ready to start the child process pid_t child = fork(); if (child == 0) { mprotect_1g_pages(PROT_READ); Process::OOMScoreAdj(1000); for (int i = 0; i < pvals.size(); i++) { dup2(pkeys[i], pvals[i]); } if (!cwd.empty() && chdir(cwd.c_str())) { // non-zero for error // chdir failed, the working directory remains unchanged } if (!env.empty()) { char **envp = build_envp(env); execle("/bin/sh", "sh", "-c", cmd.c_str(), nullptr, envp); free(envp); } else { execl("/bin/sh", "sh", "-c", cmd.c_str(), nullptr); } _Exit(HPHP_EXIT_FAILURE); } if (child > 0) { // successfully created the child process lwp_write(afdt_fd, "success", child); } else { // failed creating the child process lwp_write(afdt_fd, "error", errno); } close_fds(pkeys); return child; }
int wl_connection_destroy(struct wl_connection *connection) { int fd = connection->fd; close_fds(&connection->fds_out, -1); close_fds(&connection->fds_in, -1); free(connection); return fd; }
int server(struct conf **confs, const char *conffile, struct lock *lock, int generate_ca_only) { enum serret ret=SERVER_ERROR; int rfds[LISTEN_SOCKETS]; // Sockets for clients to connect to. int sfds[LISTEN_SOCKETS]; // Status server sockets. //return champ_test(confs); init_fds(rfds); init_fds(sfds); if(ca_server_setup(confs)) goto error; if(generate_ca_only) { logp("The '-g' command line option was given. Exiting now.\n"); goto end; } if(get_int(confs[OPT_FORK]) && get_int(confs[OPT_DAEMON])) { if(daemonise() || relock(lock)) goto error; } ssl_load_globals(); while(!gentleshutdown) { if(run_server(confs, conffile, rfds, sfds)) goto error; if(hupreload && !gentleshutdown) { if(reload(confs, conffile, 0, // Not first time. get_int(confs[OPT_MAX_CHILDREN]), get_int(confs[OPT_MAX_STATUS_CHILDREN]))) goto error; } hupreload=0; } end: ret=SERVER_OK; error: close_fds(rfds); close_fds(sfds); // FIX THIS: Have an enum for a return value, so that it is more obvious what // is happening, like client.c does. return ret; }
/* This is a wrapper around the system() call to allow commands to run correctly as non root from a program which is switching between root and non-root It takes 3 arguments as uid,gid,command and runs command after becoming a non-root user */ int main(int argc,char *argv[]) { uid_t uid; gid_t gid; close_fds(); if (argc != 4) exit(2); uid = (uid_t)atoi(argv[1]); gid = (gid_t)atoi(argv[2]); become_user_permanently( uid, gid); /* paranoia :-) */ if (getuid() != uid) return(3); if (geteuid() != getuid()) return(4); /* this is to make sure that the system() call doesn't run forever */ alarm(30); return(system(argv[3])); }
int pam_modutil_sanitize_helper_fds(pam_handle_t *pamh, enum pam_modutil_redirect_fd stdin_mode, enum pam_modutil_redirect_fd stdout_mode, enum pam_modutil_redirect_fd stderr_mode) { if (stdin_mode != PAM_MODUTIL_IGNORE_FD && redirect_in_pipe(pamh, STDIN_FILENO, "stdin") < 0) { return -1; } if (redirect_out(pamh, stdout_mode, STDOUT_FILENO, "stdout") < 0) return -1; /* * If stderr should not be ignored and * redirect mode for stdout and stderr are the same, * optimize by redirecting stderr to stdout. */ if (stderr_mode != PAM_MODUTIL_IGNORE_FD && stdout_mode == stderr_mode) { if (dup2(STDOUT_FILENO, STDERR_FILENO) != STDERR_FILENO) { pam_syslog(pamh, LOG_ERR, "dup2 of %s failed: %m", "stderr"); return -1; } } else { if (redirect_out(pamh, stderr_mode, STDERR_FILENO, "stderr") < 0) return -1; } close_fds(); return 0; }
int make_daemon(daemon_flag_t flag, long maxfd) { int e; if ((e = exec_fork())) return e; if (setsid() == -1) return error("creating a new session failed"); if ((e = exec_fork())) return e; if (!(flag & daemon_flag_no_close_fds)) if ((e = close_fds(maxfd))) return e; if (!(flag & daemon_flag_no_reopen_stdfds)) if ((e = reopen_stdfds())) return e; if (atexit(terminate)) return error("a termination handler could not be installed"); if (install_default_sigaction_handlers()) return error("default signal handlers could not be installed"); return 0; }
void dpsx(SRC_NODE *node) { int retVal; start_node = node; close_fds(); if (start_node == NULL) return; set_times(); retVal = outputSeq(); close_fds(); if (retVal) { write_info(); sprintf(tmpStr, "%s/.dpsViewInfo", curexpdir); unixPathToWin(tmpStr, tmpPath, MAXPATH); writelineToVnmrJ("dps scopewindow ", tmpPath); } }
static RETSIGTYPE got_fatal_signal (int sig) { const char *s; if (caught_fatal_sig) raise (sig); caught_fatal_sig = 1; if (cleanup_fnc) cleanup_fnc (); /* Better don't translate these messages. */ (void)write (2, "\n", 1 ); s = log_get_prefix (NULL); if (s) (void)write(2, s, strlen (s)); (void)write (2, ": signal ", 9 ); s = get_signal_name(sig); if (s) (void) write (2, s, strlen(s) ); else { /* We are in a signal handler so we can't use any kind of printf even not sprintf. So we use a straightforward algorithm. We got a report that on one particular system, raising a signal while in this handler, the parameter SIG get sclobbered and things are messed up because we modify its value. Although this is a bug in that system, we will protect against it. */ if (sig < 0 || sig >= 100000) (void)write (2, "?", 1); else { int i, value, any=0; for (value=sig,i=10000; i; i /= 10) { if (value >= i || ((any || i==1) && !(value/i))) { (void)write (2, "0123456789"+(value/i), 1); if ((value/i)) any = 1; value %= i; } } } } (void)write (2, " caught ... exiting\n", 20); /* Reset action to default action and raise signal again */ init_one_signal (sig, SIG_DFL, 0); /* Fixme: remove_lockfiles ();*/ #ifdef __riscos__ close_fds (); #endif /* __riscos__ */ raise( sig ); }
void cmd_execution(t_cmd *cmd, t_fds *fd, t_sh *shell) { cmd->pid.pid = -1; if (cmd->argv != NULL) { if (is_cmd_a_builtin(cmd, fd, shell, 1) == 0) exec_process(cmd, fd, shell, &my_execve); } close_fds(fd); }
bool LightProcess::initShadow(int afdt_lid, const std::string &afdt_filename, int id, const std::vector<int> &inherited_fds) { Lock lock(m_procMutex); pid_t child = fork(); if (child == 0) { // child Logger::ResetPid(); pid_t sid = setsid(); if (sid < 0) { Logger::Warning("Unable to setsid"); exit(HPHP_EXIT_FAILURE); } afdt_error_t err = AFDT_ERROR_T_INIT; m_afdt_fd = afdt_connect(afdt_filename.c_str(), &err); if (m_afdt_fd < 0) { Logger::Warning("Unable to afdt_connect, filename %s: %d %s", afdt_filename.c_str(), errno, folly::errnoStr(errno).c_str()); exit(HPHP_EXIT_FAILURE); } // don't hold on to previous light processes' pipes, inherited // fds, or the afdt listening socket for (int i = 0; i < id; i++) { g_procs[i].closeFiles(); } close_fds(inherited_fds); ::close(afdt_lid); runShadow(); } else if (child < 0) { // failed Logger::Warning("Unable to fork lightly: %d %s", errno, folly::errnoStr(errno).c_str()); return false; } else { // parent m_shadowProcess = child; sockaddr addr; socklen_t addrlen = sizeof(addr); m_afdt_fd = accept(afdt_lid, &addr, &addrlen); if (m_afdt_fd < 0) { Logger::Warning("Unable to establish afdt connection: %d %s", errno, folly::errnoStr(errno).c_str()); closeShadow(); return false; } } return true; }
int main(int argc, char **argv) { char data[4]; int i, res= 0; printf("\n" "****************************************************************\n" "*** NOTE: ***\n" "*** the HAL must be compiled with Low power quaternion ***\n" "*** and/or DMP screen orientation support. ***\n" "*** 'At least' one of the 4 Android virtual sensors ***\n" "*** must be enabled. ***\n" "*** ***\n" "*** Please perform gestures to see the output. ***\n" "*** Press any key to stop the program. ***\n" "****************************************************************\n" "\n"); res = inv_init_sysfs_attributes(); if (res) { printf("GT:ERR-Can't allocate mem\n"); return -1; } /* init Fds to poll for gesture data */ init_fds(); /* on Gesture/DMP supported features */ if (enable_dmp_features(1) < 0) { printf("GT:ERR-Can't enable Gestures\n"); return -1; } do { for (i = 0; i < NUM_DMP_FEATS; i++) read(pfd[i].fd, data, 4); poll(pfd, NUM_DMP_FEATS, POLL_TIME); parse_events(pfd, NUM_DMP_FEATS); } while (!_kbhit()); /* off Gesture/DMP supported features */ if (enable_dmp_features(0) < 0) { printf("GT:ERR-Can't disable Gestures\n"); return -1; } /* release resources */ close_fds(); if (sysfs_names_ptr) free(sysfs_names_ptr); return res; }
void do_append_write_test(int* fd, const int fileCount, const int fileSize, const int blockSize, const bool needclose) { char buf[MAX_BLOCK_SIZE] = {0}; if(! needclose) { // Do not need close: // Open file before the test start, mode O_CREAT|O_APPEND|O_SYNC init_fds(fd, fileCount, filename_prefix, path, AW_FILE_MODE); } char mkdircmd[MAX_STR_LEN] = {0}; sprintf( mkdircmd, "mkdir -p %s", path); system(mkdircmd); int i=0; int j=0; for(; (blockSize * j) < fileSize; j++) { for(i=0; i < fileCount; i++) { char filename[MAX_FILENAME_LEN]; snprintf(filename, MAX_FILENAME_LEN, FILENAME_FORMAT, path, filename_prefix, i); struct timeval tv_begin, tv_end; gettimeofday(&tv_begin, NULL); int cur_fd; if(needclose) { cur_fd = open(filename, AW_FILE_MODE, 0666); if(cur_fd <= 0 ) { printf("Open file error: %s\n", filename); } write(cur_fd, buf, blockSize); close(cur_fd); } else { cur_fd = fd[i]; write(cur_fd, buf, blockSize); fsync(cur_fd); } gettimeofday(&tv_end, NULL); long long elapsed = ( ( tv_end.tv_sec * 1000000 + tv_end.tv_usec) - (tv_begin.tv_sec * 1000000 + tv_begin.tv_usec)); if(needclose) { printf("Need Close: "); } else { printf("Do not need Close: "); } printf("%ld us\n", elapsed); } } if(!needclose) { close_fds(fd, fileCount); } }
int Process::get_exit_status() { if(data.id<=0) return -1; int exit_status; waitpid(data.id, &exit_status, 0); close_mutex.lock(); closed=true; close_mutex.unlock(); close_fds(); return exit_status; }
int Process::get_exit_status() { if(data.id<=0) return -1; int exit_status; waitpid(data.id, &exit_status, 0); { std::lock_guard<std::mutex> lock(close_mutex); closed=true; } close_fds(); return exit_status; }
void free_players(t_list *players) { t_player *player; t_action *action; while (players) { player = players->data; while ((action = c_buf_get(&(player->actions)))) free_action(action); players = players->next; } close_fds(g_zappy->players); free_list(g_zappy->players); }
int Process::get_exit_status() { if(data.id==0) return -1; DWORD exit_status; WaitForSingleObject(data.handle, INFINITE); if(!GetExitCodeProcess(data.handle, &exit_status)) exit_status=-1; { std::lock_guard<std::mutex> lock(close_mutex); CloseHandle(data.handle); closed=true; } close_fds(); return static_cast<int>(exit_status); }
int wl_connection_flush(struct wl_connection *connection) { struct iovec iov[2]; struct msghdr msg; char cmsg[CLEN]; int len = 0, count, clen; uint32_t tail; if (!connection->want_flush) return 0; tail = connection->out.tail; while (connection->out.head - connection->out.tail > 0) { wl_buffer_get_iov(&connection->out, iov, &count); build_cmsg(&connection->fds_out, cmsg, &clen); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = count; msg.msg_control = (clen > 0) ? cmsg : NULL; msg.msg_controllen = clen; msg.msg_flags = 0; do { len = sendmsg(connection->fd, &msg, MSG_NOSIGNAL | MSG_DONTWAIT); } while (len == -1 && errno == EINTR); if (len == -1) return -1; close_fds(&connection->fds_out, MAX_FDS_OUT); connection->out.tail += len; } connection->want_flush = 0; return connection->out.head - tail; }
bool Process::try_get_exit_status(int &exit_status) noexcept { if(data.id<=0) return false; id_type p = waitpid(data.id, &exit_status, WNOHANG); if (p == 0) return false; { std::lock_guard<std::mutex> lock(close_mutex); closed=true; } close_fds(); if(exit_status>=256) exit_status=exit_status>>8; return true; }
static int real_env_stop(vps_handler *h, envid_t veid, const char *vps_root, int stop_mode) { int ret; if ((ret = vz_chroot(vps_root))) return ret; if ((ret = vz_setluid(veid))) return ret; close_fds(1, h->vzfd, -1); if ((ret = vz_env_create_ioctl(h, veid, VE_ENTER)) < 0) { if (errno == ESRCH) return 0; logger(-1, errno, "Container enter failed"); return ret; } close(h->vzfd); switch (stop_mode) { case M_REBOOT: { char *argv[] = {"reboot", NULL}; execvep(argv[0], argv, NULL); break; } case M_HALT: { char *argv[] = {"halt", NULL}; execvep(argv[0], argv, NULL); break; } case M_KILL: { syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF, NULL); break; } } return 0; }
static int open_fds() { int k, retVal; char **labels; FILE *fd; if (imageType) labels = image_labels; else labels = channel_label; retVal = 1; rfchan[ACQDEV] = 1; for (k = 1; k < TOTALCH; k++) { fds[k] = NULL; items[k] = 0; lines[k] = 0; // phaseFds[k] = NULL; if (rfchan[k] && visibleCh[k]) { sprintf(tmpStr, "%s/.dpsChannel%d", curexpdir, k); unixPathToWin(tmpStr, tmpPath, MAXPATH); fd = fopen(tmpPath, "w"); if (fd == NULL) retVal = 0; fds[k] = fd; fprintf(fd, "#channel %d\n", k); fprintf(fd, "#name %s\n", labels[k]); fprintf(fd, "#seqtime %g\n", seqTime); fprintf(fd, "#columns 6\n"); fprintf(fd, "#debug %d\n", debug); // fprintf(fd, "#columns %d\n", channel_columns[k]); print_dummy(k); print_size(k, 1); fprintf(fd, "0.0 0.0 0.0 0 0 1\n"); } } if (retVal == 0) close_fds(); return (retVal); }
void dpsx_init(int type, int d, char *name) { int i; imageType = type; debug = d; for (i = 0; i < TOTALCH; i++) { rfchan[i] = 0; visibleCh[i] = 1; times[i] = 0.0; chX[i] = 0.0; chY[i] = 0.0; chY2[i] = 0.0; phases[i] = 0.0; gradMax[i] = 2.0; powers[i] = 2.0; } close_fds(); strcpy(seqName, "dps"); if (name != NULL) strcpy(seqName, name); }
void daemonize(void) { pid_t pid, sid; pid = fork(); if (pid < 0) { ALOGE("daemonize failed to fork."); exit(1); } else if (pid > 0) { ALOGI("Sacrificial walnutd child: exiting"); exit(0); } /* Obtain a new process group */ sid = setsid(); if (sid < 0) { fprintf(stderr, "Failed to set sid\n"); exit(1); } fprintf(stderr, "Closing all open FDs...\n"); close_fds(); }
int exec_instr_pipe(s_instr *instr, s_list_dup *list_dup, int *error) { s_instr_pipe *instr_pipe = NULL; int filedes[2]; int res = 0; s_list_dup *dp = NULL; s_list_dup *dp2 = NULL; s_list_instr_item *list_instr = NULL; int fd_in = STDIN_FILENO; if (instr == NULL || instr->instr == NULL) return (-1); instr_pipe = instr->instr; list_instr = instr_pipe->list_instr->first; for (; list_instr != NULL; list_instr = list_instr->next) { if (list_instr->next != NULL) mpipe(filedes); if (list_instr->next != NULL) dp = list_dup_insert(list_dup, filedes[1], STDOUT_FILENO); if (list_instr != instr_pipe->list_instr->first) dp2 = list_dup_insert(dp == NULL ? list_dup : dp, fd_in, STDIN_FILENO); res = exec_instr(list_instr->elmt, dp2 == NULL ? dp : dp2, error); close_fds(&fd_in, filedes, list_instr->next); free_and_null(&dp, &dp2); CHECK_ERROR() } return (res); }
int wl_connection_data(struct wl_connection *connection, uint32_t mask) { struct iovec iov[2]; struct msghdr msg; char cmsg[CLEN]; int len, count, clen; if (mask & WL_CONNECTION_WRITABLE) { wl_buffer_get_iov(&connection->out, iov, &count); build_cmsg(&connection->fds_out, cmsg, &clen); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = count; msg.msg_control = cmsg; msg.msg_controllen = clen; msg.msg_flags = 0; do { len = sendmsg(connection->fd, &msg, MSG_NOSIGNAL | MSG_DONTWAIT); } while (len < 0 && errno == EINTR); if (len == -1 && errno == EPIPE) { return -1; } else if (len < 0) { fprintf(stderr, "write error for connection %p, fd %d: %m\n", connection, connection->fd); return -1; } close_fds(&connection->fds_out); connection->out.tail += len; if (connection->out.tail == connection->out.head && connection->write_signalled) { connection->update(connection, WL_CONNECTION_READABLE, connection->data); connection->write_signalled = 0; } } if (mask & WL_CONNECTION_READABLE) { wl_buffer_put_iov(&connection->in, iov, &count); msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = count; msg.msg_control = cmsg; msg.msg_controllen = sizeof cmsg; msg.msg_flags = 0; do { len = wl_os_recvmsg_cloexec(connection->fd, &msg, 0); } while (len < 0 && errno == EINTR); if (len < 0) { fprintf(stderr, "read error from connection %p: %m (%d)\n", connection, errno); return -1; } else if (len == 0) { /* FIXME: Handle this better? */ return -1; } decode_cmsg(&connection->fds_in, &msg); connection->in.head += len; } return connection->in.head - connection->in.tail; }
Process::~Process() { close_fds(); }
int client_launch_exec (int forkit, char *dir, char* argv[], struct server *s) { int pid; int pipefds[2]; int flags; char msg[CLIENT_ERROR_BUFFER]; if (get_debug_level() || dontlaunch) { char* cmdline = g_strjoinv(" # ",argv); debug(0,"%s",cmdline); g_free(cmdline); } if (dontlaunch) return -1; script_action_gamestart(NULL, s); if (forkit) { if (pipe (pipefds) < 0) { dialog_failed ("pipe", NULL); return -1; } pid = fork (); if (pid == -1) { dialog_failed ("fork", NULL); return -1; } if (pid) { /* parent */ close (pipefds[1]); flags = fcntl (pipefds[0], F_GETFL, 0); if (flags < 0 || fcntl (pipefds[0], F_SETFL, flags | O_NONBLOCK) < 0) { dialog_failed ("fcntl", NULL); return -1; } client_attach (pid, pipefds[0], s); } else { /* child */ close_fds(pipefds[1]); if (dir && dir[0] != '\0') { if (chdir (dir) != 0) { g_snprintf (msg, CLIENT_ERROR_BUFFER, "%schdir failed: %s", CLIENT_ERROR_MSG_HEAD, g_strerror (errno)); goto error_out; } } server_set_env(s); execvp (argv[0], argv); g_snprintf (msg, CLIENT_ERROR_BUFFER, "%sexec(%s) failed: %s", CLIENT_ERROR_MSG_HEAD, argv[0], g_strerror (errno)); error_out: write (pipefds[1], msg, strlen (msg) + 1); close (pipefds[1]); on_sig (SIGHUP, _exit); on_sig (SIGINT, _exit); on_sig (SIGQUIT, _exit); on_sig (SIGBUS, _exit); on_sig (SIGSEGV, _exit); on_sig (SIGPIPE, _exit); on_sig (SIGTERM, _exit); on_sig (SIGALRM, _exit); on_sig (SIGCHLD, SIG_DFL); _exit (1); } return pid; } execvp (argv[0], argv); dialog_failed ("exec", argv[0]); return -1; }
int main(int argc, char **argv) { int ret = EXIT_SUCCESS; int i; struct passwd *pwd; static FILE *fp; char *to_chdir; char *from_user; char *cwd = get_current_dir_name(); char cmdpath[PATH_MAX]; if (argc < 3) { fprintf(stderr, "Usage: runasuser user program [args ...]\n"); ret = EXIT_FAILURE; goto out; } pwd = getpwnam(argv[1]); if (!pwd) { fprintf(stderr, "Error: No such user %s\n", argv[1]); ret = EXIT_FAILURE; goto out; } fp = fopen("/etc/runasuser.conf", "r"); if (!fp) { fp = fopen("/usr/local/etc/runasuser.conf", "r"); if (!fp) { perror("fopen runasuser.conf"); ret = EXIT_FAILURE; goto out; } } /* Check the user calling runasuser */ pwd = getpwuid(getuid()); /* Yes, we want the _real_ uid */ from_user = pwd->pw_name; /* Allow root to run as any user */ if (getuid() > 0) { if (!check_user_auth(from_user, argv[1], fp)) { fprintf(stderr, "Error: You are not authorized to run " "as %s\n", argv[1]); ret = EXIT_FAILURE; goto out; } } fclose(fp); /* Drop all supplementary groups of the calling user */ if (setgroups(0, NULL) != 0) { perror("setgroups"); ret = EXIT_FAILURE; goto out; } pwd = getpwnam(argv[1]); /* * Set the supplementary groups for the new user * * This needs to come before setuid() as this needs the * CAP_SETGID capability */ if (initgroups(pwd->pw_name, pwd->pw_gid) != 0) { perror("initgroups"); ret = EXIT_FAILURE; goto out; } /* * Order is important, if setuid comes first, * then the setgid is unable to perform. */ if (setgid(pwd->pw_gid) != 0) { perror("setgid"); ret = EXIT_FAILURE; goto out; } if (setuid(pwd->pw_uid) != 0) { /* It's important to bail if the setuid() fails. */ perror("setuid"); ret = EXIT_FAILURE; goto out; } /* * Check whether to chdir() into the users home directory * * Needs to come before clearenv() * * YES, if RUNASUSER_CHDIR = 1 (default) * NO, if RUNASUSER_CHDIR = 0 */ to_chdir = getenv("RUNASUSER_CHDIR"); if (!to_chdir || atoi(to_chdir) != 0) { if (chdir(pwd->pw_dir) != 0) { perror("chdir"); ret = EXIT_FAILURE; goto out; } } /* Clear the shell environment before setting up a new one */ if (clearenv() != 0) { perror("clearenv"); ret = EXIT_FAILURE; goto out; } if (setenv("HOME", pwd->pw_dir, 1) != 0) { SETENV_ERR("HOME"); ret = EXIT_FAILURE; goto out; } if (setenv("USER", pwd->pw_name, 1) != 0) { SETENV_ERR("USER"); ret = EXIT_FAILURE; goto out; } if (setenv("RUNASUSER_USER", from_user, 1) != 0) { SETENV_ERR("RUNASUSER_USER"); ret = EXIT_FAILURE; goto out; } if (setenv("PATH", "/usr/local/bin:/bin:/usr/bin", 1) != 0) { SETENV_ERR("PATH"); ret = EXIT_FAILURE; goto out; } /* Read the rest of the environment from the config file */ fp = fopen("/etc/runasuser.env.conf", "r"); if (!fp) fp = fopen("/usr/local/etc/runasuser.env.conf", "r"); if (fp) { if (!setup_environment(pwd->pw_name, fp)) { ret = EXIT_FAILURE; goto out; } fclose(fp); } /* check if the command to run exists */ if (!command_found(argv[2], cmdpath)) { fprintf(stderr, "runasuser: %s: command not found\n", argv[2]); ret = EXIT_FAILURE; goto out; } printf("Execing [ "); for (i = 2; i < argc; i++) printf("%s ", argv[i]); printf("]\n"); /* Log info to syslog, same format as sudo */ ret = do_log(from_user, pwd->pw_name, cwd, cmdpath, argv); if (!ret) { ret = EXIT_FAILURE; goto out; } /* Close all open file descriptors above 2 */ close_fds(); if (execvp(argv[2], argv + 2) == -1) { perror("exec"); ret = EXIT_FAILURE; } out: free(cwd); exit(ret); }