Update README - Download link out of date.
[dockapps.git] / wmArchUp / wmarchup.c
blobc80d9e2b545fe79ba7ec2baa7e9720ae767444e5
1 /* Also includes Xlib, Xresources, XPM, stdlib and stdio */
2 #include <libdockapp/dockapp.h>
3 #include <stdio.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <stdlib.h>
7 #include <sys/wait.h>
9 /* Include the pixmap to use */
10 #include "archlinux.xpm"
11 #include "archlinux_bw.xpm"
12 #include "loading.xpm"
14 #define TRUE 1
15 #define FALSE 0
16 #define MAX 256
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
25 void destroy(void);
26 void check_for_updates();
27 void buttonrelease(int button, int state, int x, int y);
28 void update();
29 char *get_update_script();
32 * Global variables
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;
38 char *script;
41 * M A I N
44 int
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 */
61 int interval = 0;
63 /* Set program options */
64 DAProgramOption options[] = {
66 "-c",
67 "--check-interval",
68 "Check interval in minutes. Default 10 minutes.",
69 DONatural,
70 False,
71 {&interval}
75 /* provide standard command-line options */
76 DAParseArguments(
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",
81 VERSION);
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);
91 DAMakePixmapFromData(
92 archlinux,
93 &arch,
94 &arch_mask,
95 &height,
96 &width);
98 DAMakePixmapFromData(
99 archlinux_bw,
100 &arch_bw,
101 &arch_bw_mask,
102 &height,
103 &width);
105 DAMakePixmapFromData(
106 loading,
107 &checking,
108 &checking_mask,
109 &height,
110 &width);
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. */
121 DAShow();
123 /* Check for updates at the begining */
124 check_for_updates();
126 /* Loop for events */
127 DAEventLoop();
129 /* not reached */
130 exit(EXIT_SUCCESS);
133 void
134 update()
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);
152 void
153 check_for_updates()
155 XSelectInput(DAGetDisplay(NULL), DAGetWindow(), NoEventMask);
156 char res[MAX];
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);
167 DASetPixmap(arch);
168 } else {
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);
182 void
183 destroy(void)
185 return;
188 /* A mouse button was pressed and released.
189 * See if it was button 1 left click or button 3 right click. */
190 void
191 buttonrelease(int button, int state, int x, int y)
193 if (button == 1) {
194 update();
195 } else if (button == 3) {
196 check_for_updates();
200 char *
201 get_update_script()
203 int length;
204 char *p;
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.");
210 exit(1);
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);
225 * Catch some errors:
227 if (length < 0) {
228 perror("resolving symlink /proc/self/exe.");
229 exit(1);
231 if (length >= MAXPATHLEN) {
232 fprintf(stderr, "Path too long.\n");
233 exit(1);
236 fullpath[length] = '\0';
237 if ((p = strrchr(fullpath, '/'))) {
238 *(p + 1) = '\0';
240 strcat(fullpath, script_name);
242 return fullpath;