some bugfixes (including 3548041)
[vde.git] / vde-2 / src / vdeterm.c
blobe1be16cb88ca9718064ba450fc98ebe249b12c87
1 /* Copyright 2005 Renzo Davoli VDE-2
2 * Licensed under the GPLv2
4 * Minimal terminal emulator on a UNIX stream socket
5 */
7 #define _GNU_SOURCE
8 #include <stdio.h>
9 #include <string.h>
10 #include <fcntl.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <poll.h>
14 #include <signal.h>
15 #include <errno.h>
16 #include <sys/socket.h>
17 #include <sys/un.h>
18 #include <termios.h>
19 #include <libvdehist.h>
21 char *prompt;
22 static struct termios tiop;
24 static void cleanup(void)
26 fprintf(stderr,"\n");
27 tcsetattr(STDIN_FILENO,TCSAFLUSH,&tiop);
30 static void sig_handler(int sig)
32 cleanup();
33 signal(sig, SIG_DFL);
34 if (sig == SIGTERM)
35 _exit(0);
36 else
37 kill(getpid(), sig);
40 static void setsighandlers()
42 /* setting signal handlers.
43 * sets clean termination for SIGHUP, SIGINT and SIGTERM, and simply
44 * ignores all the others signals which could cause termination. */
45 struct { int sig; const char *name; int ignore; } signals[] = {
46 { SIGHUP, "SIGHUP", 0 },
47 { SIGINT, "SIGINT", 0 },
48 { SIGPIPE, "SIGPIPE", 1 },
49 { SIGALRM, "SIGALRM", 1 },
50 { SIGTERM, "SIGTERM", 0 },
51 { SIGUSR1, "SIGUSR1", 1 },
52 { SIGUSR2, "SIGUSR2", 1 },
53 { SIGPROF, "SIGPROF", 1 },
54 { SIGVTALRM, "SIGVTALRM", 1 },
55 #ifdef VDE_LINUX
56 { SIGPOLL, "SIGPOLL", 1 },
57 #ifdef SIGSTKFLT
58 { SIGSTKFLT, "SIGSTKFLT", 1 },
59 #endif
60 { SIGIO, "SIGIO", 1 },
61 { SIGPWR, "SIGPWR", 1 },
62 #ifdef SIGUNUSED
63 { SIGUNUSED, "SIGUNUSED", 1 },
64 #endif
65 #endif
66 #ifdef VDE_DARWIN
67 { SIGXCPU, "SIGXCPU", 1 },
68 { SIGXFSZ, "SIGXFSZ", 1 },
69 #endif
70 { 0, NULL, 0 }
73 int i;
74 for(i = 0; signals[i].sig != 0; i++)
75 if(signal(signals[i].sig,
76 signals[i].ignore ? SIG_IGN : sig_handler) < 0)
77 fprintf(stderr,"Error setting handler for %s: %s\n", signals[i].name,
78 strerror(errno));
81 #define BUFSIZE 1024
82 static char *copy_header_prompt (int vdefd,int termfd,char *sock)
84 char buf[BUFSIZE];
85 int n;
86 char *prompt;
87 while (1) {
88 struct pollfd wfd={vdefd,POLLIN|POLLHUP,0};
89 poll(&wfd,1,-1);
90 while ((n=read(vdefd,buf,BUFSIZE))>0) {
91 if (buf[n-2]=='$' &&
92 buf[n-1]==' ') {
93 n-=2;
94 buf[n]=0;
95 while (n>0 && buf[n] !='\n')
96 n--;
97 write(termfd,buf,n+1);
98 asprintf(&prompt,"%s[%s]: ",buf+n+1,sock);
99 return prompt;
100 } else
101 write(termfd,buf,n);
106 int main(int argc,char *argv[])
108 struct sockaddr_un sun;
109 int fd;
110 int rv;
111 int flags;
112 struct termios newtiop;
113 static struct pollfd pfd[]={
114 {STDIN_FILENO,POLLIN | POLLHUP,0},
115 {STDIN_FILENO,POLLIN | POLLHUP,0}};
116 //static int fileout[]={STDOUT_FILENO,STDOUT_FILENO};
117 struct vdehiststat *vdehst;
118 setsighandlers();
119 tcgetattr(STDIN_FILENO,&tiop);
120 atexit(cleanup);
121 sun.sun_family=PF_UNIX;
122 snprintf(sun.sun_path,sizeof(sun.sun_path),"%s",argv[1]);
123 //asprintf(&prompt,"vdterm[%s]: ",argv[1]);
124 if((fd=socket(PF_UNIX,SOCK_STREAM,0))<0) {
125 perror("Socket opening error");
126 exit(-1);
128 if ((rv=connect(fd,(struct sockaddr *)(&sun),sizeof(sun))) < 0) {
129 perror("Socket connecting error");
130 exit(-1);
132 newtiop=tiop;
133 newtiop.c_cc[VMIN]=1;
134 newtiop.c_cc[VTIME]=0;
135 newtiop.c_lflag &= ~ICANON;
136 newtiop.c_lflag &= ~ECHO;
137 tcsetattr(STDIN_FILENO,TCSAFLUSH,&newtiop);
138 flags = fcntl(fd, F_GETFL);
139 flags |= O_NONBLOCK;
140 fcntl(fd, F_SETFL, flags);
141 pfd[1].fd=fd;
142 prompt=copy_header_prompt(fd,STDOUT_FILENO,argv[1]);
143 vdehst=vdehist_new(STDIN_FILENO,fd);
144 write(STDOUT_FILENO,prompt,strlen(prompt)+1);
145 while(1) {
146 poll(pfd,2,-1);
147 //printf("POLL %d %d\n",pfd[0].revents,pfd[1].revents);
148 if(pfd[0].revents & POLLHUP ||
149 pfd[1].revents & POLLHUP)
150 exit(0);
151 if(pfd[0].revents & POLLIN) {
152 if (vdehist_term_to_mgmt(vdehst) != 0)
153 exit(0);
155 if(pfd[1].revents & POLLIN)
156 vdehist_mgmt_to_term(vdehst);
157 //printf("POLL RETURN!\n");