Released version 3-2015061300
[notion.git] / mod_notionflux / notionflux / notionflux.c
blob793882ab49eff1c3db8dc7fcc868a2d958a39ada
1 /*
2 * mod_notionflux/notionflux/notionflux.c
4 * Copyright (c) Tuomo Valkonen 2004-2005.
6 * This is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
12 #include <X11/Xlib.h>
13 #include <X11/Xatom.h>
15 #include <libtu/types.h>
17 #include <stdio.h>
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/un.h>
26 #include "../notionflux.h"
28 static void die(const char *s)
30 fprintf(stderr, "%s\n", s);
31 exit(1);
35 static void die_e(const char *s)
37 perror(s);
38 exit(1);
41 static void mywrite(int fd, const char *buf, int n)
43 while(n>0){
44 int k;
45 k=write(fd, buf, n);
46 if(k<0 && (errno!=EAGAIN && errno!=EINTR))
47 die_e("Writing");
48 if(k>0){
49 n-=k;
50 buf+=k;
56 static int myread(int fd, char *buf, int n)
58 int left=n;
60 while(left>0){
61 int k;
62 k=read(fd, buf, left);
63 if(k<0 && (errno!=EAGAIN && errno!=EINTR))
64 die_e("Writing");
65 if(k==0)
66 break;
67 if(k>0){
68 left-=k;
69 buf+=k;
72 return n-left;
76 static char buf[MAX_DATA];
79 /*{{{ X */
82 static Display *dpy=NULL;
85 static ulong xwindow_get_property_(Window win, Atom atom, Atom type,
86 ulong n32expected, bool more, uchar **p,
87 int *format)
89 Atom real_type;
90 ulong n=-1, extra=0;
91 int status;
93 do{
94 status=XGetWindowProperty(dpy, win, atom, 0L, n32expected,
95 False, type, &real_type, format, &n,
96 &extra, p);
98 if(status!=Success || *p==NULL)
99 return -1;
101 if(extra==0 || !more)
102 break;
104 XFree((void*)*p);
105 n32expected+=(extra+4)/4;
106 more=FALSE;
107 }while(1);
109 if(n==0){
110 XFree((void*)*p);
111 *p=NULL;
112 return -1;
115 return n;
119 ulong xwindow_get_property(Window win, Atom atom, Atom type,
120 ulong n32expected, bool more, uchar **p)
122 int format=0;
123 return xwindow_get_property_(win, atom, type, n32expected, more, p,
124 &format);
128 char *xwindow_get_string_property(Window win, Atom a, int *nret)
130 char *p;
131 int n;
133 n=xwindow_get_property(win, a, XA_STRING, 64L, TRUE, (uchar**)&p);
135 if(nret!=NULL)
136 *nret=n;
138 return (n<=0 ? NULL : p);
142 void xwindow_set_string_property(Window win, Atom a, const char *value)
144 if(value==NULL){
145 XDeleteProperty(dpy, win, a);
146 }else{
147 XChangeProperty(dpy, win, a, XA_STRING,
148 8, PropModeReplace, (uchar*)value, strlen(value));
153 static char *get_socket()
155 Atom a;
156 char *s;
158 dpy=XOpenDisplay(NULL);
160 if(dpy==NULL)
161 die_e("Unable to open display.");
163 a=XInternAtom(dpy, "_NOTION_MOD_NOTIONFLUX_SOCKET", True);
165 if(a==None)
166 die_e("Missing atom. Notion not running?");
168 s=xwindow_get_string_property(DefaultRootWindow(dpy), a, NULL);
170 XCloseDisplay(dpy);
172 return s;
176 /*}}}*/
179 int main(int argc, char *argv[])
181 int sock;
182 struct sockaddr_un serv;
183 const char *sockname;
184 int use_stdin=1;
185 char res;
186 int n;
188 if(argc>1){
189 if(argc!=3 || strcmp(argv[1], "-e")!=0)
190 die("Usage: notionflux [-e code]");
192 if(strlen(argv[2])>=MAX_DATA)
193 die("Too much data.");
195 use_stdin=0;
198 sockname=get_socket();
199 if(sockname==NULL)
200 die("No socket.");
202 if(strlen(sockname)>SOCK_MAX)
203 die("Socket name too long.");
205 sock=socket(AF_UNIX, SOCK_STREAM, 0);
206 if(sock<0)
207 die_e("Opening socket");
209 serv.sun_family=AF_UNIX;
210 strcpy(serv.sun_path, sockname);
212 if(connect(sock, (struct sockaddr*)&serv, sizeof(struct sockaddr_un))<0)
213 die_e("Connecting socket");
215 if(!use_stdin){
216 mywrite(sock, argv[2], strlen(argv[2])+1);
217 }else{
218 char c='\0';
219 while(1){
220 if(fgets(buf, MAX_DATA, stdin)==NULL)
221 break;
222 mywrite(sock, buf, strlen(buf));
224 mywrite(sock, &c, 1);
227 n=myread(sock, &res, 1);
229 if(n!=1 || (res!='E' && res!='S'))
230 die("Invalid response");
232 while(1){
233 n=myread(sock, buf, MAX_DATA);
235 if(n==0)
236 break;
238 if(res=='S')
239 mywrite(1, buf, n);
240 else /* res=='E' */
241 mywrite(2, buf, n);
243 if(n<MAX_DATA)
244 break;
247 return 0;