1 /* Also includes Xlib, Xresources, XPM, stdlib and stdio */
9 /* Include the pixmap to use */
10 #include "archlinux.xpm"
11 #include "archlinux_bw.xpm"
12 #include "loading.xpm"
17 #define MAXPATHLEN 4096
18 #define CHK_INTERVAL 600
19 #define WMARCHUP_VER "1.2"
20 #define VERSION "wmArchUp version " WMARCHUP_VER
23 * Prototypes for local functions
26 void check_for_updates();
27 void buttonrelease(int button
, int state
, int x
, int y
);
29 char *get_update_script();
34 Pixmap arch
, arch_mask
, arch_bw
, arch_bw_mask
, checking
, checking_mask
;
35 unsigned short height
, width
;
36 unsigned int check_interval
= CHK_INTERVAL
;
37 int updates_available
= FALSE
;
45 main(int argc
, char **argv
)
47 /* Find bash update script */
48 script
= get_update_script();
50 /* Set callbacks for events */
51 DACallbacks eventCallbacks
= {
52 destroy
, /* destroy */
53 NULL
, /* buttonPress */
54 &buttonrelease
, /* buttonRelease */
55 NULL
, /* motion (mouse) */
56 NULL
, /* mouse enters window */
57 NULL
, /* mouse leaves window */
58 check_for_updates
/* timeout */
63 /* Set program options */
64 DAProgramOption options
[] = {
68 "Check interval in minutes. Default 10 minutes.",
75 /* provide standard command-line options */
77 argc
, argv
, /* Where the options come from */
78 options
, 1, /* Our list with options */
79 "This is dockapp watch for available updates "
80 "in Arch Linux packages.\n",
83 /* Set the check interval */
84 check_interval
= interval
? (interval
* 60) : CHK_INTERVAL
;
86 /* Check if correct libdockapp version exists in system */
87 DASetExpectedVersion(20050716);
89 DAInitialize("", "WMArchUp", 56, 56, argc
, argv
);
105 DAMakePixmapFromData(
112 /* Respond to destroy and timeout events (the ones not NULL in the
113 * eventCallbacks variable.
115 DASetCallbacks(&eventCallbacks
);
117 /* Set timeout in msec */
118 DASetTimeout(check_interval
* 1000);
120 /* Show the dockapp window. */
123 /* Check for updates at the begining */
126 /* Loop for events */
136 if (updates_available
== TRUE
) {
137 XSelectInput(DAGetDisplay(NULL
), DAGetWindow(), NoEventMask
);
139 int ret
= system(script
);
141 if (WEXITSTATUS(ret
) == 0) {
142 updates_available
= FALSE
;
143 DASetShape(arch_bw_mask
);
144 DASetPixmap(arch_bw
);
147 XSelectInput(DAGetDisplay(NULL
), DAGetWindow(),
148 ButtonPressMask
| ButtonReleaseMask
);
155 XSelectInput(DAGetDisplay(NULL
), DAGetWindow(), NoEventMask
);
159 DASetShape(checking_mask
);
160 DASetPixmap(checking
);
162 /* Read output from command */
163 FILE *fp
= popen("checkupdates", "r");
164 if (fgets(res
, MAX
, fp
) != NULL
) {
165 updates_available
= TRUE
;
166 DASetShape(arch_mask
);
169 updates_available
= FALSE
;
170 DASetShape(arch_bw_mask
);
171 DASetPixmap(arch_bw
);
174 if (pclose(fp
) != 0) {
175 fprintf(stderr
, " Error: Failed to close command stream \n");
178 XSelectInput(DAGetDisplay(NULL
), DAGetWindow(),
179 ButtonPressMask
| ButtonReleaseMask
);
188 /* A mouse button was pressed and released.
189 * See if it was button 1 left click or button 3 right click. */
191 buttonrelease(int button
, int state
, int x
, int y
)
195 } else if (button
== 3) {
205 char *script_name
= "arch_update.sh";
207 char *fullpath
= malloc(MAXPATHLEN
+ strlen(script_name
));
208 if (fullpath
== NULL
) {
209 perror("Can't allocate memory.");
214 * /proc/self is a symbolic link to the process-ID subdir of /proc, e.g.
215 * /proc/4323 when the pid of the process of this program is 4323.
216 * Inside /proc/<pid> there is a symbolic link to the executable that is
217 * running as this <pid>. This symbolic link is called "exe". So if we
218 * read the path where the symlink /proc/self/exe points to we have the
219 * full path of the executable.
222 length
= readlink("/proc/self/exe", fullpath
, MAXPATHLEN
);
228 perror("resolving symlink /proc/self/exe.");
231 if (length
>= MAXPATHLEN
) {
232 fprintf(stderr
, "Path too long.\n");
236 fullpath
[length
] = '\0';
237 if ((p
= strrchr(fullpath
, '/'))) {
240 strcat(fullpath
, script_name
);