cmd2.c

Upload User: acmefrp
Upload Date: 2010-03-06
Package Size: 23768k
Code Size: 11k
Category: OS Develop
Development Platform: C/C++
  1. #ifndef lint
  2. static char *sccsid = "@(#)cmd2.c 1.1 92/07/30 SMI"; /* from S5R2 1.1 */
  3. #endif
  4. #include "rcv.h"
  5. #include <sys/stat.h>
  6. /*
  7.  * mailx -- a modified version of a University of California at Berkeley
  8.  * mail program
  9.  *
  10.  * More user commands.
  11.  */
  12. /*
  13.  * If any arguments were given, go to the next applicable argument
  14.  * following dot, otherwise, go to the next applicable message.
  15.  * If given as first command with no arguments, print first message.
  16.  */
  17. next(msgvec)
  18. int *msgvec;
  19. {
  20. register struct message *mp;
  21. register int *ip, *ip2;
  22. int list[2], mdot;
  23. if (*msgvec != NULL) {
  24. /*
  25.  * If some messages were supplied, find the 
  26.  * first applicable one following dot using
  27.  * wrap around.
  28.  */
  29. mdot = dot - &message[0] + 1;
  30. /*
  31.  * Find the first message in the supplied
  32.  * message list which follows dot.
  33.  */
  34. for (ip = msgvec; *ip != NULL; ip++)
  35. if (*ip > mdot)
  36. break;
  37. if (*ip == NULL)
  38. ip = msgvec;
  39. ip2 = ip;
  40. do {
  41. mp = &message[*ip2 - 1];
  42. if ((mp->m_flag & MDELETED) == 0) {
  43. dot = mp;
  44. goto hitit;
  45. }
  46. if (*ip2 != NULL)
  47. ip2++;
  48. if (*ip2 == NULL)
  49. ip2 = msgvec;
  50. } while (ip2 != ip);
  51. printf("No messages applicablen");
  52. return(1);
  53. }
  54. /*
  55.  * If this is the first command, select message 1.
  56.  * Note that this must exist for us to get here at all.
  57.  */
  58. if (!sawcom)
  59. goto hitit;
  60. /*
  61.  * Just find the next good message after dot, no
  62.  * wraparound.
  63.  */
  64. for (mp = dot+1; mp < &message[msgCount]; mp++)
  65. if ((mp->m_flag & (MDELETED|MSAVED)) == 0)
  66. break;
  67. if (mp >= &message[msgCount]) {
  68. printf("At EOFn");
  69. return(0);
  70. }
  71. dot = mp;
  72. hitit:
  73. /*
  74.  * Print dot.
  75.  */
  76. list[0] = dot - &message[0] + 1;
  77. list[1] = NULL;
  78. return(type(list));
  79. }
  80. /*
  81.  * Save a message in a file.  Mark the message as saved
  82.  * so we can discard when the user quits.
  83.  */
  84. save(str)
  85. char str[];
  86. {
  87. return(save1(str, 1));
  88. }
  89. /*
  90.  * Copy a message to a file without affected its saved-ness
  91.  */
  92. copycmd(str)
  93. char str[];
  94. {
  95. return(save1(str, 0));
  96. }
  97. /*
  98.  * Save/copy the indicated messages at the end of the passed file name.
  99.  * If mark is true, mark the message "saved."
  100.  */
  101. save1(str, mark)
  102. char str[];
  103. {
  104. char *file, *cmd;
  105. int f, *msgvec;
  106. cmd = mark ? "save" : "copy";
  107. msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
  108. if ((file = snarf(str, &f, 0)) == NOSTR)
  109. file = Getf("MBOX");
  110. if (f==-1)
  111. return(1);
  112. if (!f) {
  113. *msgvec = first(0, MMNORM);
  114. if (*msgvec == NULL) {
  115. printf("No messages to %s.n", cmd);
  116. return(1);
  117. }
  118. msgvec[1] = NULL;
  119. }
  120. if (f && getmsglist(str, msgvec, 0) < 0)
  121. return(1);
  122. if ((file = expand(file)) == NOSTR)
  123. return(1);
  124. savemsglist(file, msgvec, mark, 0);
  125. return(0);
  126. }
  127. Save(msgvec)
  128. int *msgvec;
  129. {
  130. return(Save1(msgvec, 1));
  131. }
  132. Copy(msgvec)
  133. int *msgvec;
  134. {
  135. return(Save1(msgvec, 0));
  136. }
  137. /*
  138.  * save/copy the indicated messages at the end of a file named
  139.  * by the sender of the first message in the msglist.
  140.  */
  141. Save1(msgvec, mark)
  142. int *msgvec;
  143. {
  144. register char *from;
  145. char recfile[BUFSIZ];
  146. from = striphosts(nameof(&message[*msgvec-1], 0));
  147. getrecf(from, recfile, 1);
  148. savemsglist(expand(recfile), msgvec, mark, 0);
  149. return(0);
  150. }
  151. /*
  152.  * save a message list in a file.
  153.  * if wr set, doing "write" instead
  154.  * of "save" or "copy" so don't put
  155.  * out first and last lines.
  156.  */
  157. int wr_linecount; /* count of lines written */
  158. int wr_charcount; /* char count of lines written */
  159. int wr_maxlines; /* total lines in message */
  160. savemsglist(file, msgvec, mark, wr)
  161. char *file;
  162. int *msgvec;
  163. {
  164. register int *ip, mesg;
  165. register struct message *mp;
  166. char *disp;
  167. FILE *obuf;
  168. struct stat statb;
  169. int lc, t;
  170. long cc;
  171. int wrputs();
  172. printf(""%s" ", file);
  173. fflush(stdout);
  174. if (stat(file, &statb) >= 0)
  175. disp = "[Appended]";
  176. else
  177. disp = "[New file]";
  178. if ((obuf = fopen(file, "a")) == NULL) {
  179. perror("");
  180. return;
  181. }
  182. cc = 0L;
  183. lc = 0;
  184. for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
  185. mesg = *ip;
  186. touch(mesg);
  187. mp = &message[mesg-1];
  188. wr_linecount = 0;
  189. wr_charcount = 0;
  190. if (wr) {
  191. wr_maxlines = mp->m_lines;
  192. t = msend(mp, obuf, 0, wrputs);
  193. } else {
  194. wr_maxlines = 0;
  195. t = msend(mp, obuf, (int)value("alwaysignore"), wrputs);
  196. }
  197. if (t < 0) {
  198. perror(file);
  199. fclose(obuf);
  200. return;
  201. }
  202. lc += t;
  203. cc += wr_charcount;
  204. if (wr)
  205. lc -= 2;
  206. if (mark)
  207. mp->m_flag |= MSAVED;
  208. }
  209. fflush(obuf);
  210. if (ferror(obuf))
  211. perror(file);
  212. fclose(obuf);
  213. printf("%s %d/%ldn", disp, lc, cc);
  214. }
  215. wrputs(line, obuf)
  216. char *line;
  217. FILE *obuf;
  218. {
  219. wr_linecount++;
  220. /*
  221.  * If doing "write" command and this is the first line or
  222.  * the last line, don't write it out.  Since we may add a
  223.  * "Status" line the line count may be off by one so insist
  224.  * that the last line is blank before we skip it.
  225.  */
  226. if (wr_maxlines && (wr_linecount == 1 ||
  227.     (wr_linecount >= wr_maxlines && strcmp(line, "n") == 0)))
  228. return;
  229. wr_charcount += strlen(line);
  230. fputs(line, obuf);
  231. }
  232. /*
  233.  * Write the indicated messages at the end of the passed
  234.  * file name, minus header and trailing blank line.
  235.  */
  236. swrite(str)
  237. char str[];
  238. {
  239. register char *file;
  240. int f, *msgvec;
  241. msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
  242. if ((file = snarf(str, &f, 1)) == NOSTR)
  243. return(1);
  244. if (f==-1)
  245. return(1);
  246. if ((file = expand(file)) == NOSTR)
  247. return(1);
  248. if (!f) {
  249. *msgvec = first(0, MMNORM);
  250. if (*msgvec == NULL) {
  251. printf("No messages to write.n");
  252. return(1);
  253. }
  254. msgvec[1] = NULL;
  255. }
  256. if (f && getmsglist(str, msgvec, 0) < 0)
  257. return(1);
  258. if ((file = expand(file)) == NOSTR)
  259. return(1);
  260. savemsglist(file, msgvec, 1, 1);
  261. return(0);
  262. }
  263. /*
  264.  * Snarf the file from the end of the command line and
  265.  * return a pointer to it.  If there is no file attached,
  266.  * just return NOSTR.  Put a null in front of the file
  267.  * name so that the message list processing won't see it,
  268.  * unless the file name is the only thing on the line, in
  269.  * which case, return 0 in the reference flag variable.
  270.  */
  271. char *
  272. snarf(linebuf, flag, erf)
  273. char linebuf[];
  274. int *flag;
  275. {
  276. register char *cp;
  277. char end;
  278. *flag = 1;
  279. cp = strlen(linebuf) + linebuf - 1;
  280. /*
  281.  * Strip away trailing blanks.
  282.  */
  283. while (*cp == ' ' && cp > linebuf)
  284. cp--;
  285. *++cp = 0;
  286. /*
  287.  * Now see if string is quoted
  288.  */
  289. if (cp > linebuf && any(cp[-1], "'"")) {
  290. end = *--cp;
  291. *cp = '';
  292. while (*cp != end && cp > linebuf)
  293. cp--;
  294. if (*cp != end) {
  295. printf("Syntax error: missing %c.n", end);
  296. *flag = -1;
  297. return(NOSTR);
  298. }
  299. if (cp==linebuf)
  300. *flag = 0;
  301. *cp++ = '';
  302. return(cp);
  303. }
  304. /*
  305.  * Now search for the beginning of the file name.
  306.  */
  307. while (cp > linebuf && !any(*cp, "t "))
  308. cp--;
  309. if (*cp == '') {
  310. if (erf)
  311. printf("No file specified.n");
  312. *flag = 0;
  313. return(NOSTR);
  314. }
  315. if (any(*cp, " t"))
  316. *cp++ = 0;
  317. else
  318. *flag = 0;
  319. return(cp);
  320. }
  321. /*
  322.  * Delete messages.
  323.  */
  324. delete(msgvec)
  325. int msgvec[];
  326. {
  327. return(delm(msgvec));
  328. }
  329. /*
  330.  * Delete messages, then type the new dot.
  331.  */
  332. deltype(msgvec)
  333. int msgvec[];
  334. {
  335. int list[2];
  336. int lastdot;
  337. lastdot = dot - &message[0] + 1;
  338. if (delm(msgvec) >= 0) {
  339. list[0] = dot - &message[0];
  340. list[0]++;
  341. if (list[0] > lastdot) {
  342. touch(list[0]);
  343. list[1] = NULL;
  344. return(type(list));
  345. }
  346. printf("At EOFn");
  347. return(0);
  348. }
  349. else {
  350. printf("No more messagesn");
  351. return(0);
  352. }
  353. }
  354. /*
  355.  * Delete the indicated messages.
  356.  * Set dot to some nice place afterwards.
  357.  * Internal interface.
  358.  */
  359. delm(msgvec)
  360. int *msgvec;
  361. {
  362. register struct message *mp;
  363. register *ip, mesg;
  364. int last;
  365. last = NULL;
  366. for (ip = msgvec; *ip != NULL; ip++) {
  367. mesg = *ip;
  368. touch(mesg);
  369. mp = &message[mesg-1];
  370. mp->m_flag |= MDELETED|MTOUCH;
  371. mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX);
  372. last = mesg;
  373. }
  374. if (last != NULL) {
  375. dot = &message[last-1];
  376. last = first(0, MDELETED);
  377. if (last != NULL) {
  378. dot = &message[last-1];
  379. return(0);
  380. }
  381. else {
  382. dot = &message[0];
  383. return(-1);
  384. }
  385. }
  386. /*
  387.  * Following can't happen -- it keeps lint happy
  388.  */
  389. return(-1);
  390. }
  391. /*
  392.  * Undelete the indicated messages.
  393.  */
  394. undelete(msgvec)
  395. int *msgvec;
  396. {
  397. register struct message *mp;
  398. register *ip, mesg;
  399. for (ip = msgvec; ip-msgvec < msgCount; ip++) {
  400. mesg = *ip;
  401. if (mesg == 0)
  402. return(0);
  403. touch(mesg);
  404. mp = &message[mesg-1];
  405. dot = mp;
  406. mp->m_flag &= ~MDELETED;
  407. }
  408. return(0);
  409. }
  410. /*
  411.  * Add the given header fields to the retained list.
  412.  * If no arguments, print the current list of retained fields.
  413.  */
  414. retfield(list)
  415. char *list[];
  416. {
  417. char field[BUFSIZ];
  418. register int h;
  419. register struct ignore *igp;
  420. char **ap;
  421. if (argcount(list) == 0)
  422. return(retshow());
  423. for (ap = list; *ap != 0; ap++) {
  424. istrcpy(field, *ap);
  425. if (member(field, retain))
  426. continue;
  427. h = hash(field);
  428. igp = (struct ignore *) calloc(1, sizeof (struct ignore));
  429. igp->i_field = calloc(strlen(field) + 1, sizeof (char));
  430. strcpy(igp->i_field, field);
  431. igp->i_link = retain[h];
  432. retain[h] = igp;
  433. nretained++;
  434. }
  435. return(0);
  436. }
  437. /*
  438.  * Print out all currently retained fields.
  439.  */
  440. retshow()
  441. {
  442. register int h, count;
  443. struct ignore *igp;
  444. char **ap, **ring;
  445. int igcomp();
  446. count = 0;
  447. for (h = 0; h < HSHSIZE; h++)
  448. for (igp = retain[h]; igp != 0; igp = igp->i_link)
  449. count++;
  450. if (count == 0) {
  451. printf("No fields currently being retained.n");
  452. return(0);
  453. }
  454. ring = (char **) salloc((count + 1) * sizeof (char *));
  455. ap = ring;
  456. for (h = 0; h < HSHSIZE; h++)
  457. for (igp = retain[h]; igp != 0; igp = igp->i_link)
  458. *ap++ = igp->i_field;
  459. *ap = 0;
  460. qsort(ring, count, sizeof (char *), igcomp);
  461. for (ap = ring; *ap != 0; ap++)
  462. printf("%sn", *ap);
  463. return(0);
  464. }
  465. /*
  466.  * Add the given header fields to the ignored list.
  467.  * If no arguments, print the current list of ignored fields.
  468.  */
  469. igfield(list)
  470. char *list[];
  471. {
  472. char field[BUFSIZ];
  473. register int h;
  474. register struct ignore *igp;
  475. char **ap;
  476. if (argcount(list) == 0)
  477. return(igshow());
  478. for (ap = list; *ap != 0; ap++) {
  479. if (isign(*ap))
  480. continue;
  481. istrcpy(field, *ap);
  482. h = hash(field);
  483. igp = (struct ignore *) calloc(1, sizeof (struct ignore));
  484. igp->i_field = calloc((unsigned) strlen(field) + 1, sizeof (char));
  485. strcpy(igp->i_field, field);
  486. igp->i_link = ignore[h];
  487. ignore[h] = igp;
  488. }
  489. return(0);
  490. }
  491. /*
  492.  * Print out all currently ignored fields.
  493.  */
  494. igshow()
  495. {
  496. register int h, count;
  497. struct ignore *igp;
  498. char **ap, **ring;
  499. int igcomp();
  500. count = 0;
  501. for (h = 0; h < HSHSIZE; h++)
  502. for (igp = ignore[h]; igp != 0; igp = igp->i_link)
  503. count++;
  504. if (count == 0) {
  505. printf("No fields currently being ignored.n");
  506. return(0);
  507. }
  508. ring = (char **) salloc((count + 1) * sizeof (char *));
  509. ap = ring;
  510. for (h = 0; h < HSHSIZE; h++)
  511. for (igp = ignore[h]; igp != 0; igp = igp->i_link)
  512. *ap++ = igp->i_field;
  513. *ap = 0;
  514. qsort((char *) ring, (unsigned) count, sizeof (char *), igcomp);
  515. for (ap = ring; *ap != 0; ap++)
  516. printf("%sn", *ap);
  517. return(0);
  518. }
  519. /*
  520.  * Compare two names for sorting ignored field list.
  521.  */
  522. igcomp(l, r)
  523. char **l, **r;
  524. {
  525. return(strcmp(*l, *r));
  526. }