[Genlist] Fix genlist selected issue
[framework/uifw/elementary.git] / src / bin / run.c
1 #include "elementary_config.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <errno.h>
5 #include <string.h>
6 #include <limits.h>
7 #include <sys/types.h>
8 #include <sys/socket.h>
9 #include <sys/un.h>
10 #ifdef HAVE_ENVIRON
11 # define _GNU_SOURCE 1
12 #endif
13 #include <unistd.h>
14 #include <sys/stat.h>
15 #include <fcntl.h>
16 #ifdef HAVE_ALLOCA_H
17 # include <alloca.h>
18 #endif
19
20 #ifdef HAVE_ENVIRON
21 extern char **environ;
22 #endif
23
24 #define LENGTH_OF_SOCKADDR_UN(s) (strlen((s)->sun_path) + (size_t)(((struct sockaddr_un *)NULL)->sun_path))
25
26 int
27 main(int argc, char **argv)
28 {
29    int sock, socket_unix_len, i, n;
30    struct sockaddr_un socket_unix;
31    char buf[PATH_MAX];
32    struct stat st;
33    char *exe;
34    int we_are_elementary_run = 0;
35    char *disp;
36    char *cwd;
37
38    int sargc, slen, envnum;
39    unsigned char *sbuf = NULL, *pos;
40    char **sargv = NULL;
41
42    if (!getcwd(buf, sizeof(buf) - 1))
43      {
44         fprintf(stderr, "elementary_quicklaunch: currect working dir too big.\n");
45         exit(-1);
46      }
47    cwd = strdup(buf);
48    if (!(disp = getenv("DISPLAY"))) disp = "unknown";
49    snprintf(buf, sizeof(buf), "/tmp/elm-ql-%i/%s", getuid(), disp);
50    if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
51      {
52         perror("elementary_quicklaunch: socket(AF_UNIX, SOCK_STREAM, 0)");
53         exit(-1);
54      }
55    socket_unix.sun_family = AF_UNIX;
56    strncpy(socket_unix.sun_path, buf, sizeof(socket_unix.sun_path));
57    socket_unix.sun_path[(int)(sizeof(socket_unix.sun_path)/sizeof(socket_unix.sun_path[0])) - 1] = '\0';
58    socket_unix_len = LENGTH_OF_SOCKADDR_UN(&socket_unix);
59    if (connect(sock, (struct sockaddr *)&socket_unix, socket_unix_len) < 0)
60      {
61         perror("elementary_quicklaunch: connect(sock, (struct sockaddr *)&socket_unix, socket_unix_len)");
62         printf("elementary_quicklaunch: cannot connect to socket '%s'\n", buf);
63         exit(1);
64      }
65    exe = argv[0];
66    if (!(((exe[0] == '/')) ||
67          ((exe[0] == '.') && (exe[1] == '/')) ||
68          ((exe[0] == '.') && (exe[1] == '.') && (exe[2] == '/'))))
69      {
70         char *path = getenv("PATH");
71         int exelen = strlen(argv[0]);
72         if (path)
73           {
74              const char *p, *pp;
75
76              p = path;
77              pp = p;
78              exe = NULL;
79              for (;;)
80                {
81                   if ((*p == ':') || (!*p))
82                     {
83                        unsigned int len;
84
85                        len = p - pp;
86                        if (len < (sizeof(buf) - exelen - 3))
87                          {
88                             strncpy(buf, pp, len);
89                             strcpy(buf + len, "/");
90                             strcpy(buf + len + 1, argv[0]);
91                             if (!access(buf, R_OK | X_OK))
92                               {
93                                  exe = buf;
94                                  break;
95                               }
96                             if (!*p) break;
97                             p++;
98                             pp = p;
99                          }
100                     }
101                   else
102                     {
103                        if (!*p) break;
104                        p++;
105                     }
106                }
107           }
108      }
109    if (exe)
110      {
111         if (!lstat(exe, &st))
112           {
113              if (S_ISLNK(st.st_mode))
114                {
115                   char buf2[PATH_MAX];
116
117                   ssize_t len = readlink(exe, buf2, sizeof(buf2) - 1);
118                   if (len >= 0)
119                     {
120                        char *p;
121                        buf2[len] = 0;
122                        p = strrchr(buf2, '/');
123                        if (p) p++;
124                        else p = buf2;
125                        if (!strncasecmp(p, "elementary_run", 14))
126                          we_are_elementary_run = 1;
127                     }
128                }
129           }
130      }
131    if (we_are_elementary_run)
132      {
133         sargc = argc;
134         sargv = argv;
135      }
136    else
137      {
138         sargc = argc - 1;
139         sargv = &(argv[1]);
140      }
141    
142    slen = 0;
143    envnum = 0;
144    
145    // header:
146    //  UL 'total bytes'
147    //  UL 'argnum'
148    //  UL 'envnum'
149    slen += sizeof(unsigned long) * 3;
150    
151    for (i = 0; i < sargc; i++)
152      {
153         slen += sizeof(unsigned long);
154         slen += strlen(sargv[i]) + 1;
155      }
156    
157 #ifdef HAVE_ENVIRON
158    // count how much space is needed for environment
159    for (i = 0; environ[i]; i++)
160      {
161         slen += sizeof(unsigned long);
162         slen += strlen(environ[i]) + 1;
163         envnum++;
164      }
165 #endif
166
167    // how much space is needed for cwd
168    slen += sizeof(unsigned long);
169    slen += strlen(cwd) + 1;
170
171    // allocate buffer on stack
172    sbuf = alloca(slen);
173    
174    // fill in header
175    ((unsigned long *)(sbuf))[0] = slen - sizeof(unsigned long);
176    ((unsigned long *)(sbuf))[1] = sargc;
177    ((unsigned long *)(sbuf))[2] = envnum;
178    // pos pointer after header
179    pos = (unsigned char *)(&((((unsigned long *)(sbuf))[3 + sargc + envnum + 1])));
180    n = 3;
181
182    // fill in args
183    for (i = 0; i < sargc; i++)
184      {
185         ((unsigned long *)(sbuf))[n] = (unsigned long)pos - (unsigned long)sbuf;
186         strcpy((char *)pos, sargv[i]);
187         pos += strlen(sargv[i]) + 1;
188         n++;
189      }
190    
191 #ifdef HAVE_ENVIRON
192    // fill in environ
193    for (i = 0; environ[i]; i++)
194      {
195         ((unsigned long *)(sbuf))[n] = (unsigned long)pos - (unsigned long)sbuf;
196         strcpy((char *)pos, environ[i]);
197         pos += strlen(environ[i]) + 1;
198         n++;
199      }
200 #endif
201
202    // fill in cwd
203    ((unsigned long *)(sbuf))[n] = (unsigned long)pos - (unsigned long)sbuf;
204    n++;
205    strcpy((char *)pos, cwd);
206    
207    if (write(sock, sbuf, slen) < 0)
208      printf("elementary_quicklaunch: cannot write to socket '%s'\n", buf);
209    close(sock);
210    return 0;
211 }