2
* memos.c: Translate Palm Memos into e-mail format
4
* Copyright (c) 1996, Kenneth Albanowski
6
* This program is free software; you can redistribute it and/or modify it
7
* under the terms of the GNU General Public License as published by the
8
* Free Software Foundation; either version 2 of the License, or (at your
9
* option) any later version.
11
* This program is distributed in the hope that it will be useful, but
12
* WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14
* Public License for more details.
16
* You should have received a copy of the GNU General Public License along
17
* with this program; if not, write to the Free Software Foundation, Inc.,
18
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30
#include "pi-source.h"
31
#include "pi-socket.h"
35
#include "pi-header.h"
37
/* constants to determine how to produce memos */
38
#define MEMO_MBOX_STDOUT 0
39
#define MEMO_DIRECTORY 1
40
#define MAXDIRNAMELEN 1024
45
/* Declare prototypes */
46
static void display_help(char *progname);
47
void print_splash(char *progname);
48
int pilot_connect(char *port);
50
struct option options[] = {
51
{"help", no_argument, NULL, 'h'},
52
{"version", no_argument, NULL, 'v'},
53
{"port", required_argument, NULL, 'p'},
54
{"verbose", no_argument, NULL, 'V'},
55
{"delete", required_argument, NULL, 'd'},
56
{"file", required_argument, NULL, 'f'},
57
{"save", required_argument, NULL, 's'},
58
{"category", required_argument, NULL, 'c'},
59
{"regex", required_argument, NULL, 'r'},
63
static const char *optstring = "p:hvVd:f:s:c:r:";
65
void write_memo_mbox(struct Memo m, struct MemoAppInfo mai, int category);
66
void write_memo_in_directory(char *dirname, struct Memo m,
67
struct MemoAppInfo mai, int category,
70
/***********************************************************************
72
* Function: write_memo_mbox
74
* Summary: Write a memo entry to MailDB database
80
***********************************************************************/
81
void write_memo_mbox(struct Memo m, struct MemoAppInfo mai, int category)
89
/* FIXME: might be good to get the time stamp of the memo file for
90
* the "Received" line */
92
time_str = ctime(&now);
94
printf("From: MemoDB@Palm.Handheld via pilot-link/memos\n"
98
"Subject: ", time_str, time_str );
100
/* print category name in brackets in subject field */
101
printf("[%s] ", mai.category.name[category]);
103
/* print (at least part of) first line as part of subject: */
104
for (j = 0; j < 40; j++) {
105
if ((!m.text[j]) || (m.text[j] == '\n'))
107
printf("%c", m.text[j]);
117
/***********************************************************************
119
* Function: write_memo_in_directory
121
* Summary: Writes each memo into /$DIR/$CATEGORY/$FILENAME form
122
* after the user specifies the -d /dir/name argument
128
***********************************************************************/
130
write_memo_in_directory(char *dirname, struct Memo m,
131
struct MemoAppInfo mai, int category, int verbose)
134
char pathbuffer[MAXDIRNAMELEN + (128 * 3)] = "",
138
/* Should check if dirname exists and is a directory */
139
mkdir(dirname, 0700);
141
/* Create a directory for the category */
142
strncat(pathbuffer, dirname, MAXDIRNAMELEN);
143
strncat(pathbuffer, "/", 1);
145
/* Should make sure category doesn't have slashes in it */
146
strncat(pathbuffer, mai.category.name[category], 60);
148
/* Should check if there were problems creating directory */
149
/* open the actual file to write */
150
strncat(pathbuffer, "/", 1);
151
for (j = 0; j < 40; j++) {
152
if ((!m.text[j]) || (m.text[j] == '\n'))
154
if (m.text[j] == '/') {
155
strncat(pathbuffer, "=2F", 3);
158
if (m.text[j] == '=') {
159
strncat(pathbuffer, "=3D", 3);
163
if (m.text[j] == ':') {
164
strncat(pathbuffer, "=3A", 3);
168
/* escape if it's an ISO8859 control chcter (note: some
169
are printable on the Palm) */
170
if ((m.text[j] | 0x7f) < ' ') {
172
sprintf(tmp, "=%2X", (unsigned char) m.text[j]);
177
strcat(pathbuffer, tmp);
181
printf("Writing %s\n", pathbuffer);
184
if (!(fd = fopen(pathbuffer, "w"))) {
185
printf("%s: can't open file \"%s\" for writing\n",
186
progname, pathbuffer);
193
/***********************************************************************
195
* Function: display_help
197
* Summary: Outputs the program arguments and params
203
***********************************************************************/
204
static void display_help(char *progname)
206
printf(" Manipulate MemoDB.pdb entries from a file or your Palm device\n\n");
207
printf(" Usage: memos -p <port> [-V] [options]\n\n");
208
printf(" Options:\n");
209
printf(" -p, --port <port> Use device file <port> to communicate with Palm\n");
210
printf(" -h, --help Display help information for %s\n", progname);
211
printf(" -v, --version Display %s version information\n", progname);
212
printf(" -V, --verbose Verbose, with -d, print each filename when\n");
213
printf(" written\n");
214
printf(" -d, --delete Delete memo named by number <num>\n");
215
printf(" -f, --file [file] .. Use <file> as input file (instead of MemoDB.pdb)\n");
216
printf(" -s, --save <dir> Save memos in <dir> instead of writing to\n");
218
printf(" -c, --category <cat> Only upload memos in this category\n");
219
printf(" -r, --regex [regexp] Select memos saved by regular expression on\n");
220
printf(" title\n\n");
222
printf(" By default, the contents of your Palm's memo database will be written to\n");
223
printf(" standard output as a standard Unix mailbox (mbox-format) file, with each\n");
224
printf(" memo as a separate message. The subject of each message will be the\n");
225
printf(" category.\n\n");
227
printf(" If '-s' is specified, than instead of being written to standard output,\n");
228
printf(" will be saved in subdirectories of <dir>. Each subdirectory will be the\n");
229
printf(" name of a category on the Palm, and will contain the memos in that\n");
230
printf(" category. Each memo's filename will be the first line (up to the first 40\n");
231
printf(" chcters) of the memo. Control chcters, slashes, and equal signs that\n");
232
printf(" would otherwise appear in filenames are converted after the fashion of\n");
233
printf(" MIME's quoted-printable encoding. Note that if you have two memos in the\n");
234
printf(" same category whose first lines are identical, one of them will be\n");
235
printf(" overwritten.\n\n");
237
printf(" If '-f' is specified, the specified file will be treated as a memo\n");
238
printf(" database from which to read memos, rather than HotSyncing from the Palm.\n\n");
243
int main(int argc, char *argv[])
255
mode = MEMO_MBOX_STDOUT,
260
unsigned char buffer[0xffff];
262
char appblock[0xffff],
263
dirname[MAXDIRNAMELEN] = "",
267
category_name[MAXDIRNAMELEN + 1] = "",
268
filename[MAXDIRNAMELEN + 1], *ptr;
270
struct MemoAppInfo mai;
271
struct pi_file *pif = NULL;
274
regex_t title_pattern;
277
while ((c = getopt_long(argc, argv, optstring, options, NULL)) != -1) {
281
display_help(progname);
284
print_splash(progname);
293
strncpy(filename, optarg, MAXDIRNAMELEN);
294
filename[MAXDIRNAMELEN] = '\0';
297
strncpy(dirname, optarg, sizeof(dirname));
298
mode = MEMO_DIRECTORY;
301
strncpy(category_name, optarg, MAXDIRNAMELEN);
302
category_name[strlen( category_name )] = '\0';
305
ret = regcomp(&title_pattern, optarg, REG_NOSUB);
306
buf = (char *) malloc(bufsize);
308
regerror(ret, &title_pattern, buf,
316
display_help(progname);
321
/* FIXME - Need to add tests here for port/filename, clean this. -DD */
322
if (filename[0] == '\0') {
324
sd = pilot_connect(port);
329
if (dlp_OpenConduit(sd) < 0)
332
/* Open the Memo Pad's database, store access handle in db */
333
if (dlp_OpenDB(sd, 0, 0x80 | 0x40, "MemoDB", &db) < 0) {
334
printf("Unable to open MemoDB.\n");
335
dlp_AddSyncLogEntry(sd,
336
"Unable to open MemoDB.\n");
340
dlp_ReadAppBlock(sd, db, 0, (unsigned char *) appblock,
345
pif = pi_file_open(filename);
347
perror("pi_file_open");
351
ret = pi_file_get_app_info(pif, (void *) &ptr, &len);
353
perror("pi_file_get_app_info");
357
memcpy(appblock, ptr, len);
360
unpack_MemoAppInfo(&mai, (unsigned char *) appblock, 0xffff);
362
if (category_name[0] != '\0') {
363
for (index = 0, match_category = -1; index < 16; index += 1) {
364
if ((strlen(mai.category.name[index]) > 0)
365
&& (strcmp(mai.category.name[index], category_name)
367
match_category = index;
369
if (match_category < 0) {
370
printf("Can't find specified Memo category \"%s\".\n",
372
dlp_AddSyncLogEntry(sd,
373
"Can't find specified memo category.\n");
378
for (index = 0;; index++) {
380
if (filename[0] == '\0') {
381
if (match_category >= 0) {
382
len = dlp_ReadNextRecInCategory(sd, db,
387
category = match_category;
389
len = dlp_ReadRecordByIndex(sd, db, index,
397
if (pi_file_read_record
398
(pif, index, (void *) &ptr, &len, &attr, &category,
401
memcpy(buffer, ptr, len);
404
/* Skip deleted records */
405
if ((attr & dlpRecAttrDeleted)
406
|| (attr & dlpRecAttrArchived))
409
/* Skip memos whose category doesn't match */
410
if( match_category >= 0 ) {
411
if( match_category != category )
415
unpack_Memo(&m, buffer, len);
417
/* Skip memos whose title does not match with the query */
418
if (title_matching) {
419
for (len = 0; m.text[len] && m.text[len] != '\n';
421
if (bufsize < len + 1)
422
buf = (char *) realloc(buf, len + 1);
423
strncpy(buf, m.text, len);
425
if (regexec(&title_pattern, buf, 0, NULL, 0) ==
431
case MEMO_MBOX_STDOUT:
432
write_memo_mbox(m, mai, category);
435
write_memo_in_directory(dirname, m, mai,
441
if (delete && (filename[0] == '\0')) {
443
printf("Deleting record %d.\n", (int) id);
444
dlp_DeleteRecord(sd, db, 0, id);
447
if (title_matching) {
448
regfree(&title_pattern);
452
if (filename[0] == '\0') {
453
/* Close the database */
455
dlp_AddSyncLogEntry(sd, "Successfully read memos from Palm.\n"
456
"Thank you for using pilot-link.\n");
467
fprintf(stderr, "Please use -h for more detailed options.\n");