~ubuntu-branches/ubuntu/edgy/nail/edgy

« back to all changes in this revision

Viewing changes to cmd2.c

  • Committer: Bazaar Package Importer
  • Author(s): Hilko Bengen
  • Date: 2004-04-01 12:58:06 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040401125806-ob0836aos7lf3kep
Tags: 10.7-1
* New upstream version (includes portions of IEEE Std 1003.1 docs)
* Updated Standards-Version

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
 
2
 * Nail - a mail user agent derived from Berkeley Mail.
 
3
 *
 
4
 * Copyright (c) 2000-2002 Gunnar Ritter, Freiburg i. Br., Germany.
 
5
 */
 
6
/*
2
7
 * Copyright (c) 1980, 1993
3
8
 *      The Regents of the University of California.  All rights reserved.
4
9
 *
33
38
 
34
39
#ifndef lint
35
40
#ifdef  DOSCCS
36
 
static char sccsid[] = "@(#)cmd2.c      1.7 (gritter) 9/19/01";
 
41
static char sccsid[] = "@(#)cmd2.c      2.8 (gritter) 11/20/02";
37
42
#endif
38
43
#endif /* not lint */
39
44
 
42
47
#include <sys/wait.h>
43
48
#endif
44
49
#include "extern.h"
 
50
#ifdef  HAVE_STRINGS_H
 
51
#include <strings.h>
 
52
#endif
45
53
 
46
54
/*
47
55
 * Mail -- a mail program
48
56
 *
49
57
 * More user commands.
50
58
 */
51
 
static int igcomp __P((const void *, const void *));
 
59
static int      igcomp __P((const void *, const void *));
 
60
static int      save1 __P((char [], int, char *, struct ignoretab *, int, int));
 
61
static char     *snarf __P((char [], int *, int));
 
62
static int      delm __P((int []));
 
63
#ifdef  DEBUG_COMMANDS
 
64
static void     clob1 __P((int));
 
65
#endif
 
66
static int      ignore1 __P((char *[], struct ignoretab *, char *));
 
67
static int      igshow __P((struct ignoretab *, char *));
 
68
static void     unignore_one __P((const char *, struct ignoretab *));
 
69
static int      unignore1 __P((char *[], struct ignoretab *, char *));
52
70
 
53
71
/*
54
72
 * If any arguments were given, go to the next applicable argument
88
106
                do {
89
107
                        mp = &message[*ip2 - 1];
90
108
                        if ((mp->m_flag & MDELETED) == 0) {
91
 
                                dot = mp;
 
109
                                setdot(mp);
92
110
                                goto hitit;
93
111
                        }
94
112
                        if (*ip2 != 0)
96
114
                        if (*ip2 == 0)
97
115
                                ip2 = msgvec;
98
116
                } while (ip2 != ip);
99
 
                printf("No messages applicable\n");
 
117
                printf(catgets(catd, CATSET, 21, "No messages applicable\n"));
100
118
                return(1);
101
119
        }
102
120
 
105
123
         * Note that this must exist for us to get here at all.
106
124
         */
107
125
 
108
 
        if (!sawcom)
 
126
        if (!sawcom) {
 
127
                if (msgcount == 0)
 
128
                        goto ateof;
109
129
                goto hitit;
 
130
        }
110
131
 
111
132
        /*
112
133
         * Just find the next good message after dot, no
113
134
         * wraparound.
114
135
         */
115
136
 
116
 
        for (mp = dot+1; mp < &message[msgcount]; mp++)
 
137
        for (mp = dot + did_print_dot; mp < &message[msgcount]; mp++)
117
138
                if ((mp->m_flag & (MDELETED|MSAVED)) == 0)
118
139
                        break;
119
140
        if (mp >= &message[msgcount]) {
120
 
                printf("At EOF\n");
 
141
ateof:
 
142
                printf(catgets(catd, CATSET, 22, "At EOF\n"));
121
143
                return(0);
122
144
        }
123
 
        dot = mp;
 
145
        setdot(mp);
