1 /*
2 | This is the source for hbiff, a program that monitors an
3 | electronic mailbox. It is provided as is. No warranties
4 | implied or otherwise are made, nor are any claims as to its
5 | usefulness for any purpose.
6 |
7 | $Source: /users/lamont/src/cmd/hbiff/RCS/hbiff.c,v $
8 | $Author: lamont $
9 | $State: Exp $ $Locker: $
10 | $Date: 92/09/15 15:01:05 $
11 */
12
13
14 char ident[] = "@(#)hbiff: $Revision: 1.2 $"; /* what string, version info */
15
16 #define TRUE 1
17 #define FALSE 0
18 #include <stdio.h>
19 #include <unistd.h>
20 #include <pwd.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/file.h>
24 #include <X11/Xlib.h>
25 #include <X11/Xutil.h>
26 #include <string.h>
27 #include <signal.h>
28 #include <time.h>
29 #include <utime.h>
30 #include <errno.h>
31
32 extern int errno;
33
34 #define MASK(f) (1 << (f))
35
36 #define max(a, b) ((a) > (b) ? (a) : (b))
37
38 #define nomail_width 64
39 #define nomail_height 64
40 static char nomail_bits[] = {
41 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
42 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
43 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
44 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
45 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
46 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
47 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
48 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0x7f,0x00,
49 0x00,0x00,0x08,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xe4,0x00,0x00,0x00,0x80,
50 0x00,0x00,0x00,0xb4,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x5c,0x71,0x1c,0x00,
51 0x00,0x01,0x00,0x00,0xac,0x62,0x0c,0x02,0x00,0x03,0x00,0x00,0x5c,0xa3,0x0a,
52 0xc5,0x09,0x02,0x00,0x00,0xac,0x22,0x89,0x88,0x08,0x02,0x00,0x00,0x5c,0x23,
53 0x89,0x88,0x08,0x02,0x00,0x00,0xac,0x22,0x88,0x8f,0x08,0x02,0x00,0x00,0x5c,
54 0x23,0x88,0x88,0x48,0x02,0x00,0x00,0xac,0x22,0x88,0x88,0x38,0x02,0x00,0x00,
55 0x5c,0x23,0x88,0xc8,0x01,0x02,0x00,0x00,0xac,0x22,0x88,0x1c,0x80,0x03,0x00,
56 0x00,0x5c,0x23,0xc8,0x01,0xf0,0x00,0x00,0x00,0xac,0x22,0x1c,0x00,0x0e,0x00,
57 0x00,0x00,0x58,0x73,0x00,0xe0,0x01,0x00,0x00,0x00,0xb2,0x02,0x00,0x1e,0x00,
58 0x00,0x00,0x00,0x67,0x03,0xf0,0x03,0x00,0x00,0x00,0x00,0xcd,0x02,0x1e,0x02,
59 0x00,0x00,0x00,0x80,0x99,0x83,0x23,0x02,0x00,0x00,0x00,0x80,0x30,0x61,0x24,
60 0x02,0x00,0x00,0x00,0xc0,0x60,0x1e,0x24,0x02,0x00,0x00,0x00,0x40,0xc0,0x00,
61 0x24,0x02,0x00,0x00,0x00,0x60,0x80,0x01,0x24,0x02,0x00,0x00,0x00,0x20,0x80,
62 0x01,0x24,0x02,0x00,0x00,0x00,0x30,0x80,0x01,0x24,0x02,0x00,0x00,0x00,0x10,
63 0x80,0x00,0x24,0x02,0x00,0x00,0x00,0x10,0xc0,0x00,0x24,0x02,0x00,0x00,0x00,
64 0x30,0x40,0x94,0x25,0x02,0x00,0x00,0x00,0x20,0x60,0x98,0x24,0x02,0x00,0x00,
65 0x00,0x60,0x30,0xb4,0x24,0x02,0x00,0x00,0x00,0xc0,0x1c,0xee,0x24,0x02,0x00,
66 0x00,0x00,0x80,0x07,0xf0,0x24,0xc2,0x00,0x00,0x00,0x00,0x00,0xa0,0x25,0x7a,
67 0x00,0x00,0x00,0x00,0x00,0x7c,0x27,0x36,0x03,0x00,0x00,0x00,0x00,0x1c,0x26,
68 0x0f,0x02,0x00,0x00,0x00,0x00,0x04,0x26,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,
69 0xa4,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0xa4,0x01,0x00,0x00,0x00,0x00,0x00,
70 0x00,0xac,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x02,0x00,0x00,0x00,0x00,
71 0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
72 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
73 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
74 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
75 0x00,0x00};
76
77 #define newmail_width 64
78 #define newmail_height 64
79 static char newmail_bits[] = {
80 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
81 0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x01,0x00,0x00,
82 0x00,0x00,0x00,0x00,0x50,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x18,0x00,
83 0x00,0x00,0x00,0x00,0x00,0x50,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x18,
84 0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,
85 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
86 0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x00,0x00,
87 0x00,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0x7f,0x00,
88 0x00,0x00,0x18,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xec,0x00,0x00,0x00,0x80,
89 0x00,0x00,0x00,0xf4,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0xfe,0x73,0x1c,0x00,
90 0x00,0x01,0x00,0xfc,0xff,0x63,0x0c,0x02,0x00,0x03,0x00,0x04,0x00,0xa2,0x0a,
91 0xc5,0x09,0x02,0x00,0x64,0x82,0x23,0x89,0x88,0x08,0x02,0x00,0x04,0xd5,0x22,
92 0x89,0x88,0x08,0x02,0x00,0x08,0x38,0x23,0x88,0x8f,0x08,0x02,0x00,0xc8,0x07,
93 0x23,0x88,0x88,0x48,0x02,0x00,0x3e,0x80,0x22,0x88,0x88,0x38,0x02,0x00,0x06,
94 0x40,0x22,0x88,0xc8,0x01,0x02,0x00,0xfe,0x3f,0x22,0x88,0x1c,0x80,0x03,0x00,
95 0x02,0x00,0x22,0xc8,0x01,0xf0,0x00,0x00,0x06,0x00,0x22,0x1c,0x00,0x0e,0x00,
96 0x00,0x04,0x80,0x73,0x00,0xe0,0x01,0x00,0x00,0x04,0xf8,0x02,0x00,0x1e,0x00,
97 0x00,0x00,0x04,0x6f,0x03,0xf0,0x03,0x00,0x00,0x00,0xe4,0xcd,0x02,0x1e,0x02,
98 0x00,0x00,0x00,0x9c,0x99,0x83,0x23,0x02,0x00,0x00,0x00,0x80,0x30,0x63,0x24,
99 0x02,0x00,0x00,0x00,0xc0,0x60,0x1e,0x24,0x02,0x00,0x00,0x00,0x40,0xc0,0x00,
100 0x24,0x02,0x00,0x00,0x00,0x60,0x80,0x01,0x24,0x02,0x00,0x00,0x00,0x20,0x80,
101 0x01,0x24,0x02,0x00,0x00,0x00,0x30,0x80,0x01,0x24,0x02,0x00,0x00,0x00,0x10,
102 0x80,0x00,0x24,0x02,0x00,0x00,0x00,0x10,0xc0,0x00,0x24,0x02,0x00,0x00,0x00,
103 0x30,0x40,0x94,0x25,0x02,0x00,0x00,0x00,0x20,0x60,0x98,0x24,0x02,0x00,0x00,
104 0x00,0x60,0x30,0xb4,0x24,0x02,0x00,0x00,0x00,0xc0,0x1c,0xee,0x24,0x02,0x00,
105 0x00,0x00,0x80,0x07,0xf0,0x24,0xc2,0x00,0x00,0x00,0x00,0x00,0xa0,0x25,0x7a,
106 0x00,0x00,0x00,0x00,0x00,0x7c,0x27,0x36,0x03,0x00,0x00,0x00,0x00,0x1c,0x26,
107 0x0f,0x02,0x00,0x00,0x00,0x00,0x04,0x26,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,
108 0xa4,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0xa4,0x01,0x00,0x00,0x00,0x00,0x00,
109 0x00,0xac,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x02,0x00,0x00,0x00,0x00,
110 0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
111 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
112 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
113 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
114 0x00,0x00};
115
116 #define oldmail_width 64
117 #define oldmail_height 64
118 static char oldmail_bits[] = {
119 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
120 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
121 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
122 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
123 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
124 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
125 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
126 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xff,0xff,0xff,0x7f,0x00,
127 0x00,0x00,0x18,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xec,0x00,0x00,0x00,0x80,
128 0x00,0x00,0x00,0xf4,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0xfe,0x73,0x1c,0x00,
129 0x00,0x01,0x00,0xfc,0xff,0x63,0x0c,0x02,0x00,0x03,0x00,0x04,0x00,0xa2,0x0a,
130 0xc5,0x09,0x02,0x00,0x64,0x82,0x23,0x89,0x88,0x08,0x02,0x00,0x04,0xd5,0x22,
131 0x89,0x88,0x08,0x02,0x00,0x08,0x38,0x23,0x88,0x8f,0x08,0x02,0x00,0xc8,0x07,
132 0x23,0x88,0x88,0x48,0x02,0x00,0x3e,0x80,0x22,0x88,0x88,0x38,0x02,0x00,0x06,
133 0x40,0x22,0x88,0xc8,0x01,0x02,0x00,0xfe,0x3f,0x22,0x88,0x1c,0x80,0x03,0x00,
134 0x02,0x00,0x22,0xc8,0x01,0xf0,0x00,0x00,0x06,0x00,0x22,0x1c,0x00,0x0e,0x00,
135 0x00,0x04,0x80,0x73,0x00,0xe0,0x01,0x00,0x00,0x04,0xf8,0x02,0x00,0x1e,0x00,
136 0x00,0x00,0x04,0x6f,0x03,0xf0,0x03,0x00,0x00,0x00,0xe4,0xcd,0x02,0x1e,0x02,
137 0x00,0x00,0x00,0x9c,0x99,0x83,0x23,0x02,0x00,0x00,0x00,0x80,0x30,0x63,0x24,
138 0x02,0x00,0x00,0x00,0xc0,0x60,0x1e,0x24,0x02,0x00,0x00,0x00,0x40,0xc0,0x00,
139 0x24,0x02,0x00,0x00,0x00,0x60,0x80,0x01,0x24,0x02,0x00,0x00,0x00,0x20,0x80,
140 0x01,0x24,0x02,0x00,0x00,0x00,0x30,0x80,0x01,0x24,0x02,0x00,0x00,0x00,0x10,
141 0x80,0x00,0x24,0x02,0x00,0x00,0x00,0x10,0xc0,0x00,0x24,0x02,0x00,0x00,0x00,
142 0x30,0x40,0x94,0x25,0x02,0x00,0x00,0x00,0x20,0x60,0x98,0x24,0x02,0x00,0x00,
143 0x00,0x60,0x30,0xb4,0x24,0x02,0x00,0x00,0x00,0xc0,0x1c,0xee,0x24,0x02,0x00,
144 0x00,0x00,0x80,0x07,0xf0,0x24,0xc2,0x00,0x00,0x00,0x00,0x00,0xa0,0x25,0x7a,
145 0x00,0x00,0x00,0x00,0x00,0x7c,0x27,0x36,0x03,0x00,0x00,0x00,0x00,0x1c,0x26,
146 0x0f,0x02,0x00,0x00,0x00,0x00,0x04,0x26,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,
147 0xa4,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0xa4,0x01,0x00,0x00,0x00,0x00,0x00,
148 0x00,0xac,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x02,0x00,0x00,0x00,0x00,
149 0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
150 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
151 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
152 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
153 0x00,0x00};
154
155 #define nomail 0
156 #define newmail 1
157 #define oldmail 2
158
159 Pixmap pix[3];
160
161 FILE *fp;
162 XClassHint class_spec;
163 Display *disp_ptr;
164 GC gc;
165 GC rev_gc;
166 GC new_mail_gc;
167 GC summary_gc;
168 XGCValues gcvalues;
169 int screen;
170 Window window_id;
171 Window from_wid = 0;
172 int width, height, swidth, sheight;
173 int max_lines, max_width;
174 int lines, new_lines;
175 int x_neg, y_neg, sx_neg, sy_neg; /* flags to indicate that x and/or y are negative */
176 int result;
177 int x, y, sx, sy, i;
178 int pix_x_offset, pix_y_offset, text_x_offset, text_y_offset;
179 int border_width;
180 char *Display_name;
181 int counter;
182 XSetWindowAttributes win_attrib;
183 unsigned long background, foreground, border;
184 unsigned long new_mail_background, new_mail_foreground;
185 unsigned long summary_background, summary_foreground;
186 XFontStruct *ae_font;
187 int fontheight, fontwidth;
188 char *bg_color, *fg_color, *b_color, *nm_bg_color, *nm_fg_color;
189 char *summary_fg_color, *summary_bg_color;
190 XColor exact_def_return, screen_def_return;
191 Colormap colormap;
192 int curr_state = 255;
193 int new_mail_raise;
194 char *username;
195 char mail_file[128];
196 char hostname[128];
197 char *mail_command;
198 char num_of_msgs[16];
199 char num_of_new[16];
200 int hostname_len;
201 int timer;
202 char *font_name;
203 int reverse_video;
204 int new_mail_reverse;
205 int new_mail_beep = TRUE;
206 int show_new_mail = FALSE;
207 int reverse_on;
208 int no_flash = FALSE;
209 int reverse_list = FALSE;
210 int new_mail_showing = FALSE;
211 int show_tally = FALSE;
212 int global_volume = 50;
213 int name_set = FALSE;
214 int file_is_dir = FALSE;
215 XSizeHints xsh, sxsh;
216
217 XEvent event;
218 XButtonEvent *button_event;
219
220 int xfd, readfds;
221 int ttymask;
222 struct timeval timeout;
223 int number_of_events;
224 int child_num;
225 time_t last_hbiff_access = 0;
226
227 int clear_child();
228
229 struct passwd *pw;
230
231 struct from_text {
232 int length; /* should include NULL character */
233 char *string; /* line of text */
234 char flag; /* flag to indicate that this is new mail */
235 struct from_text *next; /* next line */
236 };
237
238 struct from_text *old_msg_list = NULL, *new_msg_list = NULL;
239
240 /*
241 | Sound stuff borrowed from a program written by Roger Petersen
242 */
243
244 XKeyboardControl save_kbd;
245
246 int argc1;
247 char **argv1;
248
main(argc,argv)249 main(argc, argv)
250 int argc;
251 char *argv[];
252 {
253 char text[10];
254 KeySym key;
255 int done;
256 int temp;
257 char buffer[512];
258 char *temp_ptr;
259 struct stat buf;
260
261 Display_name = (char *) getenv("DISPLAY");
262 /*
263 | Check if the user specified a display on the command line
264 */
265 for (counter=1; counter < argc; counter++)
266 {
267 if (!strcmp(argv[counter], "-display"))
268 {
269 counter++;
270 Display_name = argv[counter];
271 }
272 }
273
274 argc1 = argc;
275 argv1 = argv;
276
277 /*
278 | default mail command
279 */
280 mail_command = "xterm -e Mail";
281 x = 100;
282 y = 100;
283 sx = 50;
284 sy = 50;
285 x_neg = y_neg = sx_neg = sy_neg = FALSE;
286 xsh.flags = sxsh.flags = PPosition | PSize;
287 child_num = 0;
288 timer = 30;
289 border_width = 3;
290 height = width = 0;
291 pw = getpwuid(getuid());
292 username = pw->pw_name;
293 gethostname(hostname, 32);
294 temp_ptr = hostname;
295 while ((*temp_ptr != '\0') && (*temp_ptr != '.'))
296 temp_ptr++;
297 *temp_ptr = '\0';
298 hostname_len = strlen(hostname);
299 mail_file[0] = '\0';
300 reverse_video = new_mail_reverse = new_mail_raise = new_mail_beep = FALSE;
301 reverse_on = FALSE;
302 if ((disp_ptr = XOpenDisplay(Display_name)) == 0)
303 {
304 fprintf(stderr, "could not open display \"%s\"\n", Display_name);
305 exit(1);
306 }
307 screen = DefaultScreen(disp_ptr);
308
309 /*
310 | get default values from ~/.Xdefaults file
311 */
312 get_defaults();
313
314 /*
315 | see what options were specified on the command line
316 */
317 for (counter=1; counter < argc; counter++)
318 {
319 if (!strcmp(argv[counter], "-display"))
320 {
321 counter++;
322 Display_name = argv[counter];
323 }
324 else if (!strcmp(argv[counter], "-fg"))
325 {
326 counter++;
327 fg_color = argv[counter];
328 }
329 else if (!strcmp(argv[counter], "-bg"))
330 {
331 counter++;
332 bg_color = argv[counter];
333 }
334 else if (!strcmp(argv[counter], "-bc"))
335 {
336 counter++;
337 b_color = argv[counter];
338 }
339 else if (!strcmp(argv[counter], "-fn"))
340 {
341 counter++;
342 font_name = argv[counter];
343 }
344 else if (!strcmp(argv[counter], "-h"))
345 {
346 counter++;
347 height = atoi(argv[counter]);
348 }
349 else if (!strcmp(argv[counter], "-w"))
350 {
351 counter++;
352 width = atoi(argv[counter]);
353 }
354 else if (!strcmp(argv[counter], "-t"))
355 {
356 counter++;
357 timer = atoi(argv[counter]);
358 }
359 else if (!strcmp(argv[counter], "-v"))
360 {
361 counter++;
362 global_volume = atoi(argv[counter]);
363 }
364 else if (!strcmp(argv[counter], "-sn"))
365 {
366 show_new_mail = TRUE;
367 }
368 else if (!strcmp(argv[counter], "-F"))
369 {
370 no_flash = TRUE;
371 }
372 else if (!strcmp(argv[counter], "-tally"))
373 {
374 show_tally = TRUE;
375 }
376 else if (!strncmp(argv[counter], "-geometry", strlen(argv[counter])))
377 {
378 counter++;
379
380 result = XParseGeometry(argv[counter], &x, &y, &width, &height);
381 xsh.flags = USPosition | USSize;
382 x_neg = result & XNegative;
383 y_neg = result & YNegative;
384 }
385 else if (!strncmp(argv[counter], "-summaryGeometry", strlen(argv[counter])))
386 {
387 counter++;
388
389 result = XParseGeometry(argv[counter], &sx, &sy, &swidth, &sheight);
390 sxsh.flags = USPosition | USSize;
391 sx_neg = result & XNegative;
392 sy_neg = result & YNegative;
393 }
394 else if (*argv[counter] == '=')
395 {
396 result = XParseGeometry(argv[counter], &x, &y, &width, &height);
397 xsh.flags = USPosition | USSize;
398 x_neg = result & XNegative;
399 y_neg = result & YNegative;
400 }
401 else if (!strcmp(argv[counter], "-u"))
402 {
403 counter++;
404 username = argv[counter];
405 }
406 else if (!strcmp(argv[counter], "-m"))
407 {
408 counter++;
409 strcpy(mail_file, argv[counter]);
410 }
411 else if (!strcmp(argv[counter], "-pop"))
412 {
413 new_mail_raise = TRUE;
414 }
415 else if (!strcmp(argv[counter], "-beep"))
416 {
417 new_mail_beep = TRUE;
418 }
419 else if (!strcmp(argv[counter], "-bw"))
420 {
421 counter++;
422 border_width = atoi(argv[counter]);
423 }
424 else if (!strcmp(argv[counter], "-ro"))
425 {
426 reverse_list = TRUE;
427 }
428 else if (!strcmp(argv[counter], "-r"))
429 {
430 reverse_video = TRUE;
431 }
432 else if (!strcmp(argv[counter], "-R"))
433 {
434 new_mail_reverse = TRUE;
435 }
436 else if (!strcmp(argv[counter], "-H"))
437 {
438 if (!name_set)
439 hostname_len = FALSE;
440 }
441 else if (!strcmp(argv[counter], "-name"))
442 {
443 counter++;
444 name_set = TRUE;
445 strcpy(hostname, argv[counter]);
446 hostname_len = strlen(hostname);
447 }
448 else if (!strcmp(argv[counter], "-xrm"))
449 {
450 /*
451 | ignore
452 */
453 counter++;
454 }
455 #ifdef DEBUG
456 else if (!strcmp(argv[counter], "-DEBUG"))
457 {
458 /*
459 | The following code will start an hpterm which will in turn execute
460 | a debugger and "adopt" the process, so it can be debugged.
461 */
462
463 int child_id;
464 char command_line[256];
465
466 child_id = getpid();
467 if (!fork())
468 {
469 sprintf(command_line,
470 "hpterm -fg wheat -bg DarkSlateGrey -n %s -e xdb %s -P %d",
471 "hello", argv[0], child_id);
472 execl("/bin/sh", "sh", "-c", command_line, NULL);
473 fprintf(stderr, "could not exec new window\n");
474 exit(1);
475 }
476
477 /*
478 | When in debugger, set child_id to zero (p child_id=0) to continue
479 | executing the software.
480 */
481
482 while (child_id != 0)
483 ;
484 }
485 #endif
486 else if ((!strcmp(argv[counter], "-?")) || (*argv[counter] == '-'))
487 {
488 /*
489 | if option is "-?" or unrecognized, print usage message and exit
490 */
491
492 fprintf(stderr, "usage: %s [options]\n", argv[0]);
493 fprintf(stderr, " -F (do not flash when new mail)\n");
494 fprintf(stderr, " -H (do not display hostname)\n");
495 fprintf(stderr, " -R (reverse if new mail)\n");
496 fprintf(stderr, " -m mailbox\n");
497 fprintf(stderr, " -sn show new mail when received\n");
498 fprintf(stderr, " -t time between mailbox checks in seconds\n");
499 fprintf(stderr, " -v volume for new mail beep (0-100)\n");
500 fprintf(stderr, " -r (reverse video)\n");
501 fprintf(stderr, " -u username\n");
502 fprintf(stderr, " -fg foreground color\n");
503 fprintf(stderr, " -bg background color\n");
504 fprintf(stderr, " -bc border color\n");
505 fprintf(stderr, " -bw size of border in pixels\n");
506 fprintf(stderr, " -fn font name\n");
507 fprintf(stderr, " -pop (if new mail, pop to top)\n");
508 fprintf(stderr, " -beep (if new mail, notify with sound)\n");
509 fprintf(stderr, " -tally (show number of messages, and how many are new)\n");
510 fprintf(stderr, " -geometry =geometry\n");
511 fprintf(stderr, " -summaryGeometry geometry\n");
512 fprintf(stderr, " -display display name\n");
513 exit(-1);
514 }
515 }
516
517 /*
518 | if no font was specified, set font to "6x10"
519 */
520 if (font_name == '\0')
521 font_name = "fixed";
522
523 /*
524 | get the font information
525 */
526 if ((ae_font = XLoadQueryFont(disp_ptr, font_name)) == 0)
527 {
528 fprintf(stderr, "could not open font\n");
529 exit(1);
530 }
531 fontheight = ae_font->ascent + ae_font->descent;
532 fontwidth = ae_font->max_bounds.rbearing - ae_font->min_bounds.lbearing;
533 /*
534 | figure out how tall and wide the window should be to display
535 | the information
536 */
537 max_lines = (XDisplayHeight(disp_ptr, screen)) / fontheight;
538 if (lines > max_lines)
539 lines = max_lines;
540 max_width = XDisplayWidth(disp_ptr, screen);
541
542 /*
543 | set mailbox information if not set by options
544 */
545
546 if (mail_file[0] == '\0')
547 {
548 strcpy(mail_file, "/var/mail/");
549 strcat(mail_file, username);
550 }
551
552 /*
553 | make sure mailbox is a file
554 */
555 temp = stat(mail_file, &buf);
556 buf.st_mode &= ~07777;
557 if ((temp != -1) && (buf.st_mode != 0100000) && (buf.st_mode != 0))
558 {
559 file_is_dir = TRUE;
560 new_mail_showing = FALSE;
561 show_tally = FALSE;
562 }
563
564 /*
565 | set default color information
566 */
567 background = XWhitePixel(disp_ptr, screen);
568 foreground = BlackPixel(disp_ptr, screen);
569 if (reverse_video)
570 {
571 border = background;
572 background = foreground;
573 foreground = border;
574 }
575 border = foreground;
576 summary_background = background;
577 summary_foreground = foreground;
578 new_mail_foreground = foreground;
579 new_mail_background = background;
580
581 win_attrib.background_pixel = background;
582 win_attrib.border_pixel = foreground;
583
584 /*
585 | set up values for placing items in window
586 */
587
588 if (hostname_len != FALSE)
589 width = max(64, max((XTextWidth(ae_font, hostname, strlen(hostname))), width));
590 else
591 width = max(64, width);
592
593 if (hostname_len != FALSE)
594 height = max((64+fontheight+2), height);
595 else
596 height = max(64, height);
597
598 if (show_tally)
599 {
600 width = max(width, (XTextWidth(ae_font, "333 msgs", 8)));
601 width = max(width, (XTextWidth(ae_font, "333 new", 7)));
602 if (hostname_len)
603 height = max((64+(3*fontheight)+2), height);
604 else
605 height = max((64+(2*fontheight)+2), height);
606 }
607
608 /*
609 | check for negative geometry information
610 */
611 if (x_neg)
612 x = XDisplayWidth(disp_ptr, screen) + x - width - (2 * border_width);
613
614 if (y_neg)
615 y = XDisplayHeight(disp_ptr, screen) + y - height - (2 * border_width);
616
617 /*
618 | position information for pixmap
619 */
620 pix_x_offset = (width - 64) / 2;
621 if ((hostname_len != FALSE) && (!show_tally))
622 pix_y_offset = (height - (64+fontheight)) / 2;
623 else if ((hostname_len != FALSE) && (show_tally))
624 pix_y_offset = (height - (64+(3*fontheight))) / 2;
625 else if ((hostname_len == FALSE) && (show_tally))
626 pix_y_offset = (height - (64+(2*fontheight))) / 2;
627 else
628 pix_y_offset = (height - 64) / 2;
629
630 /*
631 | position information for text
632 */
633 text_x_offset = (width - (XTextWidth(ae_font, hostname, strlen(hostname)))) / 2;
634 text_y_offset = pix_y_offset + 64 + ae_font->ascent;
635
636 #ifdef FORK
637 if (fork()) /* detach process from tty */
638 exit(0);
639 #endif
640
641 /* signal(SIGCLD, SIG_IGN);*/
642
643 if ((window_id = XCreateWindow(disp_ptr, RootWindow(disp_ptr, screen),
644 x, y, width, height, border_width, DefaultDepth(disp_ptr, screen),
645 InputOutput, DefaultVisual(disp_ptr, screen), (CWBackPixel |
646 CWBackPixmap | CWColormap), &win_attrib))
647 == 0)
648 {
649 fprintf(stderr, "could not create window\n");
650 exit(1);
651 }
652 if (DisplayPlanes(disp_ptr, screen) > 1) /*check for color ability*/
653 {
654 if ((colormap = XDefaultColormap(disp_ptr, screen)) == 0)
655 {
656 fprintf(stderr, "XDefaultColormap failed with error %d \n", colormap);
657 exit(1);
658 }
659
660 if (fg_color != NULL)
661 {
662 if (XParseColor(disp_ptr, colormap, fg_color, &exact_def_return) != 0)
663 {
664 XAllocColor(disp_ptr, colormap, &exact_def_return);
665 foreground = exact_def_return.pixel;
666 }
667 else
668 {
669 fprintf(stderr, "unable to look up color \"%s\" \n", fg_color);
670 exit(1);
671 }
672 }
673
674 if (bg_color != NULL)
675 {
676 if (XParseColor(disp_ptr, colormap, bg_color, &exact_def_return) != 0)
677 {
678 XAllocColor(disp_ptr, colormap, &exact_def_return);
679 background = exact_def_return.pixel;
680 XSetWindowBackground(disp_ptr, window_id, background);
681 }
682 else
683 {
684 fprintf(stderr, "unable to look up color \"%s\" \n", bg_color);
685 exit(1);
686 }
687 }
688
689 if (nm_fg_color != NULL)
690 {
691 if (XParseColor(disp_ptr, colormap, nm_fg_color, &exact_def_return) != 0)
692 {
693 XAllocColor(disp_ptr, colormap, &exact_def_return);
694 new_mail_foreground = exact_def_return.pixel;
695 }
696 else
697 {
698 fprintf(stderr, "unable to look up color \"%s\" \n", fg_color);
699 exit(1);
700 }
701 }
702 else
703 {
704 new_mail_foreground = foreground;
705 }
706
707 if (nm_bg_color != NULL)
708 {
709 if (XParseColor(disp_ptr, colormap, nm_bg_color, &exact_def_return) != 0)
710 {
711 XAllocColor(disp_ptr, colormap, &exact_def_return);
712 new_mail_background = exact_def_return.pixel;
713 }
714 else
715 {
716 fprintf(stderr, "unable to look up color \"%s\" \n", bg_color);
717 exit(1);
718 }
719 }
720 else
721 {
722 new_mail_background = background;
723 }
724
725 if (summary_fg_color != NULL)
726 {
727 if (XParseColor(disp_ptr, colormap, summary_fg_color, &exact_def_return) != 0)
728 {
729 XAllocColor(disp_ptr, colormap, &exact_def_return);
730 summary_foreground = exact_def_return.pixel;
731 }
732 else
733 {
734 fprintf(stderr, "unable to look up color \"%s\" \n", fg_color);
735 exit(1);
736 }
737 }
738 else
739 {
740 summary_foreground = foreground;
741 }
742
743 if (summary_bg_color != NULL)
744 {
745 if (XParseColor(disp_ptr, colormap, summary_bg_color, &exact_def_return) != 0)
746 {
747 XAllocColor(disp_ptr, colormap, &exact_def_return);
748 summary_background = exact_def_return.pixel;
749 }
750 else
751 {
752 fprintf(stderr, "unable to look up color \"%s\" \n", bg_color);
753 exit(1);
754 }
755 }
756 else
757 {
758 summary_background = background;
759 }
760
761 if (b_color != NULL)
762 {
763 if (XParseColor(disp_ptr, colormap, b_color, &exact_def_return) != 0)
764 {
765 XAllocColor(disp_ptr, colormap, &exact_def_return);
766 border = exact_def_return.pixel;
767 XSetWindowBorder(disp_ptr, window_id, border);
768 }
769 else
770 {
771 fprintf(stderr, "unable to look up color \"%s\" \n", bg_color);
772 exit(1);
773 }
774 }
775 }
776 /* win_attrib.override_redirect = TRUE;
777 XChangeWindowAttributes (disp_ptr, window_id, CWOverrideRedirect,
778 &win_attrib);*/
779 /*
780 | set up values for graphics context
781 */
782 gcvalues.font = ae_font->fid;
783 gcvalues.foreground = foreground;
784 gcvalues.background = background;
785 gc = XCreateGC(disp_ptr, window_id, (GCFont | GCForeground |
786 GCBackground), &gcvalues);
787 gcvalues.foreground = background;
788 gcvalues.background = foreground;
789
790 /*
791 | set up values for reverse video graphics context
792 */
793 rev_gc = XCreateGC(disp_ptr, window_id, (GCFont | GCForeground |
794 GCBackground), &gcvalues);
795
796 /*
797 | set up values for new mail graphics context
798 */
799 gcvalues.foreground = new_mail_foreground;
800 gcvalues.background = new_mail_background;
801
802 new_mail_gc = XCreateGC(disp_ptr, window_id, (GCFont | GCForeground |
803 GCBackground), &gcvalues);
804
805 /*
806 | set up values for summary graphics context
807 */
808
809 gcvalues.foreground = summary_foreground;
810 gcvalues.background = summary_background;
811
812 summary_gc = XCreateGC(disp_ptr, window_id, (GCFont | GCForeground |
813 GCBackground), &gcvalues);
814
815 /*
816 | set up bitmaps for the different mailboxes
817 | (no mail, old mail, or new mail)
818 */
819 pix[0] = XCreateBitmapFromData(disp_ptr, window_id, nomail_bits, 64, 64);
820 pix[1] = XCreateBitmapFromData(disp_ptr, window_id, newmail_bits, 64, 64);
821 pix[2] = XCreateBitmapFromData(disp_ptr, window_id, oldmail_bits, 64, 64);
822 /*
823 pix[0] = XCreatePixmapFromBitmapData(disp_ptr, window_id, nomail_bits, 64, 64, foreground, background, XDefaultDepth(disp_ptr, screen));
824 pix[1] = XCreatePixmapFromBitmapData(disp_ptr, window_id, newmail_bits, 64, 64, foreground, background, XDefaultDepth(disp_ptr, screen));
825 pix[2] = XCreatePixmapFromBitmapData(disp_ptr, window_id, oldmail_bits, 64, 64, foreground, background, XDefaultDepth(disp_ptr, screen));
826 */
827
828 /*
829 | set up values for window
830 */
831 xsh.height = height;
832 xsh.width = width;
833 xsh.x = x;
834 xsh.y = y;
835 xsh.flags = USPosition | USSize;
836
837 XSetStandardProperties(disp_ptr, window_id, "hbiff", "hbiff", pix[1],
838 argv, argc, &xsh);
839
840 XSetCommand(disp_ptr, window_id, argv, argc);
841
842 class_spec.res_name = "hbiff";
843 class_spec.res_class = "HBiff";
844 XSetClassHint(disp_ptr, window_id, &class_spec);
845
846 XSelectInput(disp_ptr, window_id, (ButtonPressMask | KeyPressMask | ExposureMask ));
847 XMapWindow(disp_ptr, window_id);
848 /* XNextEvent(disp_ptr, &event);*/
849 XFlush(disp_ptr);
850 /* XSetErrorHandler*/
851 curr_state = 0;
852
853 /*
854 | get mailbox status and paint the window
855 */
856 update_icon(curr_state);
857 checkmail();
858 timeout.tv_sec = timer;
859 timeout.tv_usec = 0;
860 button_event = (XButtonEvent *) &event;
861 done = 0;
862 xfd = ConnectionNumber(disp_ptr);
863 /*
864 | Loop forever, examining each event.
865 */
866 while (!done) {
867 /* Get the next event */
868 number_of_events = 0;
869 while (!number_of_events)
870 {
871 ttymask = MASK(xfd);
872 readfds = ttymask;
873 temp = select(xfd+1, &readfds, 0, 0, &timeout);
874 number_of_events = XPending(disp_ptr);
875 if ((temp > 0) && (number_of_events == 0))
876 {
877 done++;
878 break;
879 }
880 checkmail();
881 }
882 while (XPending(disp_ptr))
883 {
884 XNextEvent(disp_ptr, &event);
885 /*
886 | Determine the event type and deal with it accordingly.
887 */
888
889 switch (event.type) {
890 case Expose:
891 if (event.xexpose.window == from_wid)
892 paint_lines(new_mail_showing);
893 else if (event.xexpose.count == 0)
894 update_icon(curr_state);
895 break;
896 case MappingNotify:
897 XRefreshKeyboardMapping ( &event);
898 break;
899 case KeyPress:
900 i = XLookupString(&event, text, 10, &key, NULL);
901 if (i == 1 && text[0] == 'q')
902 done++;
903 if (from_wid)
904 nuke_summary_window();
905 break;
906 case ButtonPress:
907 if ((button_event->button == Button3) && (button_event->state == ShiftMask))
908 done++;
909 else if ((button_event->button == Button3) && (child_num == 0))
910 {
911 if (from_wid)
912 nuke_summary_window();
913 if (no_flash == FALSE)
914 flash_icon(curr_state);
915 signal(SIGCHLD, clear_child);
916 if (!(child_num = fork()))
917 {
918 system(mail_command);
919 exit(0);
920 }
921 }
922 else if ((button_event->button == Button2) && (!from_wid))
923 {
924 get_from_lines();
925 display_lines(FALSE);
926 }
927 else if ((button_event->button == Button1) && (curr_state != nomail))
928 {
929 /*
930 | reset access time on mailbox, so that hbiff does not think
931 | there is new mail
932 */
933 if (from_wid)
934 nuke_summary_window();
935 fp = fopen(mail_file, "r");
936 if (fp != NULL)
937 {
938 fgets(buffer, 512, fp);
939 fclose(fp);
940 }
941 checkmail();
942 }
943 else if (from_wid)
944 nuke_summary_window();
945 unmark_msgs(new_msg_list);
946 if (curr_state == newmail)
947 {
948 curr_state = oldmail;
949 get_from_lines();
950 update_icon(curr_state);
951 }
952 break;
953 } /* switch */
954 }
955 } /* while (!done) */
956
957 /*
958 | leave hbiff
959 */
960 XFreeGC(disp_ptr, gc);
961 XFreeGC(disp_ptr, rev_gc);
962 XFreeGC(disp_ptr, new_mail_gc);
963 XFreeGC(disp_ptr, summary_gc);
964 XDestroyWindow(disp_ptr, window_id);
965 XCloseDisplay(disp_ptr);
966 }
967
flash_icon(state)968 flash_icon(state)
969 int state;
970 {
971 paint_window(state, rev_gc, foreground);
972 sleep(1);
973 paint_window(state, gc, background);
974 }
975
paint_window(state,context,background)976 paint_window(state, context, background)
977 int state;
978 GC context;
979 unsigned long background;
980 {
981 int local_y;
982 int new_off, msgs_off;
983
984 local_y = text_y_offset;
985 if (show_tally)
986 {
987 sprintf(num_of_msgs, "%d msgs", lines);
988 sprintf(num_of_new, "%d new", new_lines);
989 new_off = (width - XTextWidth(ae_font, num_of_new, strlen(num_of_new))) / 2;
990 msgs_off = (width - XTextWidth(ae_font, num_of_msgs, strlen(num_of_msgs))) / 2;
991 }
992 XSetWindowBackground(disp_ptr, window_id, background);
993 XClearWindow(disp_ptr, window_id);
994 XCopyPlane(disp_ptr, pix[state], window_id, context, 0, 0, width, height, pix_x_offset, pix_y_offset, 1);
995 if (show_tally)
996 {
997 XDrawImageString(disp_ptr, window_id, context, msgs_off, local_y, num_of_msgs, strlen(num_of_msgs));
998 local_y += fontheight;
999 if (new_lines)
1000 XDrawImageString(disp_ptr, window_id, context, new_off, local_y, num_of_new, strlen(num_of_new));
1001 local_y += fontheight;
1002 }
1003 if (hostname_len != FALSE)
1004 XDrawImageString(disp_ptr, window_id, context, text_x_offset, local_y, hostname, hostname_len);
1005 XFlush(disp_ptr);
1006 }
1007
update_icon(state)1008 update_icon(state)
1009 int state;
1010 {
1011 if ((state == newmail) && (!new_mail_reverse))
1012 {
1013 paint_window(state, new_mail_gc, new_mail_background);
1014 }
1015 else if (reverse_on)
1016 {
1017 paint_window(state, rev_gc, foreground);
1018 }
1019 else
1020 {
1021 paint_window(state, gc, background);
1022 }
1023 XSetStandardProperties(disp_ptr, window_id, "hbiff", "hbiff",
1024 pix[state], argv1, argc1, &xsh);
1025
1026 XFlush(disp_ptr);
1027 }
1028
checkmail()1029 checkmail()
1030 {
1031 static int old_state = 0; /* initially "nomail" */
1032 static int file_size = 0;
1033 static struct stat file_status;
1034 static time_t last_modified = 0;
1035 static struct utimbuf timebuf;
1036
1037 old_state = curr_state;
1038 if (stat(mail_file, &file_status) == -1)
1039 {
1040 curr_state = nomail;
1041 file_status.st_size = 0;
1042 }
1043 else
1044 {
1045 if (file_status.st_size == 0)
1046 curr_state = nomail;
1047 else if ((file_status.st_atime <= file_status.st_mtime) ||
1048 ((file_status.st_atime <= last_hbiff_access) &&
1049 (curr_state == newmail)))
1050 {
1051 curr_state = newmail;
1052 /*
1053 | Even if the window already indicates new mail, do the appropriate
1054 | operations if there is more new mail.
1055 */
1056 if ((old_state == curr_state) && (last_modified < file_status.st_mtime))
1057 {
1058 old_state = oldmail;
1059 }
1060 last_modified = file_status.st_mtime;
1061 }
1062 else /* if (file_status.st_atime > file_status.st_mtime) */
1063 {
1064 curr_state = oldmail;
1065 if (((file_status.st_ctime > last_hbiff_access) ||
1066 (file_status.st_atime > last_hbiff_access)) &&
1067 (show_new_mail || show_tally))
1068 {
1069 get_from_lines();
1070 update_icon(curr_state);
1071 }
1072 }
1073 }
1074 if (curr_state != newmail)
1075 reverse_on = FALSE;
1076 if (old_state != curr_state)
1077 {
1078 if (from_wid)
1079 nuke_summary_window();
1080 get_from_lines();
1081 if (curr_state == newmail)
1082 {
1083 if (!file_is_dir)
1084 {
1085 /*
1086 | Reset file times so that other mechanisms will
1087 | still be able to detect that mail is new.
1088 */
1089 timebuf.actime = timebuf.modtime = last_modified;
1090 utime(mail_file, &timebuf);
1091 }
1092
1093 if (new_mail_reverse)
1094 reverse_on = TRUE;
1095 if (new_mail_raise)
1096 {
1097 XRaiseWindow(disp_ptr, window_id);
1098 XFlush(disp_ptr);
1099 update_icon(curr_state);
1100 }
1101 if (no_flash == FALSE)
1102 {
1103 flash_icon(curr_state);
1104 sleep(1);
1105 flash_icon(curr_state);
1106 }
1107 if (new_mail_beep)
1108 beep_new();
1109 if (show_new_mail && new_lines)
1110 {
1111 new_mail_showing = TRUE;
1112 display_lines(new_mail_showing);
1113 }
1114 }
1115 else
1116 unmark_msgs(new_msg_list);
1117 update_icon(curr_state);
1118 }
1119 }
1120
get_defaults()1121 get_defaults()
1122 {
1123 char *string;
1124
1125 summary_fg_color = XGetDefault(disp_ptr, "hbiff", "summaryForeground");
1126 summary_bg_color = XGetDefault(disp_ptr, "hbiff", "summaryBackground");
1127 nm_fg_color = XGetDefault(disp_ptr, "hbiff", "newMailForeground");
1128 nm_bg_color = XGetDefault(disp_ptr, "hbiff", "newMailBackground");
1129 fg_color = XGetDefault(disp_ptr, "hbiff", "foreground");
1130 bg_color = XGetDefault(disp_ptr, "hbiff", "background");
1131 b_color = XGetDefault(disp_ptr, "hbiff", "borderColor");
1132 if (string = XGetDefault(disp_ptr, "hbiff", "time"))
1133 timer = atoi(string);
1134 if (string = XGetDefault(disp_ptr, "hbiff", "volume"))
1135 global_volume = atoi(string);
1136
1137 if (string = XGetDefault(disp_ptr, "hbiff", "geometry"))
1138 {
1139 result = XParseGeometry(string, &x, &y, &width, &height);
1140 xsh.flags = USPosition | USSize;
1141 x_neg = result & XNegative;
1142 y_neg = result & YNegative;
1143 }
1144 if (string = XGetDefault(disp_ptr, "hbiff", "summaryGeometry"))
1145 {
1146 result = XParseGeometry(string, &sx, &sy, &swidth, &sheight);
1147 sxsh.flags = USPosition | USSize;
1148 sx_neg = result & XNegative;
1149 sy_neg = result & YNegative;
1150 }
1151 if (string = XGetDefault(disp_ptr, "hbiff", "newMailRaise"))
1152 {
1153 new_mail_raise = yes_string(string);
1154 }
1155 if (string = XGetDefault(disp_ptr, "hbiff", "newMailBeep"))
1156 {
1157 new_mail_beep = yes_string(string);
1158 }
1159 if (string = XGetDefault(disp_ptr, "hbiff", "borderWidth"))
1160 border_width = atoi(string);
1161 if (string = XGetDefault(disp_ptr, "hbiff", "mailCommand"))
1162 {
1163 mail_command = (char *) malloc(strlen(string) + 1);
1164 strcpy(mail_command, string);
1165 }
1166 if (string = XGetDefault(disp_ptr, "hbiff", "fontName"))
1167 font_name = string;
1168 if (string = XGetDefault(disp_ptr, "hbiff", "reverseVideo"))
1169 {
1170 reverse_video = yes_string(string);
1171 }
1172 if (string = XGetDefault(disp_ptr, "hbiff", "reverseOrder"))
1173 {
1174 reverse_list = yes_string(string);
1175 }
1176 if (string = XGetDefault(disp_ptr, "hbiff", "newMailReverse"))
1177 {
1178 new_mail_reverse = yes_string(string);
1179 }
1180 if (string = XGetDefault(disp_ptr, "hbiff", "showNewMail"))
1181 {
1182 show_new_mail = yes_string(string);
1183 }
1184 if (string = XGetDefault(disp_ptr, "hbiff", "tally"))
1185 {
1186 show_tally = yes_string(string);
1187 }
1188 if (string = XGetDefault(disp_ptr, "hbiff", "noFlash"))
1189 {
1190 no_flash = yes_string(string);
1191 }
1192 if (string = XGetDefault(disp_ptr, "hbiff", "noHostname"))
1193 {
1194 if ((yes_string(string)) && (!name_set))
1195 hostname_len = FALSE;
1196 }
1197 if (string = XGetDefault(disp_ptr, "hbiff", "name"))
1198 {
1199 strcpy(hostname, string);
1200 name_set = TRUE;
1201 hostname_len = strlen(hostname);
1202 }
1203 }
1204
1205 /*
1206 | check string for a positive value (on, yes, true)
1207 */
1208
yes_string(string)1209 yes_string(string)
1210 char *string;
1211 {
1212 char temp_string[16];
1213 int counter;
1214
1215 if (strlen(string) > 4)
1216 return(FALSE);
1217
1218 for (counter = 0; counter < strlen(string); counter++)
1219 temp_string[counter] = toupper(string[counter]);
1220
1221 temp_string[counter] = NULL;
1222
1223 if ((strcmp(temp_string, "YES") == 0)
1224 || (strcmp(temp_string, "TRUE") == 0)
1225 || (strcmp(temp_string, "ON") == 0))
1226 return(TRUE);
1227 else
1228 return(FALSE);
1229 }
1230
1231 /*
1232 | Create list of mail messages, and check for messages that were not
1233 | present previously. For messages that were considered new in the
1234 | old list, set flag to indicate that they are new in the new list, too.
1235 */
1236
get_from_lines()1237 get_from_lines()
1238 {
1239 int counter;
1240 char *file_name;
1241 struct from_text *list_head, *temp_ptr;
1242 struct from_text *new_ptr, *old_ptr;
1243 char buffer[512];
1244 char buffer2[512];
1245 char from_buffer[512];
1246 char subj_buffer[512];
1247 char *temp;
1248 int sub_flag;
1249 int from_flag;
1250 int line_len, max_len;
1251 int max_lines, max_width;
1252 int done;
1253 int temp_int;
1254 int found;
1255 struct stat file_status;
1256
1257 if (file_is_dir)
1258 return(0);
1259
1260 lines = 0;
1261 new_lines = 0;
1262
1263 if (old_msg_list != NULL)
1264 {
1265 free_list(old_msg_list);
1266 }
1267 old_msg_list = new_msg_list;
1268 new_msg_list = NULL;
1269
1270 temp_int = stat(mail_file, &file_status);
1271
1272 if (temp_int != -1)
1273 {
1274 last_hbiff_access = file_status.st_atime;
1275 /*
1276 | make sure that file is non-zero size
1277 */
1278 if (file_status.st_size == 0)
1279 return(0);
1280 }
1281 else
1282 {
1283 /*
1284 | couldn't stat the file
1285 */
1286 return(0);
1287 }
1288
1289
1290 /*
1291 | open mailbox
1292 */
1293 if ((fp = fopen(mail_file, "r")) == NULL)
1294 return(0);
1295
1296 sub_flag = from_flag = FALSE;
1297 memset(buffer2, 0, 512);
1298 memset(subj_buffer, 0, 512);
1299 memset(from_buffer, 0, 512);
1300 list_head = NULL;
1301
1302 /*
1303 | create a linked list of lines containing the "From" and "Subject:"
1304 | information from each mail message
1305 */
1306 while ((temp = fgets(buffer, 512, fp)) != NULL)
1307 {
1308 if (!(strncmp(buffer, "From ", 5))) /* start of message */
1309 {
1310 from_flag = TRUE;
1311 strncpy(from_buffer, buffer, (strlen(buffer) - 1));
1312 }
1313 else if ((!(strncmp(buffer, "From: ", 5))) && from_flag)
1314 {
1315 from_parse(from_buffer, buffer);
1316 }
1317 else if ((!(strncmp(buffer, "Subject: ", 6))) && from_flag &&
1318 (subj_buffer[0] == NULL))
1319 {
1320 sub_flag = TRUE;
1321 strncat(subj_buffer, " [", 2);
1322 strncat(subj_buffer, buffer, (strlen(buffer) - 1));
1323 strncat(subj_buffer, "]", 1);
1324 }
1325 else if (((buffer[0] == '\n') || (buffer[0] == '\r')) && (from_flag))
1326 {
1327 strcpy(buffer2, from_buffer);
1328 strcat(buffer2, subj_buffer);
1329 memset(from_buffer, 0, 512);
1330 memset(subj_buffer, 0, 512);
1331 if (list_head == NULL)
1332 temp_ptr = list_head = (struct from_text *) malloc(sizeof(struct from_text));
1333 else
1334 {
1335 temp_ptr = list_head;
1336 while (temp_ptr->next != NULL)
1337 temp_ptr = temp_ptr->next;
1338 temp_ptr->next = (struct from_text *) malloc(sizeof(struct from_text));
1339 temp_ptr = temp_ptr->next;
1340 }
1341 temp_ptr->flag = FALSE;
1342 temp_ptr->length = strlen(buffer2) + 2;
1343 temp_ptr->string = (char *) malloc(temp_ptr->length);
1344 strcpy(temp_ptr->string, " ");
1345 strcat(temp_ptr->string, buffer2);
1346 temp_ptr->next = NULL;
1347 from_flag = sub_flag = FALSE;
1348 lines++;
1349 memset(buffer2, 0, 512);
1350 }
1351 }
1352
1353 if (list_head == 0)
1354 {
1355 /*
1356 | The mailbox is not in an expected format!
1357 */
1358 fprintf(stderr, "hbiff: mailbox corrupted!\n");
1359 fclose(fp);
1360 return(0);
1361 }
1362
1363 temp_ptr = list_head;
1364
1365 /*
1366 | indicate which is the most recent message
1367 */
1368
1369 while (temp_ptr->next != NULL)
1370 temp_ptr = temp_ptr->next;
1371 temp_ptr->string[0] = '>';
1372 temp_ptr = list_head;
1373
1374 if (reverse_list)
1375 {
1376 while (list_head->next != NULL)
1377 list_head = list_head->next;
1378 reverse_order(temp_ptr);
1379 temp_ptr = list_head;
1380 }
1381
1382 new_msg_list = list_head;
1383
1384 for (new_ptr = new_msg_list; new_ptr != NULL; new_ptr = new_ptr->next)
1385 {
1386 found = FALSE;
1387 for (old_ptr = old_msg_list; (old_ptr != NULL) && (!found);
1388 old_ptr = old_ptr->next)
1389 {
1390 if (old_ptr->string && (!strcmp((new_ptr->string+1), (old_ptr->string+1))))
1391 {
1392 free(old_ptr->string);
1393 old_ptr->string = NULL;
1394 found = TRUE;
1395 if (old_ptr->flag)
1396 {
1397 new_lines++;
1398 new_ptr->flag = TRUE;
1399 }
1400 }
1401 }
1402 if ((!found) && (curr_state == newmail))
1403 {
1404 new_lines++;
1405 new_ptr->flag = TRUE;
1406 }
1407 }
1408 fclose(fp);
1409 if (stat(mail_file, &file_status) != -1)
1410 {
1411 last_hbiff_access = file_status.st_atime;
1412 }
1413 }
1414
1415 /*
1416 | Create window of appropriate size to display mail summary.
1417 */
1418
display_lines(new_mail_only)1419 display_lines(new_mail_only)
1420 int new_mail_only;
1421 {
1422 XSizeHints xsh;
1423 char *file_name;
1424 char buffer[512];
1425 char buffer2[512];
1426 char from_buffer[512];
1427 char subj_buffer[512];
1428 char *temp;
1429 int sub_flag;
1430 int from_flag;
1431 int line_len = 0, max_len = 0;
1432 int done;
1433 int temp_int;
1434 int counter;
1435 int lines_to_display = 0;
1436 struct from_text *temp_ptr;
1437
1438 /* copy size hints */
1439 xsh.flags = sxsh.flags;
1440 xsh.x = sx;
1441 xsh.y = sy;
1442 xsh.width = sxsh.width;
1443 xsh.height = sxsh.height;
1444
1445 temp_ptr = new_msg_list;
1446
1447 while (temp_ptr != NULL)
1448 {
1449 if ((new_mail_only && temp_ptr->flag) || (!new_mail_only))
1450 {
1451 lines_to_display++;
1452 line_len = XTextWidth(ae_font, temp_ptr->string, (temp_ptr->length -1));
1453 }
1454 if (line_len > max_len)
1455 max_len = line_len;
1456 temp_ptr = temp_ptr->next;
1457 }
1458
1459 if (lines_to_display == 0)
1460 return(0);
1461
1462 if (max_len > max_width)
1463 max_len = max_width;
1464
1465 /*
1466 | set up summary window information
1467 */
1468
1469 xsh.height = lines_to_display * fontheight;
1470 xsh.width = max_len + 6;
1471
1472 if (sxsh.flags == (USPosition | USSize)) /* really specified by user */
1473 {
1474 /*
1475 | check for negative geometry information
1476 */
1477 if (sx_neg)
1478 xsh.x = XDisplayWidth(disp_ptr, screen) + sx - xsh.width - (2 * border_width);
1479 else
1480 xsh.x = sx;
1481 if (sy_neg)
1482 xsh.y = XDisplayHeight(disp_ptr, screen) + sy - xsh.height - (2 * border_width);
1483 else
1484 xsh.y = sy;
1485 }
1486 else
1487 {
1488 xsh.x = max(0, (x - xsh.width));
1489 xsh.y = max(0, (y - xsh.height));
1490 xsh.flags = USPosition | USSize;
1491 }
1492
1493 if ((from_wid = XCreateWindow(disp_ptr, RootWindow(disp_ptr, screen),
1494 xsh.x, xsh.y, xsh.width, xsh.height, border_width,
1495 DefaultDepth(disp_ptr, screen),
1496 InputOutput, DefaultVisual(disp_ptr, screen), (CWBackPixel |
1497 CWBackPixmap | CWColormap), &win_attrib))
1498 == 0)
1499 {
1500 fprintf(stderr, "could not create window for \"From\" info\n");
1501 }
1502
1503 XSetStandardProperties(disp_ptr, from_wid, "hbiff", "hbiff", pix[1],
1504 argv1, argc1, &xsh);
1505
1506 XSetClassHint(disp_ptr, from_wid, &class_spec);
1507 XSetWindowBackground(disp_ptr, from_wid, summary_background);
1508 XSelectInput(disp_ptr, from_wid, (ButtonPressMask | KeyPressMask | ExposureMask ));
1509 XMapWindow(disp_ptr, from_wid);
1510 XFlush(disp_ptr);
1511
1512 paint_lines(new_mail_only);
1513 }
1514
1515 /*
1516 | Print appropriate summary information in summary window.
1517 */
1518
paint_lines(new_mail_only)1519 paint_lines(new_mail_only)
1520 int new_mail_only;
1521 {
1522 struct from_text *temp_ptr;
1523 int counter, i;
1524 /*
1525 | display the text
1526 */
1527 for (i = 0, temp_ptr = new_msg_list, counter = 0; i < lines; i++)
1528 {
1529 if ((new_mail_only & temp_ptr->flag) || (!new_mail_only))
1530 {
1531 XDrawImageString(disp_ptr, from_wid, summary_gc, 2,
1532 ((counter * fontheight) + ae_font->ascent),
1533 temp_ptr->string, (temp_ptr->length - 1));
1534 counter++;
1535 }
1536 temp_ptr = temp_ptr->next;
1537 }
1538 XFlush(disp_ptr);
1539 }
1540
nuke_summary_window()1541 nuke_summary_window()
1542 {
1543 /*
1544 | Destroy summary window.
1545 */
1546
1547 XDestroyWindow(disp_ptr, from_wid);
1548 from_wid = 0;
1549 new_mail_showing = FALSE;
1550 }
1551
1552 /*
1553 | Recursively traverse the list and reverse the ordering.
1554 */
1555
1556 reverse_order(ptr)
1557 struct from_text *ptr;
1558 {
1559 struct from_text *tmp_ptr;
1560
1561 if (ptr->next != NULL)
1562 {
1563 reverse_order(ptr->next);
1564 ptr->next->next = ptr;
1565 ptr->next = NULL;
1566 }
1567 }
1568
1569 /*
1570 | Traverse the list and reset flags indicating that a message is
1571 | considered new.
1572 */
1573
1574 unmark_msgs(ptr)
1575 struct from_text *ptr;
1576 {
1577 struct from_text *tmp_ptr = ptr;
1578
1579 while (tmp_ptr != NULL)
1580 {
1581 tmp_ptr->flag = FALSE;
1582 tmp_ptr = tmp_ptr->next;
1583 }
1584 new_lines = 0;
1585 }
1586
1587 free_list(ptr)
1588 struct from_text *ptr;
1589 {
1590 /*
1591 | recursively traverse linked list, freeing data
1592 */
1593 if (ptr->next != NULL)
1594 {
1595 free_list(ptr->next);
1596 }
1597 if (ptr->string != NULL)
1598 {
1599 free(ptr->string);
1600 }
1601 free(ptr);
1602 }
1603
from_parse(out_buffer,in_buffer)1604 from_parse(out_buffer, in_buffer)
1605 char *out_buffer, *in_buffer;
1606 {
1607 int counter;
1608 char *temp_ptr;
1609 char *start_of_name;
1610 char open_paren, close_paren;
1611
1612 open_paren = '(';
1613 close_paren = ')';
1614
1615 memset(out_buffer, 0, 512);
1616
1617 if ((temp_ptr = strchr(in_buffer, '"')))
1618 {
1619 /* move to first character after open quote */
1620 temp_ptr++;
1621 start_of_name = temp_ptr;
1622 for (counter = 0; ((*temp_ptr != NULL) &&
1623 (*temp_ptr != '"') && (counter < 512)); counter++)
1624 temp_ptr++;
1625 strcpy(out_buffer, "From: ");
1626 strncat(out_buffer, start_of_name, counter);
1627 }
1628 else if ((temp_ptr = strchr(in_buffer, open_paren)))
1629 {
1630 /* move to first character after open paren */
1631 temp_ptr++;
1632 start_of_name = temp_ptr;
1633 for (counter = 0; ((*temp_ptr != NULL) &&
1634 (*temp_ptr != close_paren) && (counter < 512)); counter++)
1635 temp_ptr++;
1636 strcpy(out_buffer, "From: ");
1637 strncat(out_buffer, start_of_name, counter);
1638 }
1639 else if ((temp_ptr = strchr(in_buffer, '<')))
1640 {
1641 temp_ptr = in_buffer;
1642 while ((*temp_ptr != ' ') && (*temp_ptr != NULL))
1643 temp_ptr++;
1644 while ((*temp_ptr == ' ') && (*temp_ptr != NULL))
1645 temp_ptr++;
1646 start_of_name = temp_ptr;
1647 for (counter = 0; ((*temp_ptr != NULL) &&
1648 (*temp_ptr != '<') && (counter < 512)); counter++)
1649 temp_ptr++;
1650 strcpy(out_buffer, "From: ");
1651 strncat(out_buffer, start_of_name, counter);
1652 }
1653 else
1654 {
1655 strncpy(out_buffer, in_buffer, (strlen(in_buffer) - 1));
1656 }
1657 }
1658
clear_child()1659 clear_child()
1660 {
1661 int value;
1662
1663 value = wait(0);
1664 if (value == child_num)
1665 child_num = 0;
1666 }
1667
1668 /*
1669 | The code for setting the beeper to a different tone, beeping, and
1670 | restoring the beeper settings to what they were before is taken from
1671 | code written by Roger Petersen.
1672 */
1673
restore_kbd()1674 restore_kbd()
1675 {
1676 int mask;
1677 /* Restore initial bell values */
1678 mask = KBBellPercent | KBBellPitch | KBBellDuration;
1679 XChangeKeyboardControl(disp_ptr, mask, &save_kbd);
1680
1681 XFlush (disp_ptr);
1682 }
1683
high_res_sleep(milli_seconds)1684 void high_res_sleep(milli_seconds)
1685 long milli_seconds;
1686 {
1687 int fds = 0;
1688 struct timeval timeout;
1689
1690 timeout.tv_sec = milli_seconds / 1000; /* Seconds */
1691 timeout.tv_usec = (milli_seconds % 1000) * 1000; /* Micro-seconds */
1692 select(0, &fds, &fds, &fds, &timeout);
1693 }
1694
1695 #define SLEEP_TIMER_OVERHEAD 20; /* Milliseconds overhead in sleep routine */
1696
1697 /*
1698 * Play a tone.
1699 * The HP buffer-box with speaker seems to be capable of a range from
1700 * 82 Hz thru 16666 Hz inclusive.
1701 * 0 to 81 Hz are non-existent. 16667 Hz and above are non-existent.
1702 */
tone(volume,pitch,duration)1703 void tone(volume, pitch, duration)
1704 int volume, pitch, duration;
1705 {
1706 XKeyboardControl set_bell;
1707 unsigned int mask;
1708 unsigned int overhead;
1709
1710 overhead = SLEEP_TIMER_OVERHEAD; /* May need to be fancier, someday. */
1711 if (duration < (overhead + 10)) overhead = 0;
1712
1713 /* Limit changes to Bell */
1714 mask = KBBellPercent | KBBellPitch | KBBellDuration;
1715
1716 /* Make some changes. */
1717 set_bell.bell_percent = volume;
1718 set_bell.bell_pitch = pitch;
1719 set_bell.bell_duration = duration;
1720 XChangeKeyboardControl(disp_ptr, mask, &set_bell);
1721 XBell (disp_ptr, 0);
1722 XFlush (disp_ptr);
1723 high_res_sleep(duration - overhead);
1724 }
1725
beep_new()1726 beep_new()
1727 {
1728 XKeyboardState query_kbd;
1729
1730 /* Save current values in query_kbd */
1731 XGetKeyboardControl(disp_ptr, &query_kbd);
1732
1733 save_kbd.bell_percent = query_kbd.bell_percent;
1734 save_kbd.bell_pitch = query_kbd.bell_pitch;
1735 save_kbd.bell_duration = query_kbd.bell_duration;
1736
1737 tone(global_volume, 523, 360);
1738 tone(global_volume, 1, 40);
1739 tone(global_volume, 392, 720);
1740
1741 restore_kbd();
1742 }
1743