0
|
1 /*
|
|
2 * CDDL HEADER START
|
|
3 *
|
|
4 * The contents of this file are subject to the terms of the
|
|
5 * Common Development and Distribution License (the "License").
|
|
6 * You may not use this file except in compliance with the License.
|
|
7 *
|
|
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
9 * or http://www.opensolaris.org/os/licensing.
|
|
10 * See the License for the specific language governing permissions
|
|
11 * and limitations under the License.
|
|
12 *
|
|
13 * When distributing Covered Code, include this CDDL HEADER in each
|
|
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
15 * If applicable, add the following below this CDDL HEADER, with the
|
|
16 * fields enclosed by brackets "[]" replaced with your own identifying
|
|
17 * information: Portions Copyright [yyyy] [name of copyright owner]
|
|
18 *
|
|
19 * CDDL HEADER END
|
|
20 */
|
|
21
|
|
22 /*
|
|
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
|
|
24 * Use is subject to license terms.
|
|
25 */
|
|
26
|
|
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
|
|
28 /* All Rights Reserved */
|
|
29
|
|
30 /*
|
|
31 * University Copyright- Copyright (c) 1982, 1986, 1988
|
|
32 * The Regents of the University of California
|
|
33 * All Rights Reserved
|
|
34 *
|
|
35 * University Acknowledgment- Portions of this document are derived from
|
|
36 * software developed by the University of California, Berkeley, and its
|
|
37 * contributors.
|
|
38 */
|
|
39
|
|
40 #pragma ident "@(#)cmd2.c 1.27 06/10/11 SMI"
|
|
41
|
|
42 #include "rcv.h"
|
|
43 #include <locale.h>
|
|
44
|
|
45 /*
|
|
46 * mailx -- a modified version of a University of California at Berkeley
|
|
47 * mail program
|
|
48 *
|
|
49 * More user commands.
|
|
50 */
|
|
51
|
|
52 static int igshow(void);
|
|
53 static int igcomp(const void *l, const void *r);
|
|
54 static int save1(char str[], int mark);
|
|
55 static int Save1(int *msgvec, int mark);
|
|
56 static void savemsglist(char *file, int *msgvec, int flag);
|
|
57 static int put1(char str[], int doign);
|
|
58 static int svputs(const char *line, FILE *obuf);
|
|
59 static int wrputs(const char *line, FILE *obuf);
|
|
60 static int retshow(void);
|
|
61
|
|
62 /* flags for savemsglist() */
|
|
63 #define S_MARK 1 /* mark the message as saved */
|
|
64 #define S_NOHEADER 2 /* don't write out the header */
|
|
65 #define S_SAVING 4 /* doing save/copy */
|
|
66 #define S_NOIGNORE 8 /* don't do ignore processing */
|
|
67
|
|
68 /*
|
|
69 * If any arguments were given, print the first message
|
|
70 * identified by the first argument. If no arguments are given,
|
|
71 * print the next applicable message after dot.
|
|
72 */
|
|
73
|
|
74 int
|
|
75 next(int *msgvec)
|
|
76 {
|
|
77 register struct message *mp;
|
|
78 int list[2];
|
|
79
|
|
80 if (*msgvec != NULL) {
|
|
81 if (*msgvec < 0) {
|
|
82 printf((gettext("Negative message given\n")));
|
|
83 return (1);
|
|
84 }
|
|
85 mp = &message[*msgvec - 1];
|
|
86 if ((mp->m_flag & MDELETED) == 0) {
|
|
87 dot = mp;
|
|
88 goto hitit;
|
|
89 }
|
|
90 printf(gettext("No applicable message\n"));
|
|
91 return (1);
|
|
92 }
|
|
93
|
|
94 /*
|
|
95 * If this is the first command, select message 1.
|
|
96 * Note that this must exist for us to get here at all.
|
|
97 */
|
|
98 if (!sawcom)
|
|
99 goto hitit;
|
|
100
|
|
101 /*
|
|
102 * Just find the next good message after dot, no
|
|
103 * wraparound.
|
|
104 */
|
|
105 for (mp = dot+1; mp < &message[msgCount]; mp++)
|
|
106 if ((mp->m_flag & (MDELETED|MSAVED)) == 0)
|
|
107 break;
|
|
108 if (mp >= &message[msgCount]) {
|
|
109 printf(gettext("At EOF\n"));
|
|
110 return (0);
|
|
111 }
|
|
112 dot = mp;
|
|
113 hitit:
|
|
114 /*
|
|
115 * Print dot.
|
|
116 */
|
|
117 list[0] = dot - &message[0] + 1;
|
|
118 list[1] = NULL;
|
|
119 return (type(list));
|
|
120 }
|
|
121
|
|
122 /*
|
|
123 * Save a message in a file. Mark the message as saved
|
|
124 * so we can discard when the user quits.
|
|
125 */
|
|
126 int
|
|
127 save(char str[])
|
|
128 {
|
|
129 return (save1(str, S_MARK));
|
|
130 }
|
|
131
|
|
132 /*
|
|
133 * Copy a message to a file without affected its saved-ness
|
|
134 */
|
|
135 int
|
|
136 copycmd(char str[])
|
|
137 {
|
|
138 return (save1(str, 0));
|
|
139 }
|
|
140
|
|
141 /*
|
|
142 * Save/copy the indicated messages at the end of the passed file name.
|
|
143 * If mark is true, mark the message "saved."
|
|
144 */
|
|
145 static int
|
|
146 save1(char str[], int mark)
|
|
147 {
|
|
148 char *file, *cmd;
|
|
149 int f, *msgvec;
|
|
150
|
|
151 cmd = mark ? "save" : "copy";
|
|
152 msgvec = (int *)salloc((msgCount + 2) * sizeof (*msgvec));
|
|
153 if ((file = snarf(str, &f, 0)) == NOSTR)
|
|
154 file = Getf("MBOX");
|
|
155 if (f == -1)
|
|
156 return (1);
|
|
157 if (!f) {
|
|
158 *msgvec = first(0, MMNORM);
|
|
159 if (*msgvec == NULL) {
|
|
160 printf(gettext("No messages to %s.\n"), cmd);
|
|
161 return (1);
|
|
162 }
|
|
163 msgvec[1] = NULL;
|
|
164 }
|
|
165 if (f && getmsglist(str, msgvec, 0) < 0)
|
|
166 return (1);
|
|
167 if ((file = expand(file)) == NOSTR)
|
|
168 return (1);
|
|
169 savemsglist(file, msgvec, mark | S_SAVING);
|
|
170 return (0);
|
|
171 }
|
|
172
|
|
173 int
|
|
174 Save(int *msgvec)
|
|
175 {
|
|
176 return (Save1(msgvec, S_MARK));
|
|
177 }
|
|
178
|
|
179 int
|
|
180 Copy(int *msgvec)
|
|
181 {
|
|
182 return (Save1(msgvec, 0));
|
|
183 }
|
|
184
|
|
185 /*
|
|
186 * save/copy the indicated messages at the end of a file named
|
|
187 * by the sender of the first message in the msglist.
|
|
188 */
|
|
189 static int
|
|
190 Save1(int *msgvec, int mark)
|
|
191 {
|
|
192 register char *from;
|
|
193 char recfile[BUFSIZ];
|
|
194
|
|
195 #ifdef notdef
|
|
196 from = striphosts(nameof(&message[*msgvec-1], 0));
|
|
197 #else
|
|
198 from = nameof(&message[*msgvec-1]);
|
|
199 #endif
|
|
200 getrecf(from, recfile, 1, sizeof (recfile));
|
|
201 if (*recfile != '\0')
|
|
202 savemsglist(safeexpand(recfile), msgvec, mark | S_SAVING);
|
|
203 return (0);
|
|
204 }
|
|
205
|
|
206 int
|
|
207 sput(char str[])
|
|
208 {
|
|
209 return (put1(str, 0));
|
|
210 }
|
|
211
|
|
212 int
|
|
213 Sput(char str[])
|
|
214 {
|
|
215 return (put1(str, S_NOIGNORE));
|
|
216 }
|
|
217
|
|
218 /*
|
|
219 * Put the indicated messages at the end of the passed file name.
|
|
220 */
|
|
221 static int
|
|
222 put1(char str[], int doign)
|
|
223 {
|
|
224 char *file;
|
|
225 int f, *msgvec;
|
|
226
|
|
227 msgvec = (int *)salloc((msgCount + 2) * sizeof (*msgvec));
|
|
228 if ((file = snarf(str, &f, 0)) == NOSTR)
|
|
229 file = Getf("MBOX");
|
|
230 if (f == -1)
|
|
231 return (1);
|
|
232 if (!f) {
|
|
233 *msgvec = first(0, MMNORM);
|
|
234 if (*msgvec == NULL) {
|
|
235 printf(gettext("No messages to put.\n"));
|
|
236 return (1);
|
|
237 }
|
|
238 msgvec[1] = NULL;
|
|
239 }
|
|
240 if (f && getmsglist(str, msgvec, 0) < 0)
|
|
241 return (1);
|
|
242 if ((file = expand(file)) == NOSTR)
|
|
243 return (1);
|
|
244 savemsglist(file, msgvec, doign);
|
|
245 return (0);
|
|
246 }
|
|
247
|
|
248 /*
|
|
249 * save a message list in a file.
|
|
250 * if wr set, doing "write" instead
|
|
251 * of "save" or "copy" so don't put
|
|
252 * out header.
|
|
253 */
|
|
254
|
|
255 static int wr_linecount; /* count of lines written */
|
|
256 static int wr_charcount; /* char count of lines written */
|
|
257 static int wr_inlines; /* count of lines read */
|
|
258 static long wr_maxlines; /* total lines in message */
|
|
259 static int wr_inhead; /* in header of message */
|
|
260
|
|
261 static void
|
|
262 savemsglist(char *file, int *msgvec, int flag)
|
|
263 {
|
|
264 register int *ip, mesg;
|
|
265 register struct message *mp;
|
|
266 char *disp;
|
|
267 FILE *obuf;
|
|
268 struct stat statb;
|
|
269 long lc, cc, t;
|
|
270 int bnry, mflag;
|
|
271
|
|
272 printf("\"%s\" ", file);
|
|
273 flush();
|
|
274 if (stat(file, &statb) >= 0)
|
|
275 disp = "[Appended]";
|
|
276 else
|
|
277 disp = "[New file]";
|
|
278 if ((obuf = fopen(file, "a")) == NULL) {
|
|
279 perror("");
|
|
280 return;
|
|
281 }
|
|
282 lc = cc = 0;
|
|
283 bnry = 0;
|
|
284 if (flag & S_SAVING)
|
|
285 mflag = (int)value("alwaysignore")?(M_IGNORE|M_SAVING):M_SAVING;
|
|
286 else if (flag & S_NOIGNORE)
|
|
287 mflag = 0;
|
|
288 else
|
|
289 mflag = M_IGNORE;
|
|
290 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
|
|
291 mesg = *ip;
|
|
292 mp = &message[mesg-1];
|
|
293 if (!mp->m_text) {
|
|
294 bnry = 1;
|
|
295 }
|
|
296 wr_linecount = 0;
|
|
297 wr_charcount = 0;
|
|
298 if (flag & S_NOHEADER) {
|
|
299 wr_inhead = 1;
|
|
300 wr_maxlines = mp->m_lines;
|
|
301 wr_inlines = 0;
|
|
302 t = msend(mp, obuf, 0, wrputs);
|
|
303 } else {
|
|
304 t = msend(mp, obuf, mflag, svputs);
|
|
305 }
|
|
306 if (t < 0) {
|
|
307 perror(file);
|
|
308 fclose(obuf);
|
|
309 return;
|
|
310 }
|
|
311 touch(mesg);
|
|
312 dot = mp;
|
|
313 lc += wr_linecount;
|
|
314 cc += wr_charcount;
|
|
315 if (flag & S_MARK)
|
|
316 mp->m_flag |= MSAVED;
|
|
317 }
|
|
318 fflush(obuf);
|
|
319 if (fferror(obuf))
|
|
320 perror(file);
|
|
321 fclose(obuf);
|
|
322 if (!bnry) {
|
|
323 printf("%s %ld/%ld\n", disp, lc, cc);
|
|
324 } else {
|
|
325 printf("%s binary/%ld\n", disp, cc);
|
|
326 }
|
|
327 }
|
|
328
|
|
329 static int
|
|
330 svputs(const char *line, FILE *obuf)
|
|
331 {
|
|
332 wr_linecount++;
|
|
333 wr_charcount += strlen(line);
|
|
334 return (fputs(line, obuf));
|
|
335 }
|
|
336
|
|
337 static int
|
|
338 wrputs(const char *line, FILE *obuf)
|
|
339 {
|
|
340 /*
|
|
341 * If this is a header line or
|
|
342 * the last line, don't write it out. Since we may add a
|
|
343 * "Status" line the line count may be off by one so insist
|
|
344 * that the last line is blank before we skip it.
|
|
345 */
|
|
346 wr_inlines++;
|
|
347 if (wr_inhead) {
|
|
348 if (strcmp(line, "\n") == 0)
|
|
349 wr_inhead = 0;
|
|
350 return (0);
|
|
351 }
|
|
352 if (wr_inlines >= wr_maxlines && strcmp(line, "\n") == 0)
|
|
353 return (0);
|
|
354 wr_linecount++;
|
|
355 wr_charcount += strlen(line);
|
|
356 return (fputs(line, obuf));
|
|
357 }
|
|
358
|
|
359 /*
|
|
360 * Write the indicated messages at the end of the passed
|
|
361 * file name, minus header and trailing blank line.
|
|
362 */
|
|
363
|
|
364 int
|
|
365 swrite(char str[])
|
|
366 {
|
|
367 register char *file;
|
|
368 int f, *msgvec;
|
|
369
|
|
370 msgvec = (int *)salloc((msgCount + 2) * sizeof (*msgvec));
|
|
371 if ((file = snarf(str, &f, 1)) == NOSTR)
|
|
372 return (1);
|
|
373 if (f == -1)
|
|
374 return (1);
|
|
375 if ((file = expand(file)) == NOSTR)
|
|
376 return (1);
|
|
377 if (!f) {
|
|
378 *msgvec = first(0, MMNORM);
|
|
379 if (*msgvec == NULL) {
|
|
380 printf(gettext("No messages to write.\n"));
|
|
381 return (1);
|
|
382 }
|
|
383 msgvec[1] = NULL;
|
|
384 }
|
|
385 if (f && getmsglist(str, msgvec, 0) < 0)
|
|
386 return (1);
|
|
387 savemsglist(file, msgvec, S_MARK|S_NOHEADER);
|
|
388 return (0);
|
|
389 }
|
|
390
|
|
391 /*
|
|
392 * Snarf the file from the end of the command line and
|
|
393 * return a pointer to it. If there is no file attached,
|
|
394 * just return NOSTR. Put a null in front of the file
|
|
395 * name so that the message list processing won't see it,
|
|
396 * unless the file name is the only thing on the line, in
|
|
397 * which case, return 0 in the reference flag variable.
|
|
398 */
|
|
399
|
|
400 /*
|
|
401 * The following definitions are used to characterize the syntactic
|
|
402 * category of the preceding character in the following parse procedure.
|
|
403 * The variable pc_type assumes these values.
|
|
404 */
|
|
405
|
|
406 #define SN_DELIM 1 /* Delimiter (<blank> or line beginning) */
|
|
407 #define SN_TOKEN 2 /* A part of a token */
|
|
408 #define SN_QUOTE 4 /* An entire quoted string (ie, "...") */
|
|
409
|
|
410 char *
|
|
411 snarf(char linebuf[], int *flag, int erf)
|
|
412 {
|
|
413 register char *p; /* utility pointer */
|
|
414 register char qc; /* quotation character to match */
|
|
415 register unsigned int pc_type; /* preceding character type */
|
|
416 register char *tok_beg; /* beginning of last token */
|
|
417 register char *tok_end; /* end of last token */
|
|
418 char *line_beg; /* beginning of line, after */
|
|
419 /* leading whitespace */
|
|
420
|
|
421 /*
|
|
422 * Skip leading whitespace.
|
|
423 */
|
|
424 for (line_beg = linebuf;
|
|
425 *line_beg && any(*line_beg, " \t");
|
|
426 line_beg++) {
|
|
427 /* empty body */
|
|
428 }
|
|
429 if (!*line_beg) {
|
|
430 if (erf) {
|
|
431 printf(gettext("No file specified\n."));
|
|
432 }
|
|
433 *flag = 0;
|
|
434 return (NOSTR);
|
|
435 }
|
|
436 /*
|
|
437 * Process line from left-to-right, 1 char at a time.
|
|
438 */
|
|
439 pc_type = SN_DELIM;
|
|
440 tok_beg = tok_end = NOSTR;
|
|
441 p = line_beg;
|
|
442 while (*p != '\0') {
|
|
443 if (any(*p, " \t")) {
|
|
444 /* This character is a DELIMITER */
|
|
445 if (pc_type & (SN_TOKEN|SN_QUOTE)) {
|
|
446 tok_end = p - 1;
|
|
447 }
|
|
448 pc_type = SN_DELIM;
|
|
449 p++;
|
|
450 } else if ((qc = *p) == '"' || qc == '\'') {
|
|
451 /* This character is a QUOTE character */
|
|
452 if (pc_type == SN_TOKEN) {
|
|
453 /* embedded quotation symbols are simply */
|
|
454 /* token characters. */
|
|
455 p++;
|
|
456 continue;
|
|
457 }
|
|
458 /* Search for the matching QUOTE character */
|
|
459 for (tok_beg = p, tok_end = NOSTR, p++;
|
|
460 *p != '\0' && *p != qc;
|
|
461 p++) {
|
|
462 if (*p == '\\' && *(p+1) == qc) {
|
|
463 p++;
|
|
464 }
|
|
465 }
|
|
466 if (*p == '\0') {
|
|
467 printf(gettext("Syntax error: missing "
|
|
468 "%c.\n"), qc);
|
|
469 *flag = -1;
|
|
470 return (NOSTR);
|
|
471 }
|
|
472 tok_end = p;
|
|
473 pc_type = SN_QUOTE;
|
|
474 p++;
|
|
475 } else {
|
|
476 /* This character should be a TOKEN character */
|
|
477 if (pc_type & (SN_DELIM|SN_TOKEN)) {
|
|
478 if (pc_type & SN_DELIM) {
|
|
479 tok_beg = p;
|
|
480 tok_end = NOSTR;
|
|
481 }
|
|
482 } else {
|
|
483 printf(gettext("improper quotes"
|
|
484 " at \"%s\".\n"), p);
|
|
485 *flag = -1;
|
|
486 return (NOSTR);
|
|
487 }
|
|
488 if (*p == '\\' && *++p == '\0') {
|
|
489 printf(gettext("\'\\\' at "
|
|
490 "end of line.\n"));
|
|
491 *flag = -1;
|
|
492 return (NOSTR);
|
|
493 }
|
|
494 pc_type = SN_TOKEN;
|
|
495 p++;
|
|
496 }
|
|
497 }
|
|
498 if (pc_type == SN_TOKEN) {
|
|
499 tok_end = p - 1;
|
|
500 }
|
|
501 if (tok_beg != NOSTR && tok_end != NOSTR) {
|
|
502 if (tok_beg == line_beg) {
|
|
503 *flag = 0;
|
|
504 } else {
|
|
505 tok_beg[-1] = '\0';
|
|
506 *flag = 1;
|
|
507 }
|
|
508 tok_end[1] = '\0';
|
|
509 return (tok_beg);
|
|
510 } else {
|
|
511 if (erf) {
|
|
512 printf(gettext("No file specified\n."));
|
|
513 }
|
|
514 *flag = 0;
|
|
515 return (NOSTR);
|
|
516 }
|
|
517 }
|
|
518
|
|
519 /*
|
|
520 * Delete messages, then type the new dot.
|
|
521 */
|
|
522
|
|
523 int
|
|
524 deltype(int msgvec[])
|
|
525 {
|
|
526 int list[2];
|
|
527 int lastdot;
|
|
528
|
|
529 lastdot = dot - &message[0] + 1;
|
|
530 if (delm(msgvec) >= 0) {
|
|
531 list[0] = dot - &message[0];
|
|
532 list[0]++;
|
|
533 if (list[0] > lastdot) {
|
|
534 touch(list[0]);
|
|
535 list[1] = NULL;
|
|
536 return (type(list));
|
|
537 }
|
|
538 printf(gettext("At EOF\n"));
|
|
539 return (0);
|
|
540 } else {
|
|
541 printf(gettext("No more messages\n"));
|
|
542 return (0);
|
|
543 }
|
|
544 }
|
|
545
|
|
546 /*
|
|
547 * Delete the indicated messages.
|
|
548 * Set dot to some nice place afterwards.
|
|
549 */
|
|
550 int
|
|
551 delm(int *msgvec)
|
|
552 {
|
|
553 register struct message *mp;
|
|
554 int *ip, mesg;
|
|
555 int last;
|
|
556
|
|
557 last = NULL;
|
|
558 for (ip = msgvec; *ip != NULL; ip++) {
|
|
559 mesg = *ip;
|
|
560 touch(mesg);
|
|
561 mp = &message[mesg-1];
|
|
562 mp->m_flag |= MDELETED|MTOUCH;
|
|
563 mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX);
|
|
564 last = mesg;
|
|
565 }
|
|
566 if (last != NULL) {
|
|
567 dot = &message[last-1];
|
|
568 last = first(0, MDELETED);
|
|
569 if (last != NULL) {
|
|
570 dot = &message[last-1];
|
|
571 return (0);
|
|
572 } else {
|
|
573 dot = &message[0];
|
|
574 return (-1);
|
|
575 }
|
|
576 }
|
|
577
|
|
578 /*
|
|
579 * Following can't happen -- it keeps lint happy
|
|
580 */
|
|
581
|
|
582 return (-1);
|
|
583 }
|
|
584
|
|
585 /*
|
|
586 * Undelete the indicated messages.
|
|
587 */
|
|
588 int
|
|
589 undelete(int *msgvec)
|
|
590 {
|
|
591 register struct message *mp;
|
|
592 int *ip, mesg;
|
|
593
|
|
594 for (ip = msgvec; ip-msgvec < msgCount; ip++) {
|
|
595 mesg = *ip;
|
|
596 if (mesg == 0)
|
|
597 return (0);
|
|
598 touch(mesg);
|
|
599 mp = &message[mesg-1];
|
|
600 dot = mp;
|
|
601 mp->m_flag &= ~MDELETED;
|
|
602 }
|
|
603 return (0);
|
|
604 }
|
|
605
|
|
606 /*
|
|
607 * Add the given header fields to the retained list.
|
|
608 * If no arguments, print the current list of retained fields.
|
|
609 */
|
|
610 int
|
|
611 retfield(char *list[])
|
|
612 {
|
|
613 char field[BUFSIZ];
|
|
614 register int h;
|
|
615 register struct ignore *igp;
|
|
616 char **ap;
|
|
617
|
|
618 if (argcount(list) == 0)
|
|
619 return (retshow());
|
|
620 for (ap = list; *ap != 0; ap++) {
|
|
621 istrcpy(field, sizeof (field), *ap);
|
|
622
|
|
623 if (member(field, retain))
|
|
624 continue;
|
|
625
|
|
626 h = hash(field);
|
|
627 if ((igp = (struct ignore *)
|
|
628 calloc(1, sizeof (struct ignore))) == NULL) {
|
|
629 panic("Couldn't allocate memory");
|
|
630 }
|
|
631 if ((igp->i_field = (char *)
|
|
632 calloc(strlen(field) + 1, sizeof (char))) == NULL) {
|
|
633 panic("Couldn't allocate memory");
|
|
634 }
|
|
635 strcpy(igp->i_field, field);
|
|
636 igp->i_link = retain[h];
|
|
637 retain[h] = igp;
|
|
638 nretained++;
|
|
639 }
|
|
640 return (0);
|
|
641 }
|
|
642
|
|
643 /*
|
|
644 * Print out all currently retained fields.
|
|
645 */
|
|
646 static int
|
|
647 retshow(void)
|
|
648 {
|
|
649 register int h, count;
|
|
650 struct ignore *igp;
|
|
651 char **ap, **ring;
|
|
652
|
|
653 count = 0;
|
|
654 for (h = 0; h < HSHSIZE; h++)
|
|
655 for (igp = retain[h]; igp != 0; igp = igp->i_link)
|
|
656 count++;
|
|
657 if (count == 0) {
|
|
658 printf(gettext("No fields currently being retained.\n"));
|
|
659 return (0);
|
|
660 }
|
|
661 ring = (char **)salloc((count + 1) * sizeof (char *));
|
|
662 ap = ring;
|
|
663 for (h = 0; h < HSHSIZE; h++)
|
|
664 for (igp = retain[h]; igp != 0; igp = igp->i_link)
|
|
665 *ap++ = igp->i_field;
|
|
666 *ap = 0;
|
|
667 qsort(ring, count, sizeof (char *), igcomp);
|
|
668 for (ap = ring; *ap != 0; ap++)
|
|
669 printf("%s\n", *ap);
|
|
670 return (0);
|
|
671 }
|
|
672
|
|
673 /*
|
|
674 * Remove a list of fields from the retain list.
|
|
675 */
|
|
676 int
|
|
677 unretfield(char *list[])
|
|
678 {
|
|
679 char **ap, field[BUFSIZ];
|
|
680 register int h, count = 0;
|
|
681 register struct ignore *ig1, *ig2;
|
|
682
|
|
683 if (argcount(list) == 0) {
|
|
684 for (h = 0; h < HSHSIZE; h++) {
|
|
685 ig1 = retain[h];
|
|
686 while (ig1) {
|
|
687 free(ig1->i_field);
|
|
688 ig2 = ig1->i_link;
|
|
689 free((char *)ig1);
|
|
690 ig1 = ig2;
|
|
691 count++;
|
|
692 }
|
|
693 retain[h] = NULL;
|
|
694 }
|
|
695 if (count == 0)
|
|
696 printf(gettext(
|
|
697 "No fields currently being retained.\n"));
|
|
698 nretained = 0;
|
|
699 return (0);
|
|
700 }
|
|
701 for (ap = list; *ap; ap++) {
|
|
702 istrcpy(field, sizeof (field), *ap);
|
|
703 h = hash(field);
|
|
704 for (ig1 = retain[h]; ig1; ig2 = ig1, ig1 = ig1->i_link)
|
|
705 if (strcmp(ig1->i_field, field) == 0) {
|
|
706 if (ig1 == retain[h])
|
|
707 retain[h] = ig1->i_link;
|
|
708 else
|
|
709 ig2->i_link = ig1->i_link;
|
|
710 free(ig1->i_field);
|
|
711 free((char *)ig1);
|
|
712 nretained--;
|
|
713 break;
|
|
714 }
|
|
715 }
|
|
716 return (0);
|
|
717 }
|
|
718
|
|
719 /*
|
|
720 * Add the given header fields to the ignored list.
|
|
721 * If no arguments, print the current list of ignored fields.
|
|
722 */
|
|
723 int
|
|
724 igfield(char *list[])
|
|
725 {
|
|
726 char field[BUFSIZ];
|
|
727 register int h;
|
|
728 register struct ignore *igp;
|
|
729 char **ap;
|
|
730
|
|
731 if (argcount(list) == 0)
|
|
732 return (igshow());
|
|
733 for (ap = list; *ap != 0; ap++) {
|
|
734 if (isign(*ap, 0))
|
|
735 continue;
|
|
736 istrcpy(field, sizeof (field), *ap);
|
|
737 h = hash(field);
|
|
738 if ((igp = (struct ignore *)
|
|
739 calloc(1, sizeof (struct ignore))) == NULL) {
|
|
740 panic("Couldn't allocate memory");
|
|
741 }
|
|
742 if ((igp->i_field = (char *)
|
|
743 calloc((unsigned)strlen(field) + 1,
|
|
744 sizeof (char))) == NULL) {
|
|
745 panic("Couldn't allocate memory");
|
|
746 }
|
|
747 strcpy(igp->i_field, field);
|
|
748 igp->i_link = ignore[h];
|
|
749 ignore[h] = igp;
|
|
750 }
|
|
751 return (0);
|
|
752 }
|
|
753
|
|
754 /*
|
|
755 * Print out all currently ignored fields.
|
|
756 */
|
|
757 static int
|
|
758 igshow(void)
|
|
759 {
|
|
760 register int h, count;
|
|
761 struct ignore *igp;
|
|
762 char **ap, **ring;
|
|
763
|
|
764 count = 0;
|
|
765 for (h = 0; h < HSHSIZE; h++)
|
|
766 for (igp = ignore[h]; igp != 0; igp = igp->i_link)
|
|
767 count++;
|
|
768 if (count == 0) {
|
|
769 printf(gettext("No fields currently being ignored.\n"));
|
|
770 return (0);
|
|
771 }
|
|
772 ring = (char **)salloc((count + 1) * sizeof (char *));
|
|
773 ap = ring;
|
|
774 for (h = 0; h < HSHSIZE; h++)
|
|
775 for (igp = ignore[h]; igp != 0; igp = igp->i_link)
|
|
776 *ap++ = igp->i_field;
|
|
777 *ap = 0;
|
|
778 qsort((char *)ring, (unsigned)count, sizeof (char *), igcomp);
|
|
779 for (ap = ring; *ap != 0; ap++)
|
|
780 printf("%s\n", *ap);
|
|
781 return (0);
|
|
782 }
|
|
783
|
|
784 /*
|
|
785 * Compare two names for sorting ignored field list.
|
|
786 */
|
|
787 static int
|
|
788 igcomp(const void *l, const void *r)
|
|
789 {
|
|
790 return (strcmp(*(char **)l, *(char **)r));
|
|
791 }
|
|
792
|
|
793 /*
|
|
794 * Remove a list of fields from the ignore list.
|
|
795 */
|
|
796 int
|
|
797 unigfield(char *list[])
|
|
798 {
|
|
799 char **ap, field[BUFSIZ];
|
|
800 register int h, count = 0;
|
|
801 register struct ignore *ig1, *ig2;
|
|
802
|
|
803 if (argcount(list) == 0) {
|
|
804 for (h = 0; h < HSHSIZE; h++) {
|
|
805 ig1 = ignore[h];
|
|
806 while (ig1) {
|
|
807 free(ig1->i_field);
|
|
808 ig2 = ig1->i_link;
|
|
809 free((char *)ig1);
|
|
810 ig1 = ig2;
|
|
811 count++;
|
|
812 }
|
|
813 ignore[h] = NULL;
|
|
814 }
|
|
815 if (count == 0)
|
|
816 printf(gettext("No fields currently being ignored.\n"));
|
|
817 return (0);
|
|
818 }
|
|
819 for (ap = list; *ap; ap++) {
|
|
820 istrcpy(field, sizeof (field), *ap);
|
|
821 h = hash(field);
|
|
822 for (ig1 = ignore[h]; ig1; ig2 = ig1, ig1 = ig1->i_link)
|
|
823 if (strcmp(ig1->i_field, field) == 0) {
|
|
824 if (ig1 == ignore[h])
|
|
825 ignore[h] = ig1->i_link;
|
|
826 else
|
|
827 ig2->i_link = ig1->i_link;
|
|
828 free(ig1->i_field);
|
|
829 free((char *)ig1);
|
|
830 break;
|
|
831 }
|
|
832 }
|
|
833 return (0);
|
|
834 }
|