124
146
hitit:
125
147
        /*
126
148
         * Print dot.
141
163
{
142
164
        char *str = v;
143
165
 
144
 
        return save1(str, 1, "save", saveignore, CONV_NONE);
 
166
        return save1(str, 1, "save", saveignore, CONV_NONE, 0);
 
167
}
 
168
 
 
169
int
 
170
Save(v)
 
171
        void *v;
 
172
{
 
173
        char *str = v;
 
174
 
 
175
        return save1(str, 1, "save", saveignore, CONV_NONE, 1);
145
176
}
146
177
 
147
178
/*
153
184
{
154
185
        char *str = v;
155
186
 
156
 
        return save1(str, 0, "copy", saveignore, CONV_NONE);
 
187
        return save1(str, 0, "copy", saveignore, CONV_NONE, 0);
 
188
}
 
189
 
 
190
int
 
191
Copycmd(v)
 
192
        void *v;
 
193
{
 
194
        char *str = v;
 
195
 
 
196
        return save1(str, 0, "copy", saveignore, CONV_NONE, 1);
157
197
}
158
198
 
159
199
/*
160
200
 * Save/copy the indicated messages at the end of the passed file name.
161
201
 * If mark is true, mark the message "saved."
162
202
 */
163
 
int
164
 
save1(str, mark, cmd, ignore, convert)
 
203
static int
 
204
save1(str, mark, cmd, ignore, convert, sender_record)
165
205
        char str[];
166
206
        int mark;
167
207
        char *cmd;
169
209
{
170
210
        int *ip;
171
211
        struct message *mp;
172
 
        char *file, *disp;
 
212
        char *file = NULL, *disp;
173
213
        int f, *msgvec;
174
214
        FILE *obuf;
175
215
        int newfile;
 
216
        char *cp, *cq;
 
217
        off_t mstats[2], tstats[2];
176
218
 
177
219
        /*LINTED*/
178
220
        msgvec = (int *)salloc((msgcount + 2) * sizeof *msgvec);
179
 
        if ((file = snarf(str, &f)) == NULL)
180
 
                return(1);
 
221
        if (sender_record) {
 
222
                for (cp = str; *cp && blankchar(*cp & 0377); cp++);
 
223
                f = (*cp != '\0');
 
224
        } else {
 
225
                if ((file = snarf(str, &f, convert != CONV_TOFILE)) == NULL)
 
226
                        return(1);
 
227
        }
181
228
        if (!f) {
182
229
                *msgvec = first(0, MMNORM);
183
230
                if (*msgvec == 0) {
184
 
                        printf("No messages to %s.\n", cmd);
 
231
                        printf(catgets(catd, CATSET, 23,
 
232
                                        "No messages to %s.\n"), cmd);
185
233
                        return(1);
186
234
                }
187
235
                msgvec[1] = 0;
188
236
        }
189
237
        if (f && getmsglist(str, msgvec, 0) < 0)
190
238
                return(1);
 
239
        if (sender_record) {
 
240
                if ((cp = nameof(&message[*msgvec - 1], 0)) == NULL) {
 
241
                        printf(catgets(catd, CATSET, 24,
 
242
                                "Cannot determine message sender to %s.\n"),
 
243
                                cmd);
 
244
                        return 1;
 
245
                }
 
246
                for (cq = cp; *cq && *cq != '@'; cq++);
 
247
                *cq = '\0';
 
248
                if (value("outfolder")) {
 
249
                        file = salloc(strlen(cp) + 2);
 
250
                        file[0] = '+';
 
251
                        strcpy(&file[1], cp);
 
252
                } else
 
253
                        file = cp;
 
254
        }
191
255
        if ((file = expand(file)) == NULL)
192
256
                return(1);
193
257
        if (access(file, 0) >= 0) {
194
258
                newfile = 0;
195
 
                disp = "[Appended]";
 
259
                disp = catgets(catd, CATSET, 25, "[Appended]");
196
260
        } else {
197
261
                newfile = 1;
198
 
                disp = "[New file]";
199
 
        }
200
 
        if ((obuf = Fopen(file, "a")) == (FILE *)NULL) {
201
 
                perror(NULL);
202
 
                return(1);
203
 
        }
204
 
        if (newfile == 0) {
205
 
                /* always insert a newline since some other mail readers
206
 
                 * (notably Netscape 4.7) use this folder convention
207
 
                 */
208
 
                fputc('\n', obuf);
209
 
        }
 
262
                disp = catgets(catd, CATSET, 26, "[New file]");
 
263
        }
 
