1/* 2 * Copyright (c) 2013, ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich, 8 * Attn: Systems Group. 9 */ 10 11#include <angler/angler.h> 12#include <barrelfish/barrelfish.h> 13#include <barrelfish/debug.h> 14#include <barrelfish/spawn_client.h> 15#include <posixcompat.h> 16#include <vfs/vfs.h> 17 18#include <assert.h> 19#include <stdio.h> 20#include <unistd.h> 21 22#define SHELL "fish" 23#define BUFFER_SIZE 128 24 25static int openpty(int *amaster, int *aslave) 26{ 27 int ptm; 28 char *pts; 29 30 /* open master side */ 31 ptm = posix_openpt(O_RDWR | O_NOCTTY); 32 if (ptm < 0) { 33 return -1; 34 } 35 if (grantpt(ptm) < 0) { 36 return -1; 37 } 38 if (unlockpt(ptm) < 0) { 39 return -1; 40 } 41 *amaster = ptm; 42 43 pts = ptsname(ptm); 44 if (pts == NULL) { 45 return -1; 46 } 47 48 /* open slave side */ 49 *aslave = open(pts, O_RDWR | O_NOCTTY); 50 if (*aslave < 0) { 51 close(*amaster); 52 return -1; 53 } 54 55 return 0; 56} 57 58static void spawn_shell(int ttyfd) 59{ 60 struct capref session_id; 61 errval_t err; 62 coreid_t my_core_id = disp_get_core_id(); 63 char *shell = SHELL; 64 65 /* establish a new session */ 66 iref_t iref = posixcompat_pts_get_iref(ttyfd); 67 err = angler_new_session_with_iref(iref, &session_id); 68 if (err_is_fail(err)) { 69 USER_PANIC_ERR(err, "Error starting session."); 70 } 71 debug_printf("Created a new session.\n"); 72 73 /* setup argv of the shell */ 74 char *shell_argv[2]; 75 shell_argv[0] = SHELL; 76 shell_argv[1] = NULL; 77 78 /* inherit the session capability */ 79 struct capref inheritcn_cap; 80 err = alloc_inheritcn_with_caps(&inheritcn_cap, NULL_CAP, session_id, NULL_CAP); 81 if (err_is_fail(err)) { 82 USER_PANIC_ERR(err, "Error allocating inherit CNode with session cap."); 83 } 84 85 /* spawn shell on the same core */ 86 debug_printf("About to spawn fish.\n"); 87 err = spawn_program_with_caps(my_core_id, shell, shell_argv, NULL, 88 inheritcn_cap, NULL_CAP, SPAWN_FLAGS_NEW_DOMAIN, 89 NULL); 90 if (err_is_fail(err)) { 91 USER_PANIC_ERR(err, "Error spawning shell."); 92 } 93} 94 95int main(int argc, char *argv[]) 96{ 97 int ret = 0; 98 int ptm = 0; 99 int pts = 0; 100 101 vfs_init(); 102 103 // allocate new pseudo-terminal 104 ret = openpty(&ptm, &pts); 105 debug_printf("Allocated pseudo-terminal with fds %d and %d.\n", ptm, pts); 106 assert(ret == 0); 107 108 // spawn shell 109 spawn_shell(pts); 110 111 // read from master side 112 char buffer[BUFFER_SIZE + 1]; 113 size_t r = 0; 114 while (true) { 115 debug_printf("Waiting for characters at pseudo-terminal master.\n"); 116 r = read(ptm, buffer, BUFFER_SIZE); 117 if (r > 0) { 118 buffer[r] = '\0'; 119 printf("read %zd characters: %s\n.", r, buffer); 120 } else { 121 printf("error: read returned %zd\n", r); 122 } 123 } 124 125 return 0; 126} 127