/* create the server directory and chdir to it */ static void create_server_dir( const char *dir ) { char *p, *server_dir; struct stat st, st2; if (!(server_dir = strdup( dir ))) fatal_error( "out of memory\n" ); /* first create the base directory if needed */ p = strrchr( server_dir, '/' ); *p = 0; create_dir( server_dir, &st ); /* now create the server directory */ *p = '/'; create_dir( server_dir, &st ); if (chdir( server_dir ) == -1) fatal_perror( "chdir %s", server_dir ); if ((server_dir_fd = open( ".", O_RDONLY )) == -1) fatal_perror( "open %s", server_dir ); if (fstat( server_dir_fd, &st2 ) == -1) fatal_perror( "stat %s", server_dir ); if (st.st_dev != st2.st_dev || st.st_ino != st2.st_ino) fatal_error( "chdir did not end up in %s\n", server_dir ); free( server_dir ); }
static void signal_setup(void) { static struct event ev_sighup; static struct event ev_sigterm; static struct event ev_sigint; sigset_t set; int err; /* block SIGPIPE */ sigemptyset(&set); sigaddset(&set, SIGPIPE); err = sigprocmask(SIG_BLOCK, &set, NULL); if (err < 0) fatal_perror("sigprocmask"); /* catch signals */ signal_set(&ev_sighup, SIGHUP, handle_sighup, NULL); err = signal_add(&ev_sighup, NULL); if (err < 0) fatal_perror("signal_add"); signal_set(&ev_sigterm, SIGTERM, handle_sigterm, NULL); err = signal_add(&ev_sigterm, NULL); if (err < 0) fatal_perror("signal_add"); signal_set(&ev_sigint, SIGINT, handle_sigint, NULL); err = signal_add(&ev_sigint, NULL); if (err < 0) fatal_perror("signal_add"); }
main (int argc, char *argv[]) { static char codexxx[] = "/tmp/codeXXXXXX"; static char asxxx[] = "/tmp/asXXXXXX"; char *codefile, *hookfile, hooksfile[40], hookofile[40]; char *outfile = "a.out"; char *arg, ldargs[1024], cmd[1024]; FILE *inf, *outf; /* Make temp file names. */ codefile = mktemp (codexxx); hookfile = mktemp (asxxx); sprintf (hooksfile, "%s.s", hookfile); sprintf (hookofile, "%s.o", hookfile); /* Parse arguments. Remove output file spec, pass the rest to ld. */ ldargs[0] = '\0'; while (arg = *++argv) { if (! strcmp (arg, "-o")) outfile = *++argv; else { strcat (ldargs, " "); strcat (ldargs, arg); } } /* Load the program, searching all libraries. Use -r to save the output as a relocatable file. Examine the namelist with nm and search it for static constructors and destructors to call. Write the constructor and destructor tables to a .s file. */ sprintf (cmd, "ld -r -o %s %s && nm -p %s", codefile, ldargs, codefile); if (! (inf = popen (cmd, "r"))) fatal_perror ("Can't open pipe to ld"); if (! (outf = fopen (hooksfile, "w"))) fatal_perror ("Can't write %s", hooksfile); write_hooks (inf, outf); if (pclose (inf) || fclose (outf)) fatal ("load failed"); /* Assemble the constructor and destructor tables. Link the tables in with the rest of the program. */ sprintf (cmd, "as -o %s %s && ld -o %s %s %s && rm %s %s %s", hookofile, hooksfile, outfile, codefile, hookofile, codefile, hooksfile, hookofile); exit (system (cmd)); }
void init_intset(struct intset *set, int size) { set->size = size; set->fill_pointer = 0; set->items = malloc(size * sizeof(int)); if (!set->items) fatal_perror("malloc"); set->positions = calloc(size, sizeof(int)); if (!set->positions) fatal_perror("calloc"); }
/* create a directory and check its permissions */ static void create_dir( const char *name, struct stat *st ) { if (lstat( name, st ) == -1) { if (errno != ENOENT) fatal_perror( "lstat %s", name ); if (mkdir( name, 0700 ) == -1 && errno != EEXIST) fatal_perror( "mkdir %s", name ); if (lstat( name, st ) == -1) fatal_perror( "lstat %s", name ); } if (!S_ISDIR(st->st_mode)) fatal_error( "%s is not a directory\n", name ); if (st->st_uid != getuid()) fatal_error( "%s is not owned by you\n", name ); if (st->st_mode & 077) fatal_error( "%s must not be accessible by other users\n", name ); }
/* * Open connection to xenstore. * * @pollfds defines of signal-handling descriptors to be watched * if has to wait. * * Will not touch pollfds[NPFD_XS]. */ static void open_xs_connection(struct pollfd *pollfds) { struct timespec ts0; int64_t wsec; bool displayed_msg = false; int k; /* * If we are running as a daemon during system startup, there * can be a race condition with continuing Xen initialization * (/proc/xen including /proc/xen/privcmd may be unavailable yet, * still to be created even though Xen service startup completion * has already been signalled), so wait for a while if necessary. */ for (ts0 = getnow();;) { if (!xs) xs = xs_open(0); if (xs) break; /* time since the start */ wsec = timespec_diff_ms(getnow(), ts0) / MSEC_PER_SEC; if (run_as_daemon && wsec < max_xen_init_retries) { if (wsec >= xen_init_retry_msg && !displayed_msg) { notice_msg("waiting for Xen to initialize"); displayed_msg = true; } if (pollfds != NULL) { int npollfds = NPFD_COUNT - 1; for (k = 0; k < npollfds; k++) pollfds[k].revents = 0; if (poll(pollfds, npollfds, 1 * MSEC_PER_SEC) < 0) fatal_perror("poll"); handle_signals(pollfds, NULL); } else { sleep(1); } } else { fatal_perror("unable to open connection to xenstore"); } } }
/*********************************************************************** * setup_config_dir * * Setup the wine configuration dir. */ static void setup_config_dir(void) { const char *p, *config_dir = wine_get_config_dir(); if (chdir( config_dir ) == -1) { if (errno != ENOENT) fatal_perror( "chdir to %s\n", config_dir ); if ((p = strrchr( config_dir, '/' )) && p != config_dir) { struct stat st; char *tmp_dir; if (!(tmp_dir = malloc( p + 1 - config_dir ))) fatal_error( "out of memory\n" ); memcpy( tmp_dir, config_dir, p - config_dir ); tmp_dir[p - config_dir] = 0; if (!stat( tmp_dir, &st ) && st.st_uid != getuid()) fatal_error( "'%s' is not owned by you, refusing to create a configuration directory there\n", tmp_dir ); free( tmp_dir ); } mkdir( config_dir, 0777 ); if (chdir( config_dir ) == -1) fatal_perror( "chdir to %s\n", config_dir ); if ((p = getenv( "WINEARCH" )) && !strcmp( p, "win32" )) { /* force creation of a 32-bit prefix */ int fd = open( "system.reg", O_WRONLY | O_CREAT | O_EXCL, 0666 ); if (fd != -1) { static const char regfile[] = "WINE REGISTRY Version 2\n\n#arch=win32\n"; write( fd, regfile, sizeof(regfile) - 1 ); close( fd ); } } MESSAGE( "wine: created the configuration directory '%s'\n", config_dir ); } if (mkdir( "dosdevices", 0777 ) == -1) { if (errno == EEXIST) return; fatal_perror( "cannot create %s/dosdevices\n", config_dir ); } /* create the drive symlinks */ mkdir( "drive_c", 0777 ); symlink( "../drive_c", "dosdevices/c:" ); symlink( "/", "dosdevices/z:" ); }
/* * Read in the whole content of file @path into the buffer pointed by *@ppbuf, * as nul-terminated string. * Reallocate *@ppbuf if necessary to be large enough. * The size of the buffer is kept in *@psize. * Initial size of the buffer to use on first allocation is given by @initial_size. * Abort on error. */ static void read_whole_file(const char *path, char **ppbuf, size_t *psize, size_t initial_size) { ssize_t rsz; ssize_t rd; ssize_t rem; int fd = -1; if (*psize == 0) { *psize = initial_size; *ppbuf = malloc(*psize); if (!*ppbuf) out_of_memory(); } for (;;) { if (fd == -1) close (fd); fd = open(path, O_RDONLY); if (fd == -1) fatal_perror("unable to open file %s", path); rd = 0; for (;;) { rem = *psize - rd; if (rem <= 0) break; rsz = read(fd, *ppbuf, rem); if (rsz < 0) fatal_perror("unable to read file %s", path); if (rsz == 0) break; rd += rsz; } if (rd <= *psize - 1) { (*ppbuf)[rd] = '\0'; break; } *psize += *psize / 2; *ppbuf = realloc(*ppbuf, *psize); if (!*ppbuf) out_of_memory(); } close(fd); }
/* * Process expected signals */ static void handle_signals(struct pollfd *pollfds, bool *p_recheck_time) { struct signalfd_siginfo fdsi; ssize_t sz; /* SIGTERM - exit gracefully */ if (pollfds[NPFD_SIGTERM].revents & (POLLIN|POLLPRI)) { shutdown_xs(); notice_msg("terminating..."); exit(EXIT_SUCCESS); } /* SIGHUP - reload configuration */ if (pollfds[NPFD_SIGHUP].revents & (POLLIN|POLLPRI)) { sz = read(fd_sighup, &fdsi, sizeof(fdsi)); if (sz < 0) fatal_perror("read signalfd"); if (sz != sizeof(fdsi)) fatal_msg("read signalfd"); /* reload configuration -- currently none for memprobed */ if (p_recheck_time) *p_recheck_time = true; } }
/*********************************************************************** * start_server * * Start a new wine server. */ static void start_server(void) { static int started; /* we only try once */ char *argv[3]; static char wineserver[] = "server/wineserver"; static char debug[] = "-d"; if (!started) { int status; int pid = fork(); if (pid == -1) fatal_perror( "fork" ); if (!pid) { argv[0] = wineserver; argv[1] = TRACE_ON(server) ? debug : NULL; argv[2] = NULL; wine_exec_wine_binary( argv[0], argv, getenv("WINESERVER") ); fatal_error( "could not exec wineserver\n" ); } waitpid( pid, &status, 0 ); status = WIFEXITED(status) ? WEXITSTATUS(status) : 1; if (status == 2) return; /* server lock held by someone else, will retry later */ if (status) exit(status); /* server failed */ started = 1; } }
int main(int argc, char *argv[]) { int i; unsigned char *ptrs[TOTAL_PAGES]; parse_args(argc, argv); for (i = 0; i < TOTAL_PAGES; i++) { ptrs[i] = malloc(PAGE_SIZE); if (ptrs[i] == NULL) fatal_perror("simple_multi_malloc: malloc"); /* Touch page. */ ptrs[i][0] = 'x'; } summarise(NULL); block(); /* Not strictly necessary, but good habit to free regardless. */ for (i = 0; i < TOTAL_PAGES; i++) free(ptrs[i]); return EXIT_SUCCESS; }
static char * xreadall(int fd) { size_t nread = 0; size_t alloc = BUFSIZ; char *buf = xreallocarray(0, alloc, 1); for (;;) { ssize_t count = read(fd, buf + nread, alloc - nread); if (count == 0) break; if (count < 0) fatal_perror("read"); nread += (size_t)count; while (nread >= alloc) { alloc *= 2; buf = xreallocarray(buf, alloc, 1); } } buf = xreallocarray(buf, nread+1, 1); buf[nread] = '\0'; return buf; }
/*********************************************************************** * server_init_process * * Start the server and create the initial socket pair. */ void server_init_process(void) { obj_handle_t dummy_handle; const char *env_socket = getenv( "WINESERVERSOCKET" ); if (env_socket) { fd_socket = atoi( env_socket ); if (fcntl( fd_socket, F_SETFD, 1 ) == -1) fatal_perror( "Bad server socket %d", fd_socket ); unsetenv( "WINESERVERSOCKET" ); } else fd_socket = server_connect(); /* setup the signal mask */ sigemptyset( &server_block_set ); sigaddset( &server_block_set, SIGALRM ); sigaddset( &server_block_set, SIGIO ); sigaddset( &server_block_set, SIGINT ); sigaddset( &server_block_set, SIGHUP ); sigaddset( &server_block_set, SIGUSR1 ); sigaddset( &server_block_set, SIGUSR2 ); sigaddset( &server_block_set, SIGCHLD ); pthread_functions.sigprocmask( SIG_BLOCK, &server_block_set, NULL ); /* receive the first thread request fd on the main socket */ ntdll_get_thread_data()->request_fd = receive_fd( &dummy_handle ); #ifdef __APPLE__ send_server_task_port(); #endif }
static void runv_ignore_failure(const char *const *argv) { pid_t pid = xspawnvp(argv); int status; if (waitpid(pid, &status, 0) != pid) fatal_perror("waitpid"); }
static void * xreallocarray(void *optr, size_t nmemb, size_t size) { /* s1*s2 <= SIZE_MAX if both s1 < K and s2 < K where K = sqrt(SIZE_MAX+1) */ const size_t MUL_NO_OVERFLOW = ((size_t)1) << (sizeof(size_t) * 4); if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && nmemb > 0 && SIZE_MAX / nmemb < size) { errno = ENOMEM; fatal_perror("malloc"); } void *rv = realloc(optr, size * nmemb); if (!rv) fatal_perror("malloc"); return rv; }
static pid_t spawn_with_redir(const char *const *argv, int child_stdin, int child_stdout) { fflush(0); pid_t child = fork(); if (child == -1) fatal_perror("fork"); if (child != 0) return child; /* to the parent */ /* We are the child. The parent has arranged for it to be safe for us to write to stderr under error conditions, but the cleanup handler should not do anything. */ controller_cleanups = false; up_script_cleanups = false; /* Child-side stdin and stdout redirections. */ if (child_stdin != 0) { if (close(0)) fatal_perror("close"); if (child_stdin < 0) { if (open("/dev/null", O_RDONLY) != 0) fatal_perror("open"); } else { if (dup(child_stdin) != 0) fatal_perror("dup"); } } if (child_stdout != 1) { if (close(1)) fatal_perror("close"); if (child_stdout < 1) { if (open("/dev/null", O_WRONLY) != 1) fatal_perror("open"); } else { if (dup(child_stdout) != 1) fatal_perror("dup"); } } become_only_root(); if (sigprocmask(SIG_SETMASK, &child_sigmask, 0)) fatal_perror("sigprocmask"); execvpe(argv[0], (char *const *)argv, (char *const *)child_env); fatal_perror("execvpe"); }
static void runv(const char *const *argv) { pid_t pid = xspawnvp(argv); int status; if (waitpid(pid, &status, 0) != pid) fatal_perror("waitpid"); fatal_if_unsuccessful_child(argv[0], status); }
static char * PRINTFLIKE xasprintf(const char *fmt, ...) { char *rv; va_list ap; va_start(ap, fmt); if (vasprintf(&rv, fmt, ap) == -1) fatal_perror("asprintf"); return rv; }
/* * Socket file with the same name already exists. * If another instance of membalanced is already running, abort. * Otherwise delete leftover file, and let the caller retry again. */ static void on_addrinuse(const struct sockaddr_un& addr) { int fd; int rc; DO_RESTARTABLE(fd, socket(AF_UNIX, SOCK_STREAM, 0)); if (fd == -1) fatal_perror("unable to create RPC socket"); DO_RESTARTABLE(rc, connect(fd, (struct sockaddr*)&addr, sizeof addr)); if (rc == 0) fatal_msg("membalanced is already running and owns RPC socket"); if (errno != ECONNREFUSED) fatal_perror("socket file %s in a bad state", socket_path); /* socket exists, but no one is lisening on it */ if (unlink(socket_path) && errno != ENOENT) fatal_perror("unable to delete socket file %s", socket_path); }
struct intset *make_intset(int size) { struct intset *set; set = malloc(sizeof(struct intset)); if (!set) fatal_perror("malloc"); init_intset(set, size); return set; }
static int start_ptraced_child(void) { int pid, n, status; pid = fork(); if (pid == 0) ptrace_child(); else if (pid < 0) fatal_perror("start_ptraced_child : fork failed"); CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); if (n < 0) fatal_perror("check_ptrace : waitpid failed"); if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) fatal("check_ptrace : expected SIGSTOP, got status = %d", status); return pid; }
/*********************************************************************** * server_init_process * * Start the server and create the initial socket pair. */ void server_init_process(void) { obj_handle_t version; const char *env_socket = getenv( "WINESERVERSOCKET" ); server_pid = -1; if (env_socket) { fd_socket = atoi( env_socket ); if (fcntl( fd_socket, F_SETFD, 1 ) == -1) fatal_perror( "Bad server socket %d", fd_socket ); unsetenv( "WINESERVERSOCKET" ); } else fd_socket = server_connect(); /* setup the signal mask */ sigemptyset( &server_block_set ); sigaddset( &server_block_set, SIGALRM ); sigaddset( &server_block_set, SIGIO ); sigaddset( &server_block_set, SIGINT ); sigaddset( &server_block_set, SIGHUP ); sigaddset( &server_block_set, SIGUSR1 ); sigaddset( &server_block_set, SIGUSR2 ); sigaddset( &server_block_set, SIGCHLD ); pthread_sigmask( SIG_BLOCK, &server_block_set, NULL ); /* receive the first thread request fd on the main socket */ #ifdef SO_PASSCRED if (server_pid == -1) { int enable = 1; setsockopt( fd_socket, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable) ); ntdll_get_thread_data()->request_fd = receive_fd( &version ); enable = 0; setsockopt( fd_socket, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable) ); } else #endif ntdll_get_thread_data()->request_fd = receive_fd( &version ); if (version != SERVER_PROTOCOL_VERSION) server_protocol_error( "version mismatch %d/%d.\n" "Your %s binary was not upgraded correctly,\n" "or you have an older one somewhere in your PATH.\n" "Or maybe the wrong wineserver is still running?\n", version, SERVER_PROTOCOL_VERSION, (version > SERVER_PROTOCOL_VERSION) ? "wine" : "wineserver" ); #ifdef __APPLE__ send_server_task_port(); #endif #if defined(__linux__) && defined(HAVE_PRCTL) /* work around Ubuntu's ptrace breakage */ if (server_pid != -1) prctl( 0x59616d61 /* PR_SET_PTRACER */, server_pid ); #endif }
/* * Get current timestamp. * Preserves previous value of errno. */ static struct timespec getnow(void) { int sv_errno = errno; struct timespec ts; if (clock_gettime(clk_id, &ts)) fatal_perror("clock_gettime"); errno = sv_errno; return ts; }
/* create the lock file and return its file descriptor */ static int create_server_lock(void) { struct stat st; int fd; if (lstat( server_lock_name, &st ) == -1) { if (errno != ENOENT) fatal_perror( "lstat %s/%s", wine_get_server_dir(), server_lock_name ); } else { if (!S_ISREG(st.st_mode)) fatal_error( "%s/%s is not a regular file\n", wine_get_server_dir(), server_lock_name ); } if ((fd = open( server_lock_name, O_CREAT|O_TRUNC|O_WRONLY, 0600 )) == -1) fatal_perror( "error creating %s/%s", wine_get_server_dir(), server_lock_name ); return fd; }
void socket_set_nonblocking(int fd, int val) { int flags, res; /* get old flags */ flags = fcntl(fd, F_GETFL, 0); if (flags < 0) fatal_perror("fcntl(F_GETFL)"); /* flip O_NONBLOCK */ if (val) flags |= O_NONBLOCK; else flags &= ~O_NONBLOCK; /* set new flags */ res = fcntl(fd, F_SETFL, flags); if (res < 0) fatal_perror("fcntl(F_SETFL)"); }
static char * runv_get_output(const char *const *argv) { int pipefds[2]; if (pipe2(pipefds, O_CLOEXEC)) fatal_perror("pipe"); pid_t pid = spawn_with_redir(argv, -1, pipefds[1]); close(pipefds[1]); char *output = xreadall(pipefds[0]); close(pipefds[0]); int status; if (waitpid(pid, &status, 0) != pid) fatal_perror("waitpid"); fatal_if_unsuccessful_child(argv[0], status); return output; }
int output( const char *format, ... ) { int ret; va_list valist; va_start( valist, format ); ret = vfprintf( output_file, format, valist ); va_end( valist ); if (ret < 0) fatal_perror( "Output error" ); return ret; }
static NORETURN fatal_regerror(const char *msg, int errcode, const regex_t *offender) { size_t req = regerror(errcode, offender, 0, 0); char *errbuf = malloc(req); if (!errbuf) fatal_perror("malloc"); regerror(errcode, offender, errbuf, req); fprintf(stderr, "%s: %s: %s\n", progname, msg, errbuf); exit(1); }
static int configuration_file_exists(const char *fname) { struct stat tmpbuf; int status = stat(fname, &tmpbuf); int result = status ? 0 : 1; /* must invert result: 0 => true, !0 => false */ if (status < 0) fatal_perror(fname); return result; }
/*********************************************************************** * setup_config_dir * * Setup the wine configuration dir. */ static void setup_config_dir(void) { const char *p, *config_dir = wine_get_config_dir(); if (chdir( config_dir ) == -1) { if (errno != ENOENT) fatal_perror( "chdir to %s\n", config_dir ); if ((p = strrchr( config_dir, '/' )) && p != config_dir) { struct stat st; char *tmp_dir; if (!(tmp_dir = malloc( p + 1 - config_dir ))) fatal_error( "out of memory\n" ); memcpy( tmp_dir, config_dir, p - config_dir ); tmp_dir[p - config_dir] = 0; if (!stat( tmp_dir, &st ) && st.st_uid != getuid()) fatal_error( "'%s' is not owned by you, refusing to create a configuration directory there\n", tmp_dir ); free( tmp_dir ); } mkdir( config_dir, 0777 ); if (chdir( config_dir ) == -1) fatal_perror( "chdir to %s\n", config_dir ); MESSAGE( "wine: created the configuration directory '%s'\n", config_dir ); } if (mkdir( "dosdevices", 0777 ) == -1) { if (errno == EEXIST) return; fatal_perror( "cannot create %s/dosdevices\n", config_dir ); } /* create the drive symlinks */ mkdir( "drive_c", 0777 ); symlink( "../drive_c", "dosdevices/c:" ); symlink( "/", "dosdevices/z:" ); }