264
        if ((obuf = Fopen(file, "a+")) == NULL) {
 
265
                if ((obuf = Fopen(file, "wx")) == NULL) {
 
266
                        perror(file);
 
267
                        return(1);
 
268
                }
 
269
        } else {
 
270
                if (!newfile && fseek(obuf, -2L, SEEK_END) == 0) {
 
271
                        char buf[2];
 
272
                        int prependnl = 0;
 
273
 
 
274
                        switch (fread(buf, sizeof *buf, 2, obuf)) {
 
275
                        case 2:
 
276
                                if (buf[1] != '\n') {
 
277
                                        prependnl = 1;
 
278
                                        break;
 
279
                                }
 
280
                                /*FALLTHRU*/
 
281
                        case 1:
 
282
                                if (buf[0] != '\n')
 
283
                                        prependnl = 1;
 
284
                                break;
 
285
                        default:
 
286
                                if (ferror(obuf)) {
 
287
                                        perror(file);
 
288
                                        return(1);
 
289
                                }
 
290
                                prependnl = 0;
 
291
                        }
 
292
                        fflush(obuf);
 
293
                        if (prependnl) {
 
294
                                sputc('\n', obuf);
 
295
                                fflush(obuf);
 
296
                        }
 
297
                }
 
298
        }
 
299
        tstats[0] = tstats[1] = 0;
210
300
        for (ip = msgvec; *ip && ip-msgvec < msgcount; ip++) {
211
301
                mp = &message[*ip - 1];
212
 
                touch(mp);
213
 
                if (send_message(mp, obuf, ignore, NULL, convert) < 0) {
 
302
                if (send_message(mp, obuf, ignore, NULL, convert, mstats) < 0) {
214
303
                        perror(file);
215
304
                        Fclose(obuf);
216
305
                        return(1);
217
306
                }
 
307
                touch(mp);
218
308
                if (mark)
219
309
                        mp->m_flag |= MSAVED;
 
310
                tstats[0] += mstats[0];
 
311
                tstats[1] += mstats[1];
220
312
        }
221
313
        fflush(obuf);
222
314
        if (ferror(obuf))
223
315
                perror(file);
224
316
        Fclose(obuf);
225
 
        printf("%s %s\n", file, disp);
 
317
        printf("\"%s\" %s ", file, disp);
 
318
        if (tstats[0] >= 0)
 
319
                printf("%lu", (long)tstats[0]);
 
320
        else
 
321
                printf(catgets(catd, CATSET, 27, "binary"));
 
322
        printf("/%lu\n", (long)tstats[1]);
226
323
        return(0);
227
324
}
228
325
 
229
326
/*
230
327
 * Write the indicated messages at the end of the passed
231
328
 * file name, minus header and trailing blank line.
232
 
 * NEW: This is the MIME save function.
 
329
 * This is the MIME save function.
233
330
 */
234
331
int
235
332
swrite(v)
237
334
{
238
335
        char *str = v;
239
336
 
240
 
        return save1(str, 0, "write", allignore, CONV_TOFILE);
 
337
        return save1(str, 0, "write", allignore, CONV_TOFILE, 0);
241
338
}
242
339
 
243
340
/*
244
341
 * Snarf the file from the end of the command line and
245
342
 * return a pointer to it.  If there is no file attached,
246
 
 * just return NULL.  Put a null in front of the file
 
343
 * return the mbox file.  Put a null in front of the file
247
344
 * name so that the message list processing won't see it,
248
345
 * unless the file name is the only thing on the line, in
249
346
 * which case, return 0 in the reference flag variable.
250
347
 */
251
348
 
252
 
char *
253
 
snarf(linebuf, flag)
 
349
static char *
 
350
snarf(linebuf, flag, usembox)
254
351
        char linebuf[];
255
352
        int *flag;
