bday
changeset 7:b6f4c7fba64a
all sources now in one file
author | meillo@marmaro.de |
---|---|
date | Tue, 18 Dec 2007 11:59:21 +0100 |
parents | fc6e40f7bd5a |
children | 19c1ad697022 |
files | Makefile bday.c bdengine.c birthday.c birthday.h |
diffstat | 5 files changed, 665 insertions(+), 750 deletions(-) [+] |
line diff
1.1 --- a/Makefile Mon Dec 17 16:31:40 2007 +0100 1.2 +++ b/Makefile Tue Dec 18 11:59:21 2007 +0100 1.3 @@ -12,7 +12,7 @@ 1.4 BINDIR = ${PREFIX}/bin 1.5 MANDIR = ${PREFIX}/share/man 1.6 1.7 -SRC=birthday.c bdengine.c 1.8 +SRC=bday.c 1.9 OBJ=$(SRC:.c=.o) 1.10 1.11 CFLAGS=-O2 -Wall
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/bday.c Tue Dec 18 11:59:21 2007 +0100 2.3 @@ -0,0 +1,664 @@ 2.4 +/* 2.5 + birthday 2.6 + 2.7 + Birthday/Anniversary display on login 2.8 + 2.9 + (c) 1996 AS Mortimer 2.10 + 2.11 + This program is free software; you can redistribute it and/or 2.12 + modify it under the terms of the GNU General Public License as 2.13 + published by the Free Software Foundation; either version 2 of the 2.14 + License, or (at your option) any later version. You may also 2.15 + distribute it under the Artistic License, as comes with Perl. 2.16 + 2.17 + This program is distributed in the hope that it will be useful, 2.18 + but WITHOUT ANY WARRANTY; without even the implied warranty of 2.19 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 2.20 + 2.21 + You should have received a copy of the GNU General Public License 2.22 + along with this program; if not, write to the Free Software 2.23 + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 2.24 + 2.25 + You should also have recieved a copy of the Artistic license with 2.26 + this program. 2.27 + 2.28 + 2.29 + We're getting there. At the moment, the file used by default is ~/.birthdays 2.30 + under UNIX, or C:\PERSONAL\BDAYS.LST under DOS, but this can be overridden on 2.31 + the command line. The file has the following format: 2.32 + 2.33 + name/event/whatever=date flags 2.34 + where: 2.35 + date is dd/mm, dd/mm/yy (assumes 20th century!) or dd/mm/yyyy 2.36 + flags is ONE or ZERO of 2.37 + o bd for a birthday (default) 2.38 + o ann for an anniversary 2.39 + o ev for an event 2.40 + and zero or more of 2.41 + o w <n> to set the warn-in-advance time to n days (don't include the 2.42 + brackets! :) 2.43 + o to <date> 2.44 + o for <days> 2.45 + to specify the length of time taken by an event, for example a 2.46 + holiday. 2.47 + 2.48 + Comment lines are preceeded by #. 2.49 + 2.50 + Note: If you deviate from this format, I cannot guarantee anything about 2.51 + it's behaviour. In most cases, it will just quietly ignore the error, 2.52 + which probably isn't ideal behaviour. Oh, well. 2.53 + 2.54 + 2003/05/20: Automatic reallocation of output buffer in listsrings() by 2.55 + Sebastian Schmidt <yath@yath.eu.org>. 2.56 + 2.57 +*/ 2.58 + 2.59 + 2.60 +#include <stdarg.h> 2.61 +#include <stdio.h> 2.62 +#include <stdlib.h> 2.63 +#include <string.h> 2.64 +#include <sys/types.h> 2.65 +#include <time.h> 2.66 +#include <unistd.h> 2.67 + 2.68 + 2.69 + 2.70 +/* standard time to warn in advance, when no explicit w flag is given. */ 2.71 +#define DEF_WARN 14 2.72 + 2.73 +/* ========== Global constants and data types */ 2.74 + 2.75 + 2.76 +/* month lengths etc */ 2.77 + 2.78 +#define isleapyear(y) ((y)%4==0 && ((y)%100 != 0 || (y)%400 == 0)) 2.79 +const unsigned MLENDAT[]; 2.80 +#define mlen(m,y) (MLENDAT[(m)-1] != -1 ? MLENDAT[(m)-1] : (isleapyear((y)) ? 29 : 28)) 2.81 +#define before(a,b) ((a).month < (b).month || ((a).month == (b).month && (a).day < (b).day)) 2.82 +#define ydelta(a,b) ((int) (b).year - (a).year + before((a),(b))) 2.83 + 2.84 +/* -------- modifier flags */ 2.85 + 2.86 +#define F_MTYPE 0x07 2.87 +#define F_TBIRTHDAY 1 2.88 +#define F_TANNIVERSARY 2 2.89 +#define F_TEVENT 3 2.90 + 2.91 +/* flags processed immediately on encountering */ 2.92 +#define F_MIMMEDIATE 0x24 2.93 +#define F_WTIME_P 0x08 2.94 +#define F_FORDAYS 0x16 2.95 +#define F_TODATE 0x24 2.96 + 2.97 +struct _ftable {char *txt; unsigned flag;}; 2.98 + 2.99 +const struct _ftable FTABLE[]; 2.100 + 2.101 +struct date { 2.102 + unsigned day; 2.103 + unsigned month; 2.104 + unsigned year; 2.105 +}; 2.106 + 2.107 +struct event { 2.108 + char *text; 2.109 + struct date date; 2.110 + struct date enddate; 2.111 + int warn; 2.112 +}; 2.113 + 2.114 +typedef int (*prnfunc)(const char *); 2.115 + 2.116 +/* ========== Global Variables */ 2.117 + 2.118 +struct event* readlist(void); 2.119 +void gettoday(void); 2.120 +unsigned delta(struct date *); 2.121 +unsigned ddiff(struct date *D1, struct date *D2); 2.122 +void liststrings(struct event* evl, prnfunc outf); 2.123 +char *tdelta(struct date *d); 2.124 +char *ttime(int yr, int mn, int wk, int dy); 2.125 + 2.126 +int skptok(int j, char *ptr); 2.127 +int evcmp(const void *e1, const void *e2); 2.128 + 2.129 + 2.130 +struct date today; 2.131 +int iDWarn = DEF_WARN; 2.132 + 2.133 +const unsigned MLENDAT[]={31,-1,31,30,31,30,31,31,30,31,30,31}; 2.134 + 2.135 +const struct _ftable FTABLE[] = { 2.136 + {"bd", F_TBIRTHDAY}, 2.137 + {"ann",F_TANNIVERSARY}, 2.138 + {"ev", F_TEVENT}, 2.139 + {"w", F_WTIME_P}, 2.140 + {"to", F_TODATE}, 2.141 + {"for", F_FORDAYS}, 2.142 + {NULL, 0} 2.143 +}; 2.144 + 2.145 + 2.146 + 2.147 + 2.148 + 2.149 + 2.150 +/* 2.151 + xmalloc/xrealloc functions 2.152 + Note: the x* functions are lifted straight from the GNU libc info docs 2.153 + $Id: xmalloc.c,v 1.2 1999/01/16 17:08:59 andy Exp $ 2.154 +*/ 2.155 + 2.156 +void* xmalloc (size_t size) { 2.157 + register void* value = malloc (size); 2.158 + if (value == 0) { 2.159 + fprintf(stderr, "virtual memory exhausted\n"); 2.160 + exit(1); 2.161 + } 2.162 + return value; 2.163 +} 2.164 + 2.165 + 2.166 +void* xrealloc (void* ptr, size_t size) { 2.167 + register void* value = realloc (ptr, size); 2.168 + if (value == 0) { 2.169 + fprintf(stderr, "virtual memory exhausted\n"); 2.170 + exit(1); 2.171 + } 2.172 + return value; 2.173 +} 2.174 + 2.175 +/* ========== */ 2.176 + 2.177 + 2.178 + 2.179 +/* like strcat(), but lets the buffer automagically grow :-) 2.180 + * (needs local variable "size" with the buffer size) */ 2.181 +#define append(where, what) do { \ 2.182 + if (strlen(what) > (size - strlen(where))) { \ 2.183 + xrealloc(where, size + 128 + strlen(what)); \ 2.184 + size += 128 + strlen(what); \ 2.185 + } \ 2.186 + strcat(where, what); \ 2.187 +} while(0) 2.188 + 2.189 +/* ========== */ 2.190 + 2.191 +/* returns delta(d) in days, weeks, months, etc 2.192 + * the returned buffer is malloc()ed, do not forget to free() it */ 2.193 +char *tdelta(struct date *d) { 2.194 + int dy, wk, mn, yr; 2.195 + char *tmp; 2.196 + char *buf = xmalloc(128); 2.197 + int size = 128; 2.198 + *buf = 0; 2.199 + 2.200 + switch (delta(d)) { 2.201 + case 0: 2.202 + append(buf, "today"); 2.203 + return buf; 2.204 + case 1: 2.205 + append(buf, "tomorrow"); 2.206 + return buf; 2.207 + default: 2.208 + /* like delta(), we ignore the year */ 2.209 + yr=-before(*d,today); 2.210 + mn=d->month - today.month; 2.211 + dy=d->day - today.day; 2.212 + 2.213 + if (dy < 0) { 2.214 + dy += mlen(today.month, today.year); 2.215 + mn--; 2.216 + } 2.217 + if (mn < 0) { 2.218 + mn += 12; 2.219 + yr++; 2.220 + } 2.221 + 2.222 + wk = (dy / 7); 2.223 + dy %= 7; 2.224 + 2.225 + append(buf, "in "); 2.226 + tmp = ttime(yr, mn, wk, dy); 2.227 + append(buf, tmp); 2.228 + free(tmp); 2.229 + 2.230 + return buf; 2.231 + } 2.232 +} 2.233 + 2.234 + 2.235 + 2.236 + 2.237 + 2.238 +/* 2.239 +void donum(n,txt) { 2.240 + do { 2.241 + if (n > 0) { 2.242 + snprintf(tmp, sizeof(tmp), "%d", n); 2.243 + append(buf, tmp); 2.244 + append(buf, " " txt); 2.245 + if (n != 1) 2.246 + append(buf, "s"); 2.247 + terms--; 2.248 + if (orgterms > 1) { 2.249 + if (terms == 1) 2.250 + append(buf, " and "); 2.251 + else if (terms > 1) 2.252 + append(buf, ", "); 2.253 + } 2.254 + } 2.255 + } while(0) 2.256 +} 2.257 +*/ 2.258 + 2.259 + 2.260 +#define donum(n,txt) do { \ 2.261 + if (n > 0) { \ 2.262 + snprintf(tmp, sizeof(tmp), "%d", n); \ 2.263 + append(buf, tmp); \ 2.264 + append(buf, " " txt); \ 2.265 + if (n != 1) \ 2.266 + append(buf, "s"); \ 2.267 + terms--; \ 2.268 + if (orgterms > 1) { \ 2.269 + if (terms == 1) \ 2.270 + append(buf, " and "); \ 2.271 + else if (terms > 1) \ 2.272 + append(buf, ", "); \ 2.273 + } \ 2.274 + } \ 2.275 +} while(0) 2.276 + 2.277 + 2.278 +/* returns allocated buffer, don't forget to free() */ 2.279 +char* ttime(int yr, int mn, int wk, int dy) { 2.280 + char* buf = xmalloc(128); 2.281 + int size = 128; 2.282 + int terms, orgterms; 2.283 + char tmp[128]; 2.284 + 2.285 + *buf = 0; /* Initialize buffer */ 2.286 + terms = orgterms = (yr!=0) + (mn!=0) + (wk!=0) + (dy!=0); 2.287 + 2.288 + donum(yr, "year"); 2.289 + donum(mn, "month"); 2.290 + donum(wk, "week"); 2.291 + donum(dy, "day"); 2.292 + 2.293 + return buf; 2.294 +} 2.295 +#undef donum 2.296 + 2.297 + 2.298 + 2.299 + 2.300 + 2.301 + 2.302 +/* lists the birthdays in their string format, one by one, and passes the string to a function. */ 2.303 +void liststrings(struct event* evl, prnfunc outf) { 2.304 + int i,j; 2.305 + char *buf, *tmp; 2.306 + int size; 2.307 + 2.308 + for (i = 0; evl[i].text != NULL; i++) { 2.309 + buf = xmalloc(128); 2.310 + *buf = '\0'; 2.311 + size = 128; 2.312 + 2.313 + if (evl[i].warn == -1 && delta(&(evl[i].date))==0) { 2.314 + append(buf, evl[i].text); 2.315 + } else if (evl[i].enddate.day == 0) { 2.316 + if (delta(&(evl[i].date)) <= evl[i].warn) { 2.317 + append(buf, evl[i].text); 2.318 + append(buf, " "); 2.319 + tmp = tdelta(&(evl[i].date)); 2.320 + append(buf, tmp); 2.321 + free(tmp); 2.322 + } 2.323 + } else { 2.324 + if (delta(&(evl[i].date)) <= evl[i].warn) { 2.325 + append(buf, evl[i].text); 2.326 + append(buf, " for "); 2.327 + /* +1 because, if the difference between two dates is one day, then the length of an event on those days is two days */ 2.328 + j = ddiff(&(evl[i].date),&(evl[i].enddate)) + 1; 2.329 + tmp = ttime(0, 0, j/7, j%7); 2.330 + append(buf, tmp); 2.331 + free(tmp); 2.332 + append(buf, " "); 2.333 + tmp = tdelta(&(evl[i].date)); 2.334 + append(buf, tmp); 2.335 + } else if (delta(&(evl[i].enddate)) <= evl[i].warn) { 2.336 + append(buf, evl[i].text); 2.337 + append(buf, " "); 2.338 + j = delta(&(evl[i].enddate)); 2.339 + if (j) { 2.340 + append(buf, "for "); 2.341 + tmp = ttime(0, 0, j/7, j%7); 2.342 + append(buf, tmp); 2.343 + free(tmp); 2.344 + append(buf, " longer"); 2.345 + } else { 2.346 + append(buf, "finishes today"); 2.347 + } 2.348 + } 2.349 + } 2.350 + if (*buf) { 2.351 + append(buf, "."); 2.352 + outf(buf); 2.353 + } 2.354 + free(buf); 2.355 + } 2.356 +} 2.357 + 2.358 + 2.359 + 2.360 + 2.361 + 2.362 + 2.363 + 2.364 + 2.365 +/* sort the events by the time before the next time they come up, putting those 2.366 + where the start has passed but we are still in the time-period first */ 2.367 +int evcmp(const void *p1, const void *p2) { 2.368 + struct event *e1=(struct event *)p1; 2.369 + struct event *e2=(struct event *)p2; 2.370 + unsigned d1,d2; 2.371 + 2.372 + /* if the delta for the enddate is less than that for the start date, then we 2.373 + have passed the start date but not yet the end date, and so we should 2.374 + display the enddate; otherwise, we should display the start date */ 2.375 + 2.376 + d1=delta(&(e1->date)); 2.377 + if (e1->enddate.day && delta(&(e1->enddate)) < d1) 2.378 + d1=delta(&(e1->enddate)); 2.379 + 2.380 + d2=delta(&(e2->date)); 2.381 + if (e2->enddate.day && delta(&(e2->enddate)) < d2) 2.382 + d2=delta(&(e2->enddate)); 2.383 + 2.384 + if (d1 < d2) return -1; 2.385 + if (d1 > d2) return 1; 2.386 + 2.387 + return strcmp(e1->text, e2->text); 2.388 +} 2.389 + 2.390 + 2.391 + 2.392 + 2.393 + 2.394 + 2.395 +/* difference in days between two dates */ 2.396 +/* it is assumed that D1 < D2, and so the result is always positive */ 2.397 +unsigned ddiff(struct date *D1, struct date *D2) { 2.398 + struct date d1,d2; 2.399 + int dd,m; 2.400 + 2.401 + /* make working copies */ 2.402 + d1=*D1; 2.403 + d2=*D2; 2.404 + 2.405 + /* sort out zero years */ 2.406 + if (d1.year == 0 || d2.year==0) { 2.407 + if (d1.year != d2.year) { 2.408 + if (d1.year == 0) { 2.409 + if (before(d1,d2)) 2.410 + d1.year=d2.year; 2.411 + else 2.412 + d1.year=d2.year-1; 2.413 + } else { 2.414 + if (before(d1,d2)) 2.415 + d2.year=d1.year; 2.416 + else 2.417 + d2.year=d1.year+1; 2.418 + } 2.419 + } else { /* both years zero */ 2.420 + if (before(d1,d2)) 2.421 + d1.year=d2.year=today.year; 2.422 + else { 2.423 + d1.year=today.year; 2.424 + d2.year=d1.year+1; 2.425 + } 2.426 + } 2.427 + } 2.428 + 2.429 + /* now we can actually do the comparison ... */ 2.430 + dd=0; 2.431 + 2.432 + /* to start with, we work in months */ 2.433 + for (m=d1.month; m < d2.month + (d2.year-d1.year)*12; m++) 2.434 + dd += mlen(((m-1)%12)+1, d1.year + m/12); 2.435 + 2.436 + /* and then we renormalise for the days within the months */ 2.437 + /* the first month was included in our calculations */ 2.438 + dd -= d1.day; 2.439 + /* but the last one wasn't */ 2.440 + dd += d2.day; 2.441 + 2.442 + return dd; 2.443 +} 2.444 + 2.445 + 2.446 + 2.447 + 2.448 + 2.449 + 2.450 + 2.451 + 2.452 +/* actually until the next anniversary of ... */ 2.453 +unsigned delta(struct date *date) { 2.454 + struct date d; 2.455 + unsigned dt, mn; 2.456 + 2.457 + memcpy(&d, date, sizeof(struct date)); 2.458 + 2.459 + /* past the end of the year */ 2.460 + if (before(d, today)) { 2.461 + d.year = 1; 2.462 + } else { 2.463 + d.year = 0; 2.464 + } 2.465 + 2.466 + for (mn = today.month, dt=0; mn < d.month + 12*d.year; mn++) 2.467 + dt += mlen(((mn-1)%12) + 1,today.year + mn/12); 2.468 + 2.469 + dt -= today.day; 2.470 + dt += d.day; 2.471 + 2.472 + return dt; 2.473 +} 2.474 + 2.475 + 2.476 + 2.477 + 2.478 + 2.479 + 2.480 +void gettoday(void) { 2.481 + struct tm *tm; 2.482 + time_t t; 2.483 + 2.484 + time(&t); 2.485 + tm = localtime(&t); 2.486 + today.day = tm->tm_mday; 2.487 + today.month = tm->tm_mon + 1; /* 1-12 instead of 0-11 */ 2.488 + today.year = tm->tm_year + 1900; 2.489 +} 2.490 + 2.491 + 2.492 + 2.493 + 2.494 + 2.495 + 2.496 + 2.497 + 2.498 + 2.499 + 2.500 +struct event* readlist() { 2.501 + int i, j, k, l, d; 2.502 + struct event *evl; 2.503 + char buf[1024], buf2[1024]; 2.504 + char *ptr; 2.505 + unsigned flags; 2.506 + 2.507 + /* initialise */ 2.508 + gettoday(); 2.509 + 2.510 + for (i = 0, evl = NULL; fgets(buf, sizeof(buf), stdin) != NULL; i++) { 2.511 + evl = (struct event *) xrealloc(evl, sizeof(struct event) * (i + 1)); 2.512 + 2.513 + /* ignore comments and empty lines */ 2.514 + if (*buf == '#' || *buf == '\n') { 2.515 + i--; 2.516 + continue; 2.517 + } 2.518 + 2.519 + /* parse string in buf */ 2.520 + ptr = strrchr(buf, '='); /* allow '=' in text */ 2.521 + 2.522 + /* not a valid line, so ignore it! Cool, huh? */ 2.523 + /* Attention: only recognizes lines without '=' */ 2.524 + if (ptr == NULL) { 2.525 + fprintf(stderr, "WARNING: Invalid line in input:\n%s", buf); 2.526 + i--; 2.527 + continue; 2.528 + } 2.529 + 2.530 + *(ptr++) = 0; 2.531 + 2.532 + j = sscanf(ptr, "%u-%u-%u", &(evl[i].date.year), &(evl[i].date.month), &(evl[i].date.day)); 2.533 + /* ... unless it wasn't read, in which case set it to zero */ 2.534 + if (j==2) { 2.535 + evl[i].date.year = 0; 2.536 + } 2.537 + 2.538 + 2.539 + /* parse flags */ 2.540 + 2.541 + evl[i].warn = iDWarn; 2.542 + evl[i].enddate.day = 0; 2.543 + evl[i].enddate.month = 0; 2.544 + evl[i].enddate.year = 0; 2.545 + 2.546 + flags = 0; 2.547 + j = 0; 2.548 + 2.549 + while(j = skptok(j, ptr), ptr[j] != 0) { 2.550 + for (k = 0; FTABLE[k].txt != NULL && strncmp(FTABLE[k].txt, ptr + j, strlen(FTABLE[k].txt)); k++) { 2.551 + } 2.552 + 2.553 + switch (FTABLE[k].flag) { 2.554 + case F_WTIME_P: /* w <n> -- sets warning time */ 2.555 + sscanf(ptr + j, "w %u", &(evl[i].warn)); 2.556 + break; 2.557 + case F_FORDAYS: /* for <days> -- sets the duration of the event */ 2.558 + sscanf(ptr + j, "for %u", &d); 2.559 + evl[i].enddate=evl[i].date; 2.560 + for (l = 1; l < d; l++) { 2.561 + evl[i].enddate.day++; 2.562 + if (evl[i].enddate.day > mlen(evl[i].enddate.month, evl[i].enddate.year)) { 2.563 + evl[i].enddate.month++; 2.564 + evl[i].enddate.day = 1; 2.565 + } 2.566 + if (evl[i].enddate.month > 12) { 2.567 + evl[i].enddate.year++; 2.568 + evl[i].enddate.month = 1; 2.569 + } 2.570 + } 2.571 + break; 2.572 + case F_TODATE: /* to <date> -- sets the end date of the event */ 2.573 + l = sscanf(ptr + j, "to %u-%u-%u", &(evl[i].enddate.year), &(evl[i].enddate.month), &(evl[i].enddate.day)); 2.574 + if (l == 2) { 2.575 + evl[i].enddate.year = 0; 2.576 + } 2.577 + break; 2.578 + case 0: 2.579 + break; 2.580 + default: 2.581 + flags |= FTABLE[k].flag; 2.582 + break; 2.583 + } 2.584 + } 2.585 + 2.586 + 2.587 + /* construct event text */ 2.588 + 2.589 + switch(flags & F_MTYPE) { 2.590 + case F_TBIRTHDAY: 2.591 + default: /* assume it's a birthday */ 2.592 + if (evl[i].date.year != 0) { 2.593 + int tmp_age = ydelta(evl[i].date, today); 2.594 + if (tmp_age != 1) { 2.595 + sprintf(buf2, "%s is %d years old", buf, tmp_age); 2.596 + } else { 2.597 + sprintf(buf2, "%s is %d year old", buf, tmp_age); 2.598 + } 2.599 + } else { 2.600 + sprintf(buf2, "%s has a birthday", buf); 2.601 + } 2.602 + break; 2.603 + case F_TANNIVERSARY: 2.604 + if (evl[i].date.year != 0) { 2.605 + sprintf(buf2, "%s %d years ago", buf, ydelta(evl[i].date, today)); 2.606 + } else { 2.607 + strcpy(buf2, buf); 2.608 + } 2.609 + break; 2.610 + case F_TEVENT: 2.611 + /* if a year was specified, and this warning isn't for it, ignore! */ 2.612 + if ((evl[i].date.year != 0 && ydelta(evl[i].date, today) != 0) && (evl[i].enddate.year == 0 || ydelta(evl[i].enddate, today) != 0)) { 2.613 + i--; 2.614 + continue; 2.615 + } 2.616 + strcpy(buf2, buf); 2.617 + break; 2.618 + } 2.619 + evl[i].text = strdup(buf2); 2.620 + } 2.621 + 2.622 + evl = (struct event *) xrealloc(evl, sizeof(struct event) * (i + 1)); 2.623 + evl[i].date.day = 0; 2.624 + evl[i].date.month = 0; 2.625 + evl[i].date.year = 0; 2.626 + evl[i].text = (char *) NULL; 2.627 + 2.628 + fclose(stdin); 2.629 + 2.630 + /* NB uses i from above */ 2.631 + qsort(evl, i, sizeof(struct event), evcmp); 2.632 + return evl; 2.633 +} 2.634 + 2.635 + 2.636 + 2.637 + 2.638 + 2.639 +int skptok(int j, char *ptr) { 2.640 + for (; ptr[j] != 0 && ptr[j] != ' ' && ptr[j] != '\t' ; j++); 2.641 + for (; ptr[j] != 0 && (ptr[j] == ' ' || ptr[j] == '\t'); j++); 2.642 + 2.643 + return j; 2.644 +} 2.645 + 2.646 + 2.647 + 2.648 + 2.649 + 2.650 + 2.651 +int main(int argc, char* argv[]) { 2.652 + 2.653 + while (--argc > 0 && (*++argv)[0] == '-') { 2.654 + if (strcmp(argv[0], "-W") == 0) { 2.655 + /* TODO: catch if no value given */ 2.656 + iDWarn = atoi((++argv)[0]); 2.657 + argc--; 2.658 + } else { 2.659 + fprintf(stderr, "unknown option %s\n", argv[0]); 2.660 + exit(1); 2.661 + } 2.662 + } 2.663 + 2.664 + liststrings(readlist(), puts); 2.665 + 2.666 + return 0; 2.667 +}
3.1 --- a/bdengine.c Mon Dec 17 16:31:40 2007 +0100 3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 3.3 @@ -1,606 +0,0 @@ 3.4 -/* 3.5 - birthday.c 3.6 - 3.7 - Birthday/Anniversary display on login 3.8 - 3.9 - (c) 1996 AS Mortimer 3.10 - 3.11 - This program is free software; you can redistribute it and/or 3.12 - modify it under the terms of the GNU General Public License as 3.13 - published by the Free Software Foundation; either version 2 of the 3.14 - License, or (at your option) any later version. You may also 3.15 - distribute it under the Artistic License, as comes with Perl. 3.16 - 3.17 - This program is distributed in the hope that it will be useful, 3.18 - but WITHOUT ANY WARRANTY; without even the implied warranty of 3.19 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 3.20 - 3.21 - You should have received a copy of the GNU General Public License 3.22 - along with this program; if not, write to the Free Software 3.23 - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 3.24 - 3.25 - You should also have recieved a copy of the Artistic license with 3.26 - this program. 3.27 - 3.28 - $Id: bdengine.c,v 1.14 2001/10/21 07:03:49 andy Exp $ 3.29 - 3.30 - We're getting there. At the moment, the file used by default is ~/.birthdays 3.31 - under UNIX, or C:\PERSONAL\BDAYS.LST under DOS, but this can be overridden on 3.32 - the command line. The file has the following format: 3.33 - 3.34 - name/event/whatever=date flags 3.35 - where: 3.36 - date is dd/mm, dd/mm/yy (assumes 20th century!) or dd/mm/yyyy 3.37 - flags is ONE or ZERO of 3.38 - o bd for a birthday (default) 3.39 - o ann for an anniversary 3.40 - o ev for an event 3.41 - and zero or more of 3.42 - o w <n> to set the warn-in-advance time to n days (don't include the 3.43 - brackets! :) 3.44 - o to <date> 3.45 - o for <days> 3.46 - to specify the length of time taken by an event, for example a 3.47 - holiday. 3.48 - 3.49 - Comment lines are preceeded by #. 3.50 - 3.51 - Note: If you deviate from this format, I cannot guarantee anything about 3.52 - it's behaviour. In most cases, it will just quietly ignore the error, 3.53 - which probably isn't ideal behaviour. Oh, well. 3.54 - 3.55 - 2003/05/20: Automatic reallocation of output buffer in listsrings() by 3.56 - Sebastian Schmidt <yath@yath.eu.org>. 3.57 - 3.58 -*/ 3.59 - 3.60 - 3.61 - 3.62 -/* ========== */ 3.63 - 3.64 - 3.65 -#include <stdio.h> 3.66 -#include <stdarg.h> 3.67 -#include <stdlib.h> 3.68 -#include <string.h> 3.69 -#include <time.h> 3.70 - 3.71 -#include <sys/types.h> 3.72 -#include <unistd.h> 3.73 - 3.74 -#include "birthday.h" 3.75 - 3.76 -/* ========== */ 3.77 - 3.78 - 3.79 - 3.80 -/* 3.81 - xmalloc/xrealloc functions 3.82 - Note: the x* functions are lifted straight from the GNU libc info docs 3.83 - $Id: xmalloc.c,v 1.2 1999/01/16 17:08:59 andy Exp $ 3.84 -*/ 3.85 - 3.86 -void* xmalloc (size_t size) { 3.87 - register void* value = malloc (size); 3.88 - if (value == 0) { 3.89 - fprintf(stderr, "virtual memory exhausted\n"); 3.90 - exit(1); 3.91 - } 3.92 - return value; 3.93 -} 3.94 - 3.95 - 3.96 -void* xrealloc (void* ptr, size_t size) { 3.97 - register void* value = realloc (ptr, size); 3.98 - if (value == 0) { 3.99 - fprintf(stderr, "virtual memory exhausted\n"); 3.100 - exit(1); 3.101 - } 3.102 - return value; 3.103 -} 3.104 - 3.105 -/* ========== */ 3.106 - 3.107 - 3.108 - 3.109 - 3.110 - 3.111 - 3.112 -int skptok(int j, char *ptr); 3.113 -int evcmp(const void *e1, const void *e2); 3.114 - 3.115 - 3.116 -/* ========== Global variables */ 3.117 - 3.118 -struct date today; 3.119 -int iDWarn = DEF_WARN; 3.120 - 3.121 -const unsigned MLENDAT[]={31,-1,31,30,31,30,31,31,30,31,30,31}; 3.122 - 3.123 -const struct _ftable FTABLE[] = { 3.124 - {"bd", F_TBIRTHDAY}, 3.125 - {"ann",F_TANNIVERSARY}, 3.126 - {"ev", F_TEVENT}, 3.127 - {"w", F_WTIME_P}, 3.128 - {"to", F_TODATE}, 3.129 - {"for", F_FORDAYS}, 3.130 - {NULL, 0} 3.131 -}; 3.132 - 3.133 - 3.134 - 3.135 -/* ========== */ 3.136 - 3.137 - 3.138 - 3.139 -/* like strcat(), but lets the buffer automagically grow :-) 3.140 - * (needs local variable "size" with the buffer size) */ 3.141 -#define append(where, what) do { \ 3.142 - if (strlen(what) > (size - strlen(where))) { \ 3.143 - xrealloc(where, size + 128 + strlen(what)); \ 3.144 - size += 128 + strlen(what); \ 3.145 - } \ 3.146 - strcat(where, what); \ 3.147 -} while(0) 3.148 - 3.149 -/* ========== */ 3.150 - 3.151 -/* returns delta(d) in days, weeks, months, etc 3.152 - * the returned buffer is malloc()ed, do not forget to free() it */ 3.153 -char *tdelta(struct date *d) { 3.154 - int dy, wk, mn, yr; 3.155 - char *tmp; 3.156 - char *buf = xmalloc(128); 3.157 - int size = 128; 3.158 - *buf = 0; 3.159 - 3.160 - switch (delta(d)) { 3.161 - case 0: 3.162 - append(buf, "today"); 3.163 - return buf; 3.164 - case 1: 3.165 - append(buf, "tomorrow"); 3.166 - return buf; 3.167 - default: 3.168 - /* like delta(), we ignore the year */ 3.169 - yr=-before(*d,today); 3.170 - mn=d->month - today.month; 3.171 - dy=d->day - today.day; 3.172 - 3.173 - if (dy < 0) { 3.174 - dy += mlen(today.month, today.year); 3.175 - mn--; 3.176 - } 3.177 - if (mn < 0) { 3.178 - mn += 12; 3.179 - yr++; 3.180 - } 3.181 - 3.182 - wk = (dy / 7); 3.183 - dy %= 7; 3.184 - 3.185 - append(buf, "in "); 3.186 - tmp = ttime(yr, mn, wk, dy); 3.187 - append(buf, tmp); 3.188 - free(tmp); 3.189 - 3.190 - return buf; 3.191 - } 3.192 -} 3.193 - 3.194 - 3.195 - 3.196 - 3.197 - 3.198 -/* 3.199 -void donum(n,txt) { 3.200 - do { 3.201 - if (n > 0) { 3.202 - snprintf(tmp, sizeof(tmp), "%d", n); 3.203 - append(buf, tmp); 3.204 - append(buf, " " txt); 3.205 - if (n != 1) 3.206 - append(buf, "s"); 3.207 - terms--; 3.208 - if (orgterms > 1) { 3.209 - if (terms == 1) 3.210 - append(buf, " and "); 3.211 - else if (terms > 1) 3.212 - append(buf, ", "); 3.213 - } 3.214 - } 3.215 - } while(0) 3.216 -} 3.217 -*/ 3.218 - 3.219 - 3.220 -#define donum(n,txt) do { \ 3.221 - if (n > 0) { \ 3.222 - snprintf(tmp, sizeof(tmp), "%d", n); \ 3.223 - append(buf, tmp); \ 3.224 - append(buf, " " txt); \ 3.225 - if (n != 1) \ 3.226 - append(buf, "s"); \ 3.227 - terms--; \ 3.228 - if (orgterms > 1) { \ 3.229 - if (terms == 1) \ 3.230 - append(buf, " and "); \ 3.231 - else if (terms > 1) \ 3.232 - append(buf, ", "); \ 3.233 - } \ 3.234 - } \ 3.235 -} while(0) 3.236 - 3.237 - 3.238 -/* returns allocated buffer, don't forget to free() */ 3.239 -char* ttime(int yr, int mn, int wk, int dy) { 3.240 - char* buf = xmalloc(128); 3.241 - int size = 128; 3.242 - int terms, orgterms; 3.243 - char tmp[128]; 3.244 - 3.245 - *buf = 0; /* Initialize buffer */ 3.246 - terms = orgterms = (yr!=0) + (mn!=0) + (wk!=0) + (dy!=0); 3.247 - 3.248 - donum(yr, "year"); 3.249 - donum(mn, "month"); 3.250 - donum(wk, "week"); 3.251 - donum(dy, "day"); 3.252 - 3.253 - return buf; 3.254 -} 3.255 -#undef donum 3.256 - 3.257 - 3.258 - 3.259 - 3.260 - 3.261 - 3.262 -/* lists the birthdays in their string format, one by one, and passes the string to a function. */ 3.263 -void liststrings(struct event* evl, prnfunc outf) { 3.264 - int i,j; 3.265 - char *buf, *tmp; 3.266 - int size; 3.267 - 3.268 - for (i = 0; evl[i].text != NULL; i++) { 3.269 - buf = xmalloc(128); 3.270 - *buf = '\0'; 3.271 - size = 128; 3.272 - 3.273 - if (evl[i].warn == -1 && delta(&(evl[i].date))==0) { 3.274 - append(buf, evl[i].text); 3.275 - } else if (evl[i].enddate.day == 0) { 3.276 - if (delta(&(evl[i].date)) <= evl[i].warn) { 3.277 - append(buf, evl[i].text); 3.278 - append(buf, " "); 3.279 - tmp = tdelta(&(evl[i].date)); 3.280 - append(buf, tmp); 3.281 - free(tmp); 3.282 - } 3.283 - } else { 3.284 - if (delta(&(evl[i].date)) <= evl[i].warn) { 3.285 - append(buf, evl[i].text); 3.286 - append(buf, " for "); 3.287 - /* +1 because, if the difference between two dates is one day, then the length of an event on those days is two days */ 3.288 - j = ddiff(&(evl[i].date),&(evl[i].enddate)) + 1; 3.289 - tmp = ttime(0, 0, j/7, j%7); 3.290 - append(buf, tmp); 3.291 - free(tmp); 3.292 - append(buf, " "); 3.293 - tmp = tdelta(&(evl[i].date)); 3.294 - append(buf, tmp); 3.295 - } else if (delta(&(evl[i].enddate)) <= evl[i].warn) { 3.296 - append(buf, evl[i].text); 3.297 - append(buf, " "); 3.298 - j = delta(&(evl[i].enddate)); 3.299 - if (j) { 3.300 - append(buf, "for "); 3.301 - tmp = ttime(0, 0, j/7, j%7); 3.302 - append(buf, tmp); 3.303 - free(tmp); 3.304 - append(buf, " longer"); 3.305 - } else { 3.306 - append(buf, "finishes today"); 3.307 - } 3.308 - } 3.309 - } 3.310 - if (*buf) { 3.311 - append(buf, "."); 3.312 - outf(buf); 3.313 - } 3.314 - free(buf); 3.315 - } 3.316 -} 3.317 - 3.318 - 3.319 - 3.320 - 3.321 - 3.322 - 3.323 - 3.324 - 3.325 -/* sort the events by the time before the next time they come up, putting those 3.326 - where the start has passed but we are still in the time-period first */ 3.327 -int evcmp(const void *p1, const void *p2) { 3.328 - struct event *e1=(struct event *)p1; 3.329 - struct event *e2=(struct event *)p2; 3.330 - unsigned d1,d2; 3.331 - 3.332 - /* if the delta for the enddate is less than that for the start date, then we 3.333 - have passed the start date but not yet the end date, and so we should 3.334 - display the enddate; otherwise, we should display the start date */ 3.335 - 3.336 - d1=delta(&(e1->date)); 3.337 - if (e1->enddate.day && delta(&(e1->enddate)) < d1) 3.338 - d1=delta(&(e1->enddate)); 3.339 - 3.340 - d2=delta(&(e2->date)); 3.341 - if (e2->enddate.day && delta(&(e2->enddate)) < d2) 3.342 - d2=delta(&(e2->enddate)); 3.343 - 3.344 - if (d1 < d2) return -1; 3.345 - if (d1 > d2) return 1; 3.346 - 3.347 - return strcmp(e1->text, e2->text); 3.348 -} 3.349 - 3.350 - 3.351 - 3.352 - 3.353 - 3.354 - 3.355 -/* difference in days between two dates */ 3.356 -/* it is assumed that D1 < D2, and so the result is always positive */ 3.357 -unsigned ddiff(struct date *D1, struct date *D2) { 3.358 - struct date d1,d2; 3.359 - int dd,m; 3.360 - 3.361 - /* make working copies */ 3.362 - d1=*D1; 3.363 - d2=*D2; 3.364 - 3.365 - /* sort out zero years */ 3.366 - if (d1.year == 0 || d2.year==0) { 3.367 - if (d1.year != d2.year) { 3.368 - if (d1.year == 0) { 3.369 - if (before(d1,d2)) 3.370 - d1.year=d2.year; 3.371 - else 3.372 - d1.year=d2.year-1; 3.373 - } else { 3.374 - if (before(d1,d2)) 3.375 - d2.year=d1.year; 3.376 - else 3.377 - d2.year=d1.year+1; 3.378 - } 3.379 - } else { /* both years zero */ 3.380 - if (before(d1,d2)) 3.381 - d1.year=d2.year=today.year; 3.382 - else { 3.383 - d1.year=today.year; 3.384 - d2.year=d1.year+1; 3.385 - } 3.386 - } 3.387 - } 3.388 - 3.389 - /* now we can actually do the comparison ... */ 3.390 - dd=0; 3.391 - 3.392 - /* to start with, we work in months */ 3.393 - for (m=d1.month; m < d2.month + (d2.year-d1.year)*12; m++) 3.394 - dd += mlen(((m-1)%12)+1, d1.year + m/12); 3.395 - 3.396 - /* and then we renormalise for the days within the months */ 3.397 - /* the first month was included in our calculations */ 3.398 - dd -= d1.day; 3.399 - /* but the last one wasn't */ 3.400 - dd += d2.day; 3.401 - 3.402 - return dd; 3.403 -} 3.404 - 3.405 - 3.406 - 3.407 - 3.408 - 3.409 - 3.410 - 3.411 - 3.412 -/* actually until the next anniversary of ... */ 3.413 -unsigned delta(struct date *date) { 3.414 - struct date d; 3.415 - unsigned dt, mn; 3.416 - 3.417 - memcpy(&d, date, sizeof(struct date)); 3.418 - 3.419 - /* past the end of the year */ 3.420 - if (before(d, today)) { 3.421 - d.year = 1; 3.422 - } else { 3.423 - d.year = 0; 3.424 - } 3.425 - 3.426 - for (mn = today.month, dt=0; mn < d.month + 12*d.year; mn++) 3.427 - dt += mlen(((mn-1)%12) + 1,today.year + mn/12); 3.428 - 3.429 - dt -= today.day; 3.430 - dt += d.day; 3.431 - 3.432 - return dt; 3.433 -} 3.434 - 3.435 - 3.436 - 3.437 - 3.438 - 3.439 - 3.440 -void gettoday(void) { 3.441 - struct tm *tm; 3.442 - time_t t; 3.443 - 3.444 - time(&t); 3.445 - tm = localtime(&t); 3.446 - today.day = tm->tm_mday; 3.447 - today.month = tm->tm_mon + 1; /* 1-12 instead of 0-11 */ 3.448 - today.year = tm->tm_year + 1900; 3.449 -} 3.450 - 3.451 - 3.452 - 3.453 - 3.454 - 3.455 - 3.456 - 3.457 - 3.458 - 3.459 - 3.460 -struct event* readlist() { 3.461 - int i, j, k, l, d; 3.462 - struct event *evl; 3.463 - char buf[1024], buf2[1024]; 3.464 - char *ptr; 3.465 - unsigned flags; 3.466 - 3.467 - /* initialise */ 3.468 - gettoday(); 3.469 - 3.470 - for (i = 0, evl = NULL; fgets(buf, sizeof(buf), stdin) != NULL; i++) { 3.471 - evl = (struct event *) xrealloc(evl, sizeof(struct event) * (i + 1)); 3.472 - 3.473 - /* ignore comments and empty lines */ 3.474 - if (*buf == '#' || *buf == '\n') { 3.475 - i--; 3.476 - continue; 3.477 - } 3.478 - 3.479 - /* parse string in buf */ 3.480 - ptr = strrchr(buf, '='); /* allow '=' in text */ 3.481 - 3.482 - /* not a valid line, so ignore it! Cool, huh? */ 3.483 - /* Attention: only recognizes lines without '=' */ 3.484 - if (ptr == NULL) { 3.485 - fprintf(stderr, "WARNING: Invalid line in input:\n%s", buf); 3.486 - i--; 3.487 - continue; 3.488 - } 3.489 - 3.490 - *(ptr++) = 0; 3.491 - 3.492 - j = sscanf(ptr, "%u-%u-%u", &(evl[i].date.year), &(evl[i].date.month), &(evl[i].date.day)); 3.493 - /* ... unless it wasn't read, in which case set it to zero */ 3.494 - if (j==2) { 3.495 - evl[i].date.year = 0; 3.496 - } 3.497 - 3.498 - 3.499 - /* parse flags */ 3.500 - 3.501 - evl[i].warn = iDWarn; 3.502 - evl[i].enddate.day = 0; 3.503 - evl[i].enddate.month = 0; 3.504 - evl[i].enddate.year = 0; 3.505 - 3.506 - flags = 0; 3.507 - j = 0; 3.508 - 3.509 - while(j = skptok(j, ptr), ptr[j] != 0) { 3.510 - for (k = 0; FTABLE[k].txt != NULL && strncmp(FTABLE[k].txt, ptr + j, strlen(FTABLE[k].txt)); k++) { 3.511 - } 3.512 - 3.513 - switch (FTABLE[k].flag) { 3.514 - case F_WTIME_P: /* w <n> -- sets warning time */ 3.515 - sscanf(ptr + j, "w %u", &(evl[i].warn)); 3.516 - break; 3.517 - case F_FORDAYS: /* for <days> -- sets the duration of the event */ 3.518 - sscanf(ptr + j, "for %u", &d); 3.519 - evl[i].enddate=evl[i].date; 3.520 - for (l = 1; l < d; l++) { 3.521 - evl[i].enddate.day++; 3.522 - if (evl[i].enddate.day > mlen(evl[i].enddate.month, evl[i].enddate.year)) { 3.523 - evl[i].enddate.month++; 3.524 - evl[i].enddate.day = 1; 3.525 - } 3.526 - if (evl[i].enddate.month > 12) { 3.527 - evl[i].enddate.year++; 3.528 - evl[i].enddate.month = 1; 3.529 - } 3.530 - } 3.531 - break; 3.532 - case F_TODATE: /* to <date> -- sets the end date of the event */ 3.533 - l = sscanf(ptr + j, "to %u-%u-%u", &(evl[i].enddate.year), &(evl[i].enddate.month), &(evl[i].enddate.day)); 3.534 - if (l == 2) { 3.535 - evl[i].enddate.year = 0; 3.536 - } 3.537 - break; 3.538 - case 0: 3.539 - break; 3.540 - default: 3.541 - flags |= FTABLE[k].flag; 3.542 - break; 3.543 - } 3.544 - } 3.545 - 3.546 - 3.547 - /* construct event text */ 3.548 - 3.549 - switch(flags & F_MTYPE) { 3.550 - case F_TBIRTHDAY: 3.551 - default: /* assume it's a birthday */ 3.552 - if (evl[i].date.year != 0) { 3.553 - int tmp_age = ydelta(evl[i].date, today); 3.554 - if (tmp_age != 1) { 3.555 - sprintf(buf2, "%s is %d years old", buf, tmp_age); 3.556 - } else { 3.557 - sprintf(buf2, "%s is %d year old", buf, tmp_age); 3.558 - } 3.559 - } else { 3.560 - sprintf(buf2, "%s has a birthday", buf); 3.561 - } 3.562 - break; 3.563 - case F_TANNIVERSARY: 3.564 - if (evl[i].date.year != 0) { 3.565 - sprintf(buf2, "%s %d years ago", buf, ydelta(evl[i].date, today)); 3.566 - } else { 3.567 - strcpy(buf2, buf); 3.568 - } 3.569 - break; 3.570 - case F_TEVENT: 3.571 - /* if a year was specified, and this warning isn't for it, ignore! */ 3.572 - if ((evl[i].date.year != 0 && ydelta(evl[i].date, today) != 0) && (evl[i].enddate.year == 0 || ydelta(evl[i].enddate, today) != 0)) { 3.573 - i--; 3.574 - continue; 3.575 - } 3.576 - strcpy(buf2, buf); 3.577 - break; 3.578 - } 3.579 - evl[i].text = strdup(buf2); 3.580 - } 3.581 - 3.582 - evl = (struct event *) xrealloc(evl, sizeof(struct event) * (i + 1)); 3.583 - evl[i].date.day = 0; 3.584 - evl[i].date.month = 0; 3.585 - evl[i].date.year = 0; 3.586 - evl[i].text = (char *) NULL; 3.587 - 3.588 - fclose(stdin); 3.589 - 3.590 - /* NB uses i from above */ 3.591 - qsort(evl, i, sizeof(struct event), evcmp); 3.592 - return evl; 3.593 -} 3.594 - 3.595 - 3.596 - 3.597 - 3.598 - 3.599 - 3.600 - 3.601 - 3.602 -int skptok(int j, char *ptr) { 3.603 - for (; ptr[j] != 0 && ptr[j] != ' ' && ptr[j] != '\t' ; j++); 3.604 - for (; ptr[j] != 0 && (ptr[j] == ' ' || ptr[j] == '\t'); j++); 3.605 - 3.606 - return j; 3.607 -} 3.608 - 3.609 -
4.1 --- a/birthday.c Mon Dec 17 16:31:40 2007 +0100 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,51 +0,0 @@ 4.4 -/* 4.5 - birthday 4.6 - 4.7 - Birthday/Anniversary display on login 4.8 - 4.9 - (c) 1996 AS Mortimer 4.10 - 4.11 - This program is free software; you can redistribute it and/or 4.12 - modify it under the terms of the GNU General Public License as 4.13 - published by the Free Software Foundation; either version 2 of the 4.14 - License, or (at your option) any later version. You may also 4.15 - distribute it under the Artistic License, as comes with Perl. 4.16 - 4.17 - This program is distributed in the hope that it will be useful, 4.18 - but WITHOUT ANY WARRANTY; without even the implied warranty of 4.19 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 4.20 - 4.21 - You should have received a copy of the GNU General Public License 4.22 - along with this program; if not, write to the Free Software 4.23 - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 4.24 - 4.25 - You should also have recieved a copy of the Artistic license with 4.26 - this program. 4.27 - 4.28 - $Id: birthday.c,v 1.5 1999/04/25 14:01:29 andy Exp $ 4.29 -*/ 4.30 - 4.31 -#include <string.h> 4.32 -#include <stdio.h> 4.33 -#include <stdlib.h> 4.34 - 4.35 -#include "birthday.h" 4.36 - 4.37 - 4.38 -int main(int argc, char* argv[]) { 4.39 - 4.40 - while (--argc > 0 && (*++argv)[0] == '-') { 4.41 - if (strcmp(argv[0], "-W") == 0) { 4.42 - /* TODO: catch if no value given */ 4.43 - iDWarn = atoi((++argv)[0]); 4.44 - argc--; 4.45 - } else { 4.46 - fprintf(stderr, "unknown option %s\n", argv[0]); 4.47 - exit(1); 4.48 - } 4.49 - } 4.50 - 4.51 - liststrings(readlist(), puts); 4.52 - 4.53 - return 0; 4.54 -}
5.1 --- a/birthday.h Mon Dec 17 16:31:40 2007 +0100 5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 5.3 @@ -1,92 +0,0 @@ 5.4 -/* 5.5 - birthday 5.6 - 5.7 - Birthday/Anniversary display on login 5.8 - 5.9 - (c) 1996 AS Mortimer 5.10 - 5.11 - This program is free software; you can redistribute it and/or 5.12 - modify it under the terms of the GNU General Public License as 5.13 - published by the Free Software Foundation; either version 2 of the 5.14 - License, or (at your option) any later version. You may also 5.15 - distribute it under the Artistic License, as comes with Perl. 5.16 - 5.17 - This program is distributed in the hope that it will be useful, 5.18 - but WITHOUT ANY WARRANTY; without even the implied warranty of 5.19 - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 5.20 - 5.21 - You should have received a copy of the GNU General Public License 5.22 - along with this program; if not, write to the Free Software 5.23 - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 5.24 - 5.25 - You should also have recieved a copy of the Artistic license with 5.26 - this program. 5.27 - 5.28 - $Id: birthday.h,v 1.6 1999/04/25 14:01:29 andy Exp $ 5.29 -*/ 5.30 - 5.31 -#include <stdio.h> 5.32 - 5.33 -/* ========== Configuration section */ 5.34 - 5.35 -/* standard time to warn in advance, when no explicit w flag is given. */ 5.36 -#define DEF_WARN 14 5.37 - 5.38 -/* ========== Global constants and data types */ 5.39 - 5.40 - 5.41 -/* month lengths etc */ 5.42 - 5.43 -#define isleapyear(y) ((y)%4==0 && ((y)%100 != 0 || (y)%400 == 0)) 5.44 -extern const unsigned MLENDAT[]; 5.45 -#define mlen(m,y) (MLENDAT[(m)-1] != -1 ? MLENDAT[(m)-1] : (isleapyear((y)) ? 29 : 28)) 5.46 -#define before(a,b) ((a).month < (b).month || ((a).month == (b).month && (a).day < (b).day)) 5.47 -#define ydelta(a,b) ((int) (b).year - (a).year + before((a),(b))) 5.48 - 5.49 -/* -------- modifier flags */ 5.50 - 5.51 -#define F_MTYPE 0x07 5.52 -#define F_TBIRTHDAY 1 5.53 -#define F_TANNIVERSARY 2 5.54 -#define F_TEVENT 3 5.55 - 5.56 -/* flags processed immediately on encountering */ 5.57 -#define F_MIMMEDIATE 0x24 5.58 -#define F_WTIME_P 0x08 5.59 -#define F_FORDAYS 0x16 5.60 -#define F_TODATE 0x24 5.61 - 5.62 -struct _ftable {char *txt; unsigned flag;}; 5.63 - 5.64 -extern const struct _ftable FTABLE[]; 5.65 - 5.66 -struct date { 5.67 - unsigned day; 5.68 - unsigned month; 5.69 - unsigned year; 5.70 -}; 5.71 - 5.72 -struct event { 5.73 - char *text; 5.74 - struct date date; 5.75 - struct date enddate; 5.76 - int warn; 5.77 -}; 5.78 - 5.79 -typedef int (*prnfunc)(const char *); 5.80 - 5.81 -/* ========== */ 5.82 - 5.83 -struct event* readlist(void); 5.84 -void gettoday(void); 5.85 -unsigned delta(struct date *); 5.86 -unsigned ddiff(struct date *D1, struct date *D2); 5.87 -void liststrings(struct event* evl, prnfunc outf); 5.88 -char *tdelta(struct date *d); 5.89 -char *ttime(int yr, int mn, int wk, int dy); 5.90 - 5.91 -/* ========== Global Variables */ 5.92 - 5.93 -extern struct date today; 5.94 -extern int iDWarn; 5.95 -