void run(t_params const* params) { int fd; pid_t master; pid_t ptyfk; struct termios term; fd = open(params->file, O_WRONLY | O_CREAT | (params->append == 1 ? O_APPEND : O_TRUNC), 0644); if (fd == -1) xperror(); ptyfk = my_forkpty(&master, NULL); if (ptyfk == -1) xperror(); if (ptyfk == 0) { dup2_fd(master); execl(params->shell, params->shell, NULL); exit(0); } update_win_size(master); signal(SIGWINCH, handle_resize); remove_block(master, 0); init_term(&term); printf("Script started, file is %s\n", params->file); read_input(ptyfk, master, fd); restore_term(&term); close(fd); printf("Script done, file is %s\n", params->file); }
void init_term(struct termios* term) { if (tcgetattr(0, term) == -1) xperror(); term->c_lflag &= ~(ECHO | ICANON | ISIG | IEXTEN); if (tcsetattr(0, TCSANOW, term) == -1) xperror(); }
/** * Perform the server's mission * * @return Non-zero on error */ int master_loop(void) { int rc = 1, r; while (!reexecing && !terminating) { if (switching_vt) { int leaving = switching_vt == 1; switching_vt = 0; r = switch_vt(leaving); } else if (r = mds_message_read(&received, socket_fd), r == 0) r = handle_message(); if (r == 0) continue; if (r == -2) { eprint("corrupt message received, aborting."); goto done; } else if (errno == EINTR) continue; else fail_if (errno != ECONNRESET); eprint("lost primary connection to server."); mds_message_destroy(&received); mds_message_initialise(&received); connected = 0; fail_if (reconnect_to_display()); connected = 1; } rc = 0; if (vt_set_exclusive(display_tty_fd, 0) < 0) xperror(*argv); if (vt_set_graphical(display_tty_fd, 0) < 0) xperror(*argv); if (unlink(vtfile_path) < 0) xperror(*argv); vt_close(display_tty_fd, &old_vt_stat); goto done; fail: xperror(*argv); done: rc |= secondary_thread_failed; if (rc || !reexecing) mds_message_destroy(&received); if ((errno = pthread_join(secondary_thread, NULL))) xperror(*argv); return rc; }
/* * Go to the /devices directory and recursively find all * the device special files (with the handy library function * nftw). nftw() will call devices_entry() which will put * the entry in the hash table. After we find all the * entries allocate a table and put pointers in it so * we can sort the entries. */ static void get_devices(void) { char *dir; int i; struct devices_ent *dep, **pht, **pdep; dir = root_name("/devices"); if (chdir(dir) == -1) { xperror(dir); exit(1); } /* * Errors related to access permissions are handled * by devices_entry() and devices_entry doesn't return * non-zero so the only thing left is some other type * of error. */ if (nftw(".", devices_entry, depth, FTW_PHYS) == -1) xperror("nftw()"); devices_list = xmalloc(sizeof (struct devices_ent *) * num_devices_ents); pdep = devices_list; pht = de_hashtab; for (i = 0; i < HASHSIZE; i++) { dep = *pht; while (dep != NULL) { *pdep++ = dep; dep = dep->next; } pht++; } /* * After all the /devices entries are put in the hash * table we sort the entries. We do this for two * reasons: the rule functions may count on the order of * devices it is called with (like the cdrom stuff in * rule_sd) and if the rules create overlapping names the * links will be made in an order based on sorted entries * rather than be dependent on the order the entries * happen to be in in a directory. */ qsort((void *) devices_list, num_devices_ents, sizeof (struct devices_ent *), dcomp); }
void update_win_size(int fd) { struct winsize win; int term; static int _fd = 0; if (fd != 0) _fd = fd; if ((term = open("/dev/tty", O_RDONLY | O_NONBLOCK)) < 0) xperror(); if (ioctl(term, TIOCGWINSZ, &win) == -1) xperror(); if (ioctl(_fd, TIOCSWINSZ, &win) == -1) xperror(); }
void remove_block(int fd1, int fd2) { int flags; flags = 0; if (fcntl(fd1, F_GETFL, &flags) == -1) xperror(); if (fcntl(fd1, F_SETFL, flags | O_NONBLOCK) == -1) xperror(); flags = 0; if (fcntl(fd2, F_GETFL, &flags) == -1) xperror(); if (fcntl(fd2, F_SETFL, flags | O_NONBLOCK) == -1) xperror(); }
/** Play an audio track. */ static bool play_track(track_t i_start_track, track_t i_end_track) { bool b_ok = true; char line[80]; if (!b_cd) { read_toc(p_cdio); } read_subchannel(p_cdio); if (!b_cd || i_first_track == CDIO_CDROM_LEADOUT_TRACK) return false; if (debug) fprintf(stderr,"play tracks: %d-%d => ", i_start_track, i_end_track-1); if (i_start_track < i_first_track) i_start_track = i_first_track; if (i_start_track > i_last_audio_track) i_start_track = i_last_audio_track; if (i_end_track < i_first_track) i_end_track = i_first_track; if (i_end_track > i_last_audio_track) i_end_track = i_last_audio_track; i_end_track++; if (debug) fprintf(stderr,"%d-%d\n",i_start_track, i_end_track-1); cd_pause(p_cdio); snprintf(line, sizeof(line), "play track %d to track %d.", i_start_track, i_end_track-1); action(line); b_ok = (DRIVER_OP_SUCCESS == cdio_audio_play_msf(p_cdio, &(toc[i_start_track]), &(toc[i_end_track])) ); if (!b_ok) xperror("play"); return b_ok; }
/*! Play an audio track. */ static bool play_track(track_t i_start_track, track_t i_end_track) { bool b_ok = true; if (!b_cd) { cd_close(psz_device); read_toc(p_cdio); } read_subchannel(p_cdio); if (!b_cd || i_first_track == CDIO_CDROM_LEADOUT_TRACK) return false; if (debug) fprintf(stderr,"play tracks: %d-%d => ", i_start_track, i_end_track); if (i_start_track < i_first_track) i_start_track = i_first_track; if (i_start_track > i_last_audio_track) i_start_track = i_last_audio_track; if (i_end_track < i_first_track) i_end_track = i_first_track; if (i_end_track > i_last_audio_track) i_end_track = i_last_audio_track; if (debug) fprintf(stderr,"%d-%d\n",i_start_track, i_end_track); cd_pause(p_cdio); b_ok = (DRIVER_OP_SUCCESS == cdio_audio_play_msf(p_cdio, &(toc[i_start_track]), &(toc[i_end_track])) ); if (!b_ok) xperror("play"); return b_ok; }
/** * This function should initialise the server, * and it not invoked after a re-exec. * * @return Non-zero on error */ int initialise_server(void) { int stage = 0; const char* const message = "Command: intercept\n" "Message ID: 0\n" "Length: 62\n" "\n" "Command: list-colours\n" "Command: get-colour\n" "Command: set-colour\n"; fail_if (full_send(message, strlen(message))); fail_if (server_initialised() < 0); stage++;; fail_if (colour_list_create(&colours, 64) < 0); stage++; fail_if (mds_message_initialise(&received)); return 0; fail: xperror(*argv); if (stage >= 2) colour_list_destroy(&colours); if (stage >= 1) mds_message_destroy(&received); return 1; }
/* FATAL */ void GAP_ERROR_FATAL(char *reason, ...) { char buf[8192]; va_list args; va_start(args, reason); vsprintf(buf, reason, args); xperror(buf, xperror_out_func); if (gap_fatal_errors) { char *msg = "Gap4 has found an unrecoverable error - These are usually bugs.\nPlease email all bug reports to [email protected].\n"; #ifdef _WIN32 /* 11/1/99 johnt - WINNT will not have stdout/err defined unless running in console mode * so use a message box */ if( fileno(stderr) == -1 ){ MessageBox(NULL,buf,"Gap4 Error",MB_OK|MB_ICONERROR|MB_TASKMODAL); return; } #endif fprintf(stderr,msg); signal(SIGSEGV, SIG_DFL); /* 11/1/99 johnt - No SIGBUS on WINNT */ #if defined(SIGBUS) signal(SIGBUS, SIG_DFL); #endif stack_trace(); *((int *)0) = 88; abort(); } else { verror(ERR_FATAL, "NOTE ", "Continue at own risk!"); } }
static bool toggle_pause() { bool b_ok = true; if (!b_cd) return false; if (CDIO_MMC_READ_SUB_ST_PAUSED == sub.audio_status) { b_ok = DRIVER_OP_SUCCESS != cdio_audio_resume(p_cdio); if (!b_ok) xperror("resume"); } else { b_ok = DRIVER_OP_SUCCESS != cdio_audio_pause(p_cdio); if (!b_ok) xperror("pause"); } return b_ok; }
void *xrealloc(void *ptr, size_t size) { ptr = realloc(ptr, size); if (ptr == NULL) xperror("realloc"); return ptr; }
static void exec_script(char **argv) { argv[0] = SCRIPT; if (execv(SCRIPT, argv) == -1) xperror(gettext("cannot execute " SCRIPT)); exit(1); }
/*! Read CD TOC and set CD information. */ static void read_toc(CdIo_t *p_cdio) { track_t i; i_first_track = cdio_get_first_track_num(p_cdio); i_last_track = cdio_get_last_track_num(p_cdio); i_tracks = cdio_get_num_tracks(p_cdio); i_first_audio_track = i_first_track; i_last_audio_track = i_last_track; if ( CDIO_INVALID_TRACK == i_first_track || CDIO_INVALID_TRACK == i_last_track ) { xperror("read toc header"); b_cd = false; b_record = false; } else { b_cd = true; i_data = 0; for (i = i_first_track; i <= i_last_track+1; i++) { if ( !cdio_get_track_msf(p_cdio, i, &(toc[i])) ) { xperror("read toc entry"); b_cd = false; return; } if ( TRACK_FORMAT_AUDIO != cdio_get_track_format(p_cdio, i) ) { if ((i != i_last_track+1) ) { i_data++; if (i == i_first_track) { if (i == i_last_track) i_first_audio_track = CDIO_CDROM_LEADOUT_TRACK; else i_first_audio_track++; } } } } b_record = true; read_subchannel(p_cdio); if (auto_mode && sub.audio_status != CDIO_MMC_READ_SUB_ST_PLAY) play_track(1, CDIO_CDROM_LEADOUT_TRACK); } }
/* NOT FATAL */ void GAP_ERROR(char *reason, ...) { char buf[8192]; va_list args; va_start(args, reason); vsprintf(buf, reason, args); xperror(buf, xperror_out_func); }
void *xmalloc(size_t size) { void *ptr; ptr = malloc(size); if (ptr == NULL) xperror("malloc"); return ptr; }
/* * Go to the /dev directory and recursively find all the * symlinks. nftw() will call dev_entry() which will put * the entry in the hash table. */ static void get_dev_links(void) { char *devdir; devdir = root_name("/dev"); if (chdir(devdir) == -1) { xperror(devdir); exit(1); } /* * Errors related to access permissions are handled * by dev_entry() and dev_entry doesn't return non-zero * so the only thing left is some other type of error. */ if (nftw(".", dev_entry, depth, FTW_PHYS) == -1) xperror("nftw()"); }
/*! Pause playing audio CD */ static bool cd_pause(CdIo_t *p_cdio) { bool b_ok = true; if (sub.audio_status == CDIO_MMC_READ_SUB_ST_PLAY) { b_ok = DRIVER_OP_SUCCESS == cdio_audio_pause(p_cdio); if (!b_ok) xperror("pause"); } return b_ok; }
/*! Close CD tray */ static bool cd_close(const char *psz_device) { bool b_ok = true; if (!b_cd) { b_ok = DRIVER_OP_SUCCESS == cdio_close_tray(psz_device, &driver_id); if (!b_ok) xperror("close"); } return b_ok; }
/*! Stop playing audio CD */ static bool cd_stop(CdIo_t *p_cdio) { bool b_ok = true; if (b_cd && p_cdio) { i_last_audio_track = CDIO_INVALID_TRACK; b_ok = DRIVER_OP_SUCCESS == cdio_audio_stop(p_cdio); if ( !b_ok ) xperror("stop"); } return b_ok; }
/** * Perform the server's mission * * @return Non-zero on error */ int master_loop(void) { int rc = 1, r; while (!reexecing && !terminating) { if (danger) { danger = 0; free(send_buffer); send_buffer = NULL; send_buffer_size = 0; colour_list_pack(&colours); free(colour_list_buffer_without_values); colour_list_buffer_without_values = NULL; free(colour_list_buffer_with_values); colour_list_buffer_with_values = NULL; } if (!(r = mds_message_read(&received, socket_fd))) if (!(r = handle_message())) continue; if (r == -2) { eprint("corrupt message received, aborting."); goto done; } else if (errno == EINTR) { continue; } else { fail_if (errno != ECONNRESET); } eprint("lost connection to server."); mds_message_destroy(&received); mds_message_initialise(&received); connected = 0; fail_if (reconnect_to_display()); connected = 1; } rc = 0; goto done; fail: xperror(*argv); done: if (rc || !reexecing) { mds_message_destroy(&received); colour_list_destroy(&colours); } free(send_buffer); free(colour_list_buffer_without_values); free(colour_list_buffer_with_values); return rc; }
/* * Create a symlink called compat_link that points to target. * If it already exists correctly don't do anything. If it * exists but is incorrect, delete the link and make it. If * it doesn't exist just make it. */ static void make_link( char *compat_link, char *target, struct symlink *compat_slp, int link_type) { if (compat_slp->target != NULL) { if (strcmp(target, compat_slp->target) == 0) { if (debug) (void) printf("already %s -> %s\n", compat_link, compat_slp->target); update_db(compat_link, target, link_type); return; } else { if (debug) (void) printf("remove %s, link wrong (%s)\n", compat_link, compat_slp->target); else { if (unlink(compat_link) == -1) xperror(compat_link); else (void) di_devlink_rm_link(link_handle, compat_link); } compat_slp->target = target; } } else compat_slp->target = target; if (debug) (void) printf("link %s -> %s\n", compat_link, target); else { if (symlink(target, compat_link) == -1) xperror(compat_link); else update_db(compat_link, target, link_type); } }
/*! Eject CD */ static bool cd_eject(void) { bool b_ok = true; if (p_cdio) { cd_stop(p_cdio); b_ok = DRIVER_OP_SUCCESS == cdio_eject_media(&p_cdio); if (!b_ok) xperror("eject"); b_cd = false; p_cdio = NULL; } return b_ok; }
/** * Unmarshal server implementation specific data and update the servers state accordingly * * On critical failure the program should `abort()` or exit by other means. * That is, do not let `reexec_failure_recover` run successfully, if it unrecoverable * error has occurred or one severe enough that it is better to simply respawn. * * @param state_buf The marshalled data that as not been read already * @return Non-zero on error */ int unmarshal_server(char *state_buf) { /* buf_get_next(state_buf, int, MDS_ECHO_VARS_VERSION); */ buf_next(state_buf, int, 1); buf_get_next(state_buf, int, connected); buf_get_next(state_buf, uint32_t, message_id); fail_if (mds_message_unmarshal(&received, state_buf)); return 0; fail: xperror(*argv); mds_message_destroy(&received); return -1; }
/*! Get status/track/position info of an audio CD */ static bool read_subchannel(CdIo_t *p_cdio) { bool b_ok = true; if (!b_cd) return false; b_ok = DRIVER_OP_SUCCESS == cdio_audio_read_subchannel(p_cdio, &sub); if (!b_ok) { xperror("read subchannel"); b_cd = 0; } if (auto_mode && sub.audio_status == CDIO_MMC_READ_SUB_ST_COMPLETED) cd_eject(); return b_ok; }
/** Eject CD */ static bool cd_eject(void) { bool b_ok = true; if (p_cdio_global) { cd_stop(p_cdio_global); action("eject..."); b_ok = DRIVER_OP_SUCCESS == cdio_eject_media(&p_cdio_global); if (!b_ok) xperror("eject"); b_cd = false; cdio_destroy (p_cdio_global); p_cdio_global = NULL; } return b_ok; }
/** * Wait for confirmation that we may switch virtual terminal * * @param data Thread input parameter, will always be `NULL` * @return Thread return value, will always be `NULL` */ void* secondary_loop(void* data) { mds_message_t secondary_received; int r; (void) data; secondary_thread_started = 1; fail_if (mds_message_initialise(&secondary_received) < 0); while (!reexecing && !terminating) { if (r = mds_message_read(&secondary_received, secondary_socket_fd), r == 0) r = vt_accept_switch(display_tty_fd); if (r == 0) continue; if (r == -2) { eprint("corrupt message received, aborting."); secondary_thread_failed = 1; goto done; } else if (errno == EINTR) continue; else fail_if (errno != ECONNRESET); eprint("lost secondary connection to server."); mds_message_destroy(&secondary_received); mds_message_initialise(&secondary_received); fail_if (reconnect_fd_to_display(&secondary_socket_fd) < 0); } goto done; fail: xperror(*argv); secondary_thread_failed = 1; done: secondary_thread_started = 0; mds_message_destroy(&secondary_received); if (!reexecing && !terminating) pthread_kill(master_thread, SIGTERM); return NULL; }
/** This routine is called by vcd routines on error. Setup is done by init_input_plugin. */ static void cddb_log_handler (cddb_log_level_t level, const char message[]) { switch (level) { case CDDB_LOG_DEBUG: case CDDB_LOG_INFO: if (!b_verbose) return; /* Fall through if to warn case */ case CDDB_LOG_WARN: case CDDB_LOG_ERROR: case CDDB_LOG_CRITICAL: default: xperror(message); break; } /* gl_default_cdio_log_handler (level, message); */ }
/* ARGSUSED2 */ static int dev_entry(const char *name, const struct stat *sp, int flags, struct FTW *ftwp) { int type; char target[MAXPATHLEN + 1]; int targetlen; struct symlink *slp; if (flags == FTW_NS) { /* couldn't stat the file */ (void) fprintf(stderr, gettext("%s: cannot stat %s\n"), progname, name); return (0); } if (flags == FTW_DNR) { /* couldn't read a directory */ (void) fprintf(stderr, gettext("%s: cannot read " "directory %s\n"), progname, name); return (0); } type = sp->st_mode & S_IFMT; if (type != S_IFLNK) return (0); name += 2; /* skip "./" */ targetlen = readlink(name, target, sizeof (target)); if (targetlen == -1) xperror(name); target[targetlen] = '\0'; slp = xmalloc(sizeof (struct symlink)); slp->linkname = xstrdup(name); slp->target = xstrdup(target); slp->already = 0; insert_link_sym(slp); check_link(slp); return (0); }
/** * This function should initialise the server, * and it not invoked after a re-exec. * * @return Non-zero on error */ int initialise_server(void) { int stage = 0; const char* const message = "Command: intercept\n" "Message ID: 0\n" "Length: 14\n" "\n" "Command: echo\n"; fail_if (full_send(message, strlen(message))); fail_if (server_initialised() < 0); stage++; fail_if (mds_message_initialise(&received)); return 0; fail: xperror(*argv); if (stage == 1) mds_message_destroy(&received); return 1; }