256
353
{
257
354
        char *cp;
258
355
 
259
356
        *flag = 1;
260
 
        cp = strlen(linebuf) + linebuf - 1;
261
 
 
262
 
        /*
263
 
         * Strip away trailing blanks.
264
 
         */
265
 
 
266
 
        while (cp > linebuf && isspace(*cp))
267
 
                cp--;
268
 
        *++cp = 0;
269
 
 
270
 
        /*
271
 
         * Now search for the beginning of the file name.
272
 
         */
273
 
 
274
 
        while (cp > linebuf && !isspace(*cp))
275
 
                cp--;
276
 
        if (*cp == '\0') {
277
 
                printf("No file specified.\n");
278
 
                return(NULL);
 
357
        if ((cp = laststring(linebuf, flag, 0)) == NULL) {
 
358
                if (usembox) {
 
359
                        *flag = 0;
 
360
                        return expand("&");
 
361
                } else {
 
362
                        printf(catgets(catd, CATSET, 28,
 
363
                                                "No file specified.\n"));
 
364
                        return NULL;
 
365
                }
279
366
        }
280
 
        if (isspace(*cp))
281
 
                *cp++ = 0;
282
 
        else
283
 
                *flag = 0;
284
367
        return(cp);
285
368
}
286
369
 
315
398
                        list[1] = 0;
316
399
                        return(type(list));
317
400
                }
318
 
                printf("At EOF\n");
 
401
                printf(catgets(catd, CATSET, 29, "At EOF\n"));
319
402
        } else
320
 
                printf("No more messages\n");
 
403
                printf(catgets(catd, CATSET, 30, "No more messages\n"));
321
404
        return(0);
322
405
}
323
406
 
326
409
 * Set dot to some nice place afterwards.
327
410
 * Internal interface.
328
411
 */
329
 
int
 
412
static int
330
413
delm(msgvec)
331
414
        int *msgvec;
332
415
{
343
426
                last = *ip;
344
427
        }
345
428
        if (last != 0) {
346
 
                dot = &message[last-1];
 
429
                setdot(&message[last-1]);
347
430
                last = first(0, MDELETED);
348
431
                if (last != 0) {
349
 
                        dot = &message[last-1];
 
432
                        setdot(&message[last-1]);
350
433
                        return(0);
351
434
                }
352
435
                else {
353
 
                        dot = &message[0];
 
436
                        setdot(&message[0]);
354
437
                        return(-1);
355
438
                }
356
439
        }
376
459
        for (ip = msgvec; *ip && ip-msgvec < msgcount; ip++) {
377
460
                mp = &message[*ip - 1];
378
461
                touch(mp);
379
 
                dot = mp;
 
462
                setdot(mp);
380
463
                mp->m_flag &= ~MDELETED;
381
464
        }
382
465
        return 0;
383
466
}
384
467
 
 
468
#ifdef  DEBUG_COMMANDS
385
469
/*
386
470
 * Interactively dump core on "core"
387
471
 */
403
487
                abort();
404
488
                _exit(1);
405
489
        }
406
 
        printf("Okie dokie");
 
490
        printf(catgets(catd, CATSET, 31, "Okie dokie"));
407
491
        fflush(stdout);
408
492
        wait_child(pid);
409
493
#ifdef  WCOREDUMP
410
494
        if (WCOREDUMP(wait_status))
411
 
                printf(" -- Core dumped.\n");
 
495
                printf(catgets(catd, CATSET, 32, " -- Core dumped.\n"));
412
496
        else
413
 
                printf(" -- Can't dump core.\n");
 
497
                printf(catgets(catd, CATSET, 33, " -- Can't dump core.\n"));
414
498
#endif
415
499
        return 0;
416
500
}
436
520
/*
437
521
 * Clobber the stack.
438
522
 */
439
 
void
 
523
static void
440
524
clob1(n)
441
525
        int n;
442
526
{
449
533
                ;
450
534
        clob1(n - 1);
451
535
}
 
536
#endif  /* DEBUG_COMMANDS */
452
537
 
