GRASS Programmer's Manual  6.4.2(2012)
form/open.c
Go to the documentation of this file.
00001 #include <stdlib.h>
00002 #include <string.h>
00003 #include <unistd.h>
00004 #include <fcntl.h>
00005 #include <grass/gis.h>
00006 #include <grass/dbmi.h>
00007 #include <grass/form.h>
00008 
00009 #ifdef HAVE_SOCKET
00010 #include <sys/types.h>
00011 #ifdef __MINGW32__
00012 #include <winsock.h>
00013 
00014 #else /*__MINGW32__*/
00015 #include <sys/socket.h>
00016 #include <netinet/in.h>
00017 
00018 #endif /*__MINGW32__*/
00019 #endif /*HAVE_SOCKET */
00020 
00021 #ifdef HAVE_SOCKET
00022 static int make_socketpair(int *);
00023 #endif
00024 
00025 int first = 1;
00026 
00027 /* the pipe to send data to GUI */
00028 FILE *parent_send, *parent_recv;
00029 
00030 #ifdef HAVE_SOCKET
00031 int pipefd[2];
00032 
00033 #define pfd     pipefd[1]       /* parent's end */
00034 #define cfd     pipefd[0]       /* child's end */
00035 
00036 #endif /*HAVE_SOCKET */
00037 
00038 /* Open new form
00039  *
00040  *  returns: 0 success
00041  */
00042 #ifdef __MINGW32__
00043 int F_open(char *title, char *html)
00044 {
00045     G_fatal_error("F_open is not supported on Windows");
00046     return 1;
00047 }
00048 #else
00049 int F_open(char *title, char *html)
00050 {
00051     /* parent */
00052     int c;
00053 
00054     /* common */
00055     static int pid;
00056 
00057 #ifndef HAVE_SOCKET
00058     static int p1[2], p2[2];
00059 #endif /*HAVE_SOCKET */
00060     int length;
00061 
00062     /* child */
00063 
00064     G_debug(2, "F_open(): title = %s", title);
00065 
00066     if (first) {
00067 #ifdef HAVE_SOCKET
00068         if (make_socketpair(pipefd) < 0)
00069             G_fatal_error("Cannot make socket pair");
00070 #else
00071         if (pipe(p1) < 0 || pipe(p2) < 0)
00072             G_fatal_error("Cannot open pipe");
00073 #endif /*HAVE_SOCKET */
00074 
00075         if ((pid = fork()) < 0)
00076             G_fatal_error("Cannot create fork");
00077     }
00078 
00079     if (pid == 0) {             /* Child */
00080         char command[2000], script[2000];
00081 
00082         G_debug(2, "CHILD");
00083 
00084         /* Note: If you are forking in a Tk based apllication  you
00085          *       must  execl  before  doing any window operations in the
00086          *       child or you will receive an error from the  X server */
00087 
00088         close(0);
00089         close(1);
00090 
00091 #ifndef HAVE_SOCKET
00092         close(p1[1]);
00093         close(p2[0]);
00094         if (dup(p1[0]) != 0)
00095             G_fatal_error("Form: cannot dup() input");
00096         if (dup(p2[1]) != 1)
00097             G_fatal_error("Form: cannot dup() output");
00098 
00099 #else
00100         close(pfd);
00101         if (dup(cfd) != 0)
00102             G_fatal_error("Form: cannot dup() input");
00103         if (dup(cfd) != 1)
00104             G_fatal_error("Form: cannot dup() output");
00105 
00106 #endif /*HAVE_SOCKET */
00107 
00108 
00109 
00110         sprintf(command, "%s/etc/form/form", G_gisbase());
00111         sprintf(script, "%s/etc/form/form.tcl", G_gisbase());
00112 
00113         execl(command, "form", "-f", script, NULL);
00114 
00115         G_debug(2, "CHILD END\n");
00116         exit(0);
00117 
00118     }
00119     else {                      /* Parent */
00120         G_debug(2, "PARENT");
00121 
00122         if (first) {
00123 #ifndef HAVE_SOCKET
00124             parent_send = fdopen(p1[1], "w");
00125             close(p1[0]);
00126             parent_recv = fdopen(p2[0], "r");
00127             close(p2[1]);
00128 #else
00129             close(cfd);
00130             parent_send = fdopen(pfd, "w");
00131             parent_recv = fdopen(pfd, "r");
00132 #endif /*HAVE_SOCKET */
00133             first = 0;
00134         }
00135 
00136         G_debug(2, "PARENT HTML:\n%s\n", html);
00137 
00138         fprintf(parent_send, "O");
00139         length = strlen(title);
00140         fprintf(parent_send, "%d\n", length);
00141         fprintf(parent_send, "%s", title);
00142         length = strlen(html);
00143         fprintf(parent_send, "%d\n", length);
00144         fprintf(parent_send, "%s", html);
00145         fflush(parent_send);
00146         G_debug(2, "PARENT: Request sent\n");
00147 
00148         /* Wait for response */
00149         c = fgetc(parent_recv);
00150         G_debug(2, "PARENT: received %c\n", c);
00151     }
00152 
00153     return 0;
00154 }
00155 #endif
00156 
00157 /* Clear old forms from window
00158  *
00159  */
00160 void F_clear(void)
00161 {
00162     char c;
00163 
00164     G_debug(2, "F_clear()");
00165 
00166     if (first)
00167         return;
00168 
00169     fprintf(parent_send, "C");
00170     fflush(parent_send);
00171     c = fgetc(parent_recv);
00172     G_debug(2, "PARENT: received %c\n", c);
00173 }
00174 
00175 void F_close(void)
00176 {
00177     char c;
00178 
00179     G_debug(2, "F_close()");
00180 
00181     if (first)
00182         return;
00183 
00184     fprintf(parent_send, "D");
00185     fflush(parent_send);
00186     c = fgetc(parent_recv);
00187     G_debug(2, "PARENT: received %c\n", c);
00188 
00189     first = 1;
00190 }
00191 
00192 #ifdef HAVE_SOCKET
00193 static int make_socketpair(int *fd)
00194 {
00195     int n;
00196 
00197     if ((n = socketpair(AF_UNIX, SOCK_STREAM, IPPROTO_IP, fd)) < 0)
00198         return -1;
00199     else
00200         return 0;
00201 }
00202 
00203 #endif
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines