unsigned int freerdp_kbd_init(unsigned int keyboard_layout_id) { char xkbfile[256]; keyboard_layout_id = detect_keyboard(keyboard_layout_id, xkbfile, sizeof(xkbfile)); printf("Using keyboard layout 0x%X with xkb name %s and xkbfile %s\n", keyboard_layout_id, get_layout_name(keyboard_layout_id), xkbfile); load_keyboard_map(xkbfile); return keyboard_layout_id; }
unsigned int freerdp_kbd_init(void* dpy, unsigned int keyboard_layout_id) { memset(x_keycode_to_rdp_scancode, 0, sizeof(x_keycode_to_rdp_scancode)); memset(rdp_scancode_to_x_keycode, '\0', sizeof(rdp_scancode_to_x_keycode)); #ifdef WITH_XKBFILE if (!init_xkb(dpy)) { DEBUG_KBD("Error initializing xkb"); return 0; } if (keyboard_layout_id == 0) { keyboard_layout_id = detect_keyboard_layout_from_xkb(dpy); DEBUG_KBD("detect_keyboard_layout_from_xkb: %X", keyboard_layout_id); } init_keycodes_from_xkb(dpy, x_keycode_to_rdp_scancode, rdp_scancode_to_x_keycode); #else int vkcode; int keycode; char xkbfile[256]; KeycodeToVkcode keycodeToVkcode; if (keyboard_layout_id == 0) keyboard_layout_id = detect_keyboard(dpy, keyboard_layout_id, xkbfile, sizeof(xkbfile)); DEBUG_KBD("Using keyboard layout 0x%X with xkb name %s and xkbfile %s", keyboard_layout_id, get_layout_name(keyboard_layout_id), xkbfile); load_keyboard_map(keycodeToVkcode, xkbfile); for (keycode = 0; keycode < 256; keycode++) { vkcode = keycodeToVkcode[keycode]; DEBUG_KBD("X keycode %3d VK %3d %-19s-> RDP scancode %d/%d", keycode, vkcode, virtualKeyboard[vkcode].name, virtualKeyboard[vkcode].extended, virtualKeyboard[vkcode].scancode); x_keycode_to_rdp_scancode[keycode].keycode = virtualKeyboard[vkcode].scancode; x_keycode_to_rdp_scancode[keycode].extended = virtualKeyboard[vkcode].extended; x_keycode_to_rdp_scancode[keycode].keyname = virtualKeyboard[vkcode].name; if (x_keycode_to_rdp_scancode[keycode].extended) rdp_scancode_to_x_keycode[virtualKeyboard[vkcode].scancode][1] = keycode; else rdp_scancode_to_x_keycode[virtualKeyboard[vkcode].scancode][0] = keycode; } #endif return keyboard_layout_id; }
/* * Main function for doing the copying of bits */ int TM_perform_transfer(nvlist_t *targs, void(*prog)(int)) { char *logfile = NULL, *buf = NULL, *cprefix; char *buf1 = NULL, *layout = NULL, *dbg; FILE *cpipe = NULL, *kbd_file; float ipercent, rem_percent, cpfiles; float calc_factor; int kbd = -1, kbd_layout; int rv = 0, i; struct file_list flist, *cflist; clock_t tm; struct stat st; char zerolist[PATH_MAX]; if (pthread_mutex_lock(&tran_mutex) != 0) { Perror("Unable to acquire Transfer lock "); return (1); } if (nvlist_lookup_string(targs, "mountpoint", &mntpt) != 0) { Perror("Alternate root mountpoint not provided. Bailing. "); return (1); } if (prog == NULL) { progress = log_progress; } else { progress = prog; } logfile = malloc(PATH_MAX); if (logfile == NULL) { Perror("Malloc failed "); return (1); } (void) snprintf(logfile, PATH_MAX, "%s/%s", mntpt, TM_LOGFILE_NAME); lof = fopen(logfile, "w+"); if (lof == NULL) { Perror("Unable to open logfile "); goto error_done; } buf = malloc(BUF_SIZE); if (buf == NULL) { Perror("Malloc failed "); goto error_done; } buf1 = malloc(BUF_SIZE); if (buf1 == NULL) { Perror("Malloc failed "); goto error_done; } dbg = getenv("TM_DEBUG"); if (dbg != NULL && strcmp(dbg, "1") == 0) { TM_enable_debug(); } /* * Set TMPDIR to avoid cpio depleting ramdisk space */ if (putenv(tmpenv) != 0) { Perror(tmpenv); goto error_done; } /* * Zero length file list. */ (void) strlcpy(zerolist, mntpt, PATH_MAX); (void) strlcat(zerolist, "/flist.0length", PATH_MAX); if ((zerolength = fopen(zerolist, "w+")) == NULL) { Perror(zerolist); goto error_done; } tm = time(NULL); (void) strftime(buf, PATH_MAX, (char *)0, localtime(&tm)); INFO_MSG2("-- Starting transfer process, %s --", buf); (void) chdir("/"); CHECK_ABORT; (*progress)(0); percent = 0; opercent = 0; total_find_percent = (NUM_PREFIXES - 1) * FIND_PERCENT; /* * Get the optimized libc overlay out of the way. */ if (umount("/lib/libc.so.1") != 0) { if (errno != EINVAL) { Perror("Can't unmount /lib/libc.so.1 "); goto error_done; } } CHECK_ABORT; INFO_MSG1("Building file lists for cpio"); /* * Do a file tree walk of all the mountpoints provided and * build up pathname lists. Pathname lists of all mountpoints * under the same prefix are aggregated in the same file to * reduce the number of cpio invocations. * * This loop builds a linked list where each entry points to * a file containing a pathname list and mentions other info * like the mountpoint from which to copy etc. */ cprefix = ""; flist.next = NULL; cflist = &flist; for (i = 0; cpio_prefixes[i].chdir_prefix != NULL; i++) { char *patt; regex_t re; CHECK_ABORT; DBG_MSG3("Cpio dir: %s, Chdir to: %s", cpio_prefixes[i].cpio_dir, cpio_prefixes[i].chdir_prefix); patt = cpio_prefixes[i].match_pattern; if (strcmp(cprefix, cpio_prefixes[i].chdir_prefix) != 0 || patt != NULL || cpio_prefixes[i].clobber_files == 1 || cpio_prefixes[i].cpio_args != NULL) { cprefix = cpio_prefixes[i].chdir_prefix; cflist->next = (struct file_list *) malloc(sizeof (struct file_list)); cflist = cflist->next; cflist->next = NULL; (void) snprintf(cflist->name, PATH_MAX, "%s/flist%d", mntpt, i); DBG_MSG2(" File list tempfile: %s", cflist->name); cflist->handle = fopen(cflist->name, "w+"); if (cflist->handle == NULL) { Perror("Unable to open file list "); goto error_done; } cflist->chdir_prefix = cpio_prefixes[i].chdir_prefix; if (patt != NULL) { DBG_MSG2(" Compiling regexp: %s", patt); if (patt[0] == '!') { negate = 1; patt++; } else { negate = 0; } if (regcomp(&re, patt, REG_EXTENDED|REG_NOSUB) != 0) { Perror("Regexp error "); goto error_done; } mre = &re; } else { mre = NULL; } listfile = cflist->handle; cflist->clobber_files = cpio_prefixes[i].clobber_files; if (cpio_prefixes[i].cpio_args != NULL) { cflist->cpio_args = cpio_prefixes[i].cpio_args; } else { cflist->cpio_args = DEFAULT_CPIO_ARGS; } } INFO_MSG3("Scanning %s/%s", cflist->chdir_prefix, cpio_prefixes[i].cpio_dir); (void) chdir(cflist->chdir_prefix); if (nftw(cpio_prefixes[i].cpio_dir, add_files, 10, FTW_MOUNT|FTW_PHYS) < 0) { Perror("Nftw failed "); goto error_done; } (void) fflush(cflist->handle); } (void) fflush(zerolength); /* * Now process each entry in the list. cpio is executed with the * -V option where it prints a dot for each pathname processed. * Since we already know the number of files we can show accurate * percentage completion. */ INFO_MSG1("Beginning cpio actions ..."); rem_percent = 95 - percent; ipercent = percent; cflist = flist.next; cpfiles = 0; opercent = 0; percent = 0; calc_factor = rem_percent / nfiles; while (cflist != NULL) { (void) fclose(cflist->handle); cflist->handle = NULL; CHECK_ABORT; if (cflist->clobber_files) { if (do_clobber_files(cflist->name) != 0) { goto error_done; } } (void) chdir(cflist->chdir_prefix); (void) snprintf(buf, PATH_MAX, "%s -%sV %s < %s", CPIO, cflist->cpio_args, mntpt, cflist->name); DBG_MSG3("Executing: %s, CWD: %s", buf, cflist->chdir_prefix); cpipe = popen(buf, "r"); if (cpipe == NULL) { Perror("Unable to cpio files "); goto error_done; } while (!feof(cpipe)) { int ch = fgetc(cpipe); if (ch == '.') { cpfiles++; percent = (int)(cpfiles * calc_factor + ipercent); if (percent - opercent >= 1) { if (progress != NULL) { (*progress)(percent); } opercent = percent; } } CHECK_ABORT; } if (ferror(cpipe)) { Perror(CPIO); goto error_done; } (void) fclose(cpipe); cpipe = NULL; (void) unlink(cflist->name); cflist->name[0] = '\0'; cflist = cflist->next; } (*progress)(percent); cpipe = NULL; /* * Process zero-length files if any. */ INFO_MSG1("Creating zero-length files"); rewind(zerolength); while (fgets(buf, BUF_SIZE, zerolength) != NULL) { int fd; mode_t mod; uid_t st_uid, st_gid; char *token, *lasts; /* Get the newline out of the way */ buf[strlen(buf) - 1] = '\0'; /* Parse out ownership and perms */ GET_TOKEN(token, lasts, buf, ","); mod = atoi(token); GET_TOKEN(token, lasts, NULL, ","); st_uid = atoi(token); GET_TOKEN(token, lasts, NULL, ","); st_gid = atoi(token); GET_TOKEN(token, lasts, NULL, ","); (void) snprintf(buf1, PATH_MAX, "%s/%s", mntpt, token); fd = open(buf1, O_WRONLY | O_CREAT | O_TRUNC, mod); if (fd != -1) { (void) fchown(fd, st_uid, st_gid); (void) close(fd); DBG_MSG2("Created file %s", buf1); } else { INFO_MSG1("Unable to create file:"); Perror(buf1); } } (*progress)(97); CHECK_ABORT; INFO_MSG1("Extracting archive"); (void) chdir(mntpt); (void) snprintf(buf, PATH_MAX, "%s e -so %s | %s -idum", SZIP, ARCHIVE, CPIO); DBG_MSG3("Executing: %s, CWD: %s", buf, mntpt); if (system(buf) != 0) { Perror("Extracting archive failed "); goto error_done; } (*progress)(98); CHECK_ABORT; /* * Check for the presence of skeleton.cpio before extracting it. * This file may not be present in a Distro Constructor image. */ if (lstat(SKELETON, &st) == 0 && (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))) { INFO_MSG1("Extracting skeleton archive"); (void) snprintf(buf, PATH_MAX, "%s -imu < %s", CPIO, SKELETON, mntpt); DBG_MSG3("Executing: %s, CWD: %s", buf, mntpt); if (system(buf) != 0) { Perror("Skeleton cpio failed "); goto error_done; } } (*progress)(99); CHECK_ABORT; INFO_MSG1("Performing file operations"); for (i = 0; i < NUM_FILEOPS_LIST; i++) { int rv; CHECK_ABORT; expand_symbols(fileops_list[i].src, buf, PATH_MAX); switch (fileops_list[i].op) { int op; case FILE_OP_UNLINK: DBG_MSG2("Unlink: %s", buf); (void) unlink(buf); rv = 0; /* unlink errors are non-fatal */ break; case FILE_OP_RMDIR: DBG_MSG2("Rmdir: %s", buf); (void) rmdir(buf); rv = 0; /* Ignore rmdir errors for now */ break; case FILE_OP_MKDIR: DBG_MSG2("Mkdir: %s", buf); rv = 0; if (lstat(buf, &st) == 0) { op = 0; if ((st.st_mode & S_IFMT) != S_IFDIR) { rv = unlink(buf); op = 1; } if (rv == 0 && op) { rv = mkdir(buf, fileops_list[i].perms); } } else { rv = mkdir(buf, fileops_list[i].perms); } break; case FILE_OP_COPY: expand_symbols(fileops_list[i].dst, buf1, PATH_MAX); rv = copyfile(buf, buf1); break; case FILE_OP_CHMOD: expand_symbols(fileops_list[i].dst, buf1, PATH_MAX); rv = chmod(buf, fileops_list[i].perms); break; default: Perror("Unsupported file operation "); rv = 1; break; } if (rv != 0) { Perror("File ops error "); Perror(buf); goto error_done; } } CHECK_ABORT; INFO_MSG1("Fetching and updating keyboard layout"); (void) chdir(mntpt); DBG_MSG2("Opening keyboard device: %s", KBD_DEVICE); kbd = open(KBD_DEVICE, O_RDWR); if (kbd < 0) { Perror("Error opening keyboard"); goto error_done; } if (ioctl(kbd, KIOCLAYOUT, &kbd_layout)) { Perror("ioctl keyboard layout"); goto error_done; } CHECK_ABORT; if ((layout = get_layout_name(kbd_layout)) == NULL) { goto error_done; } kbd_file = fopen(KBD_DEFAULTS_FILE, "a+"); if (kbd_file == NULL) { Perror("Unable to open kbd defaults file "); goto error_done; } (void) fprintf(kbd_file, "LAYOUT=%s\n", layout); (void) fclose(kbd_file); DBG_MSG3("Updated keyboard defaults file: %s/%s", mntpt, KBD_DEFAULTS_FILE); INFO_MSG2("Detected %s keyboard layout", layout); tm = time(NULL); (void) strftime(buf, PATH_MAX, (char *)0, localtime(&tm)); INFO_MSG2("-- Completed transfer process, %s --", buf); (*progress)(100); goto done; error_done: rv = 1; done: if (lof != NULL) (void) fclose(lof); if (cpipe != NULL) (void) fclose(cpipe); free_flist(flist.next); if (logfile != NULL) free(logfile); if (kbd > 0) (void) close(kbd); if (buf != NULL) free(buf); if (buf1 != NULL) free(buf1); if (layout != NULL) free(layout); if (zerolength != NULL) { (void) fclose(zerolength); (void) unlink(zerolist); } do_abort = 0; (void) pthread_mutex_unlock(&tran_mutex); return (rv); }