453
538
/*
454
539
 * Add the given header fields to the retained list.
494
579
        return ignore1(list, saveignore, "ignored");
495
580
}
496
581
 
497
 
int
 
582
static int
498
583
ignore1(list, tab, which)
499
584
        char *list[];
500
585
        struct ignoretab *tab;
501
586
        char *which;
502
587
{
503
 
        char field[BUFSIZ];
504
588
        int h;
505
589
        struct ignore *igp;
506
590
        char **ap;
508
592
        if (*list == NULL)
509
593
                return igshow(tab, which);
510
594
        for (ap = list; *ap != 0; ap++) {
511
 
                istrcpy(field, *ap, BUFSIZ);
512
 
                field[BUFSIZ-1]='\0';
513
 
                if (member(field, tab))
 
595
                char *field;
 
596
                size_t sz;
 
597
 
 
598
                sz = strlen(*ap);
 
599
                field = ac_alloc(sz + 1);
 
600
                i_strcpy(field, *ap, sz + 1);
 
601
                field[sz]='\0';
 
602
                if (member(field, tab)) {
 
603
                        ac_free(field);
514
604
                        continue;
 
605
                }
515
606
                h = hash(field);
516
 
                igp = (struct ignore *) calloc(1, sizeof (struct ignore));
517
 
                igp->i_field = calloc((unsigned) strlen(field) + 1,
518
 
                        sizeof (char));
 
607
                igp = (struct ignore *)scalloc(1, sizeof (struct ignore));
 
608
                igp->i_field = smalloc(strlen(field) + 1);
519
609
                strcpy(igp->i_field, field);
520
610
                igp->i_link = tab->i_head[h];
521
611
                tab->i_head[h] = igp;
522
612
                tab->i_count++;
 
613
                ac_free(field);
523
614
        }
524
615
        return 0;
525
616
}
527
618
/*
528
619
 * Print out all currently retained fields.
529
620
 */
530
 
int
 
621
static int
531
622
igshow(tab, which)
532
623
        struct ignoretab *tab;
533
624
        char *which;
537
628
        char **ap, **ring;
538
629
 
539
630
        if (tab->i_count == 0) {
540
 
                printf("No fields currently being %s.\n", which);
 
631
                printf(catgets(catd, CATSET, 34,
 
632
                                "No fields currently being %s.\n"), which);
541
633
                return 0;
542
634
        }
543
635
        /*LINTED*/
562
654
{
563
655
        return (strcmp(*(char **)l, *(char **)r));
564
656
}
 
657
 
 
658
int
 
659
unignore(v)
 
660
        void *v;
 
661
{
 
662
        return unignore1((char **)v, ignore, "ignored");
 
663
}
 
664
 
 
665
int
 
666
unretain(v)
 
667
        void *v;
 
668
{
 
669
        return unignore1((char **)v, ignore + 1, "retained");
 
670
}
 
671
 
 
672
int
 
673
unsaveignore(v)
 
674
        void *v;
 
675
{
 
676
        return unignore1((char **)v, saveignore, "ignored");
 
677
}
 
678
 
 
679
int
 
680
unsaveretain(v)
 
681
        void *v;
 
682
{
 
683
        return unignore1((char **)v, saveignore + 1, "retained");
 
684
}
 
685
 
 
686
static void
 
687
unignore_one(name, tab)
 
688
        const char *name;
 
689
        struct ignoretab *tab;
 
690
{
 
691
        struct ignore *ip, *iq = NULL;
 
692
        int h = hash(name);
 
693
 
 
694
        for (ip = tab->i_head[h]; ip; ip = ip->i_link) {
 
695
                if (asccasecmp(ip->i_field, name)) {
 
696
                        free(ip->i_field);
 
697
                        if (iq != NULL)
 
698
                                iq->i_link = ip->i_link;
 
699
                        else
 
700
                                tab->i_head[h] = NULL;
 
701
                        free(ip);
 
702
                        tab->i_count--;
 
703
                        break;
 
704
                }
 
705
        }
 
706
}
 
707
 
 
708
static int
 
709
unignore1(list, tab, which)
 
710
        char *list[];
 
711
        struct ignoretab *tab;
 
712
        char *which;
 
713
{
 
714
        if (tab->i_count == 0) {
 
715
                printf(catgets(catd, CATSET, 34,
 
716
                                "No fields currently being %s.\n"), which);
 
717
                return 0;
 
718
        }
 
719
        while (*list)
 
720
                unignore_one(*list++, tab);
 
721
        return 0;
 
722
}