1 # 2 #include "rcv.h" 3 #include <sys/stat.h> 4 5 /* 6 * Mail -- a mail program 7 * 8 * User commands. 9 */ 10 11 static char *SccsId = "@(#)cmd1.c 1.2 10/09/80"; 12 13 /* 14 * Print the current active headings. 15 */ 16 17 static int screen; 18 19 headers(msgvec) 20 int *msgvec; 21 { 22 register int n, mesg, flag; 23 register struct message *mp; 24 25 n = msgvec[0]; 26 if (n != 0) 27 screen = (n-1)/SCREEN; 28 if (screen < 0) 29 screen = 0; 30 mp = &message[screen * SCREEN]; 31 if (mp >= &message[msgCount]) 32 mp = &message[msgCount - SCREEN]; 33 if (mp < &message[0]) 34 mp = &message[0]; 35 flag = 0; 36 mesg = mp - &message[0]; 37 dot = mp; 38 for (; mp < &message[msgCount]; mp++) { 39 mesg++; 40 if (mp->m_flag & MDELETED) 41 continue; 42 if (flag++ >= SCREEN) 43 break; 44 printhead(mesg); 45 sreset(); 46 } 47 if (flag == 0) { 48 printf("No more mail.\n"); 49 return(1); 50 } 51 return(0); 52 } 53 54 /* 55 * Scroll to the next/previous screen 56 */ 57 58 scroll(arg) 59 char arg[]; 60 { 61 register int s; 62 int cur[1]; 63 64 cur[0] = 0; 65 s = screen; 66 switch (*arg) { 67 case 0: 68 case '+': 69 s++; 70 if (s*SCREEN > msgCount) { 71 printf("On last screenful of messages\n"); 72 return(0); 73 } 74 screen = s; 75 break; 76 77 case '-': 78 if (--s < 0) { 79 printf("On first screenful of messages\n"); 80 return(0); 81 } 82 screen = s; 83 break; 84 85 default: 86 printf("Unrecognized scrolling command \"%s\"\n", arg); 87 return(1); 88 } 89 return(headers(cur)); 90 } 91 92 93 /* 94 * Print out the headlines for each message 95 * in the passed message list. 96 */ 97 98 from(msgvec) 99 int *msgvec; 100 { 101 register int *ip; 102 103 for (ip = msgvec; *ip != NULL; ip++) { 104 printhead(*ip); 105 sreset(); 106 } 107 if (--ip >= msgvec) 108 dot = &message[*ip - 1]; 109 return(0); 110 } 111 112 /* 113 * Print out the header of a specific message. 114 * This is a slight improvement to the standard one. 115 */ 116 117 printhead(mesg) 118 { 119 struct message *mp; 120 FILE *ibuf; 121 char headline[LINESIZE], wcount[10], *subjline, dispc; 122 char pbuf[BUFSIZ]; 123 int s; 124 struct headline hl; 125 register char *cp; 126 127 mp = &message[mesg-1]; 128 ibuf = setinput(mp); 129 readline(ibuf, headline); 130 subjline = hfield("subject", mp); 131 if (subjline == NOSTR) 132 subjline = hfield("subj", mp); 133 134 /* 135 * Bletch! 136 */ 137 138 if (subjline != NOSTR && strlen(subjline) > 28) 139 subjline[29] = '\0'; 140 dispc = ' '; 141 if (mp->m_flag & MSAVED) 142 dispc = '*'; 143 if (mp->m_flag & MPRESERVE) 144 dispc = 'P'; 145 parse(headline, &hl, pbuf); 146 sprintf(wcount, " %d/%d", mp->m_lines, mp->m_size); 147 s = strlen(wcount); 148 cp = wcount + s; 149 while (s < 7) 150 s++, *cp++ = ' '; 151 *cp = '\0'; 152 if (subjline != NOSTR) 153 printf("%c%3d %-8s %16.16s %s \"%s\"\n", dispc, mesg, 154 nameof(mp), hl.l_date, wcount, subjline); 155 else 156 printf("%c%3d %-8s %16.16s %s\n", dispc, mesg, 157 nameof(mp), hl.l_date, wcount); 158 } 159 160 /* 161 * Print out the value of dot. 162 */ 163 164 pdot() 165 { 166 printf("%d\n", dot - &message[0] + 1); 167 return(0); 168 } 169 170 /* 171 * Print out all the possible commands. 172 */ 173 174 pcmdlist() 175 { 176 register struct cmd *cp; 177 register int cc; 178 extern struct cmd cmdtab[]; 179 180 printf("Commands are:\n"); 181 for (cc = 0, cp = cmdtab; cp->c_name != NULL; cp++) { 182 cc += strlen(cp->c_name) + 2; 183 if (cc > 72) { 184 printf("\n"); 185 cc = strlen(cp->c_name) + 2; 186 } 187 if ((cp+1)->c_name != NOSTR) 188 printf("%s, ", cp->c_name); 189 else 190 printf("%s\n", cp->c_name); 191 } 192 return(0); 193 } 194 195 /* 196 * Type out the messages requested. 197 */ 198 199 jmp_buf pipestop; 200 201 type(msgvec) 202 int *msgvec; 203 { 204 register *ip; 205 register struct message *mp; 206 register int mesg; 207 register char *cp; 208 int c, nlines; 209 int brokpipe(); 210 FILE *ibuf, *obuf; 211 212 obuf = stdout; 213 if (setjmp(pipestop)) { 214 if (obuf != stdout) { 215 pclose(obuf); 216 pipef = NULL; 217 } 218 signal(SIGPIPE, SIG_DFL); 219 return(0); 220 } 221 if (intty && outtty && (cp = value("crt")) != NOSTR) { 222 for (ip = msgvec, nlines = 0; *ip && ip-msgvec < msgCount; ip++) 223 nlines += message[*ip - 1].m_lines; 224 if (nlines > atoi(cp)) { 225 obuf = popen(MORE, "w"); 226 if (obuf == NULL) { 227 perror(MORE); 228 obuf = stdout; 229 } 230 else { 231 pipef = obuf; 232 signal(SIGPIPE, brokpipe); 233 } 234 } 235 } 236 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 237 mesg = *ip; 238 touch(mesg); 239 mp = &message[mesg-1]; 240 dot = mp; 241 print(mp, obuf); 242 } 243 signal(SIGPIPE, SIG_DFL); 244 if (obuf != stdout) { 245 pclose(obuf); 246 pipef = NULL; 247 } 248 return(0); 249 } 250 251 /* 252 * Respond to a broken pipe signal -- 253 * probably caused by using quitting more. 254 */ 255 256 brokpipe() 257 { 258 259 signal(SIGPIPE, SIG_IGN); 260 longjmp(pipestop, 1); 261 } 262 263 /* 264 * Print the indicated message on standard output. 265 */ 266 267 print(mp, obuf) 268 register struct message *mp; 269 FILE *obuf; 270 { 271 272 if (value("quiet") == NOSTR) 273 fprintf(obuf, "Message %2d:\n", mp - &message[0] + 1); 274 touch(mp - &message[0] + 1); 275 send(mp, obuf); 276 } 277 278 /* 279 * Print the top so many lines of each desired message. 280 * The number of lines is taken from the variable "toplines" 281 * and defaults to 5. 282 */ 283 284 top(msgvec) 285 int *msgvec; 286 { 287 register int *ip; 288 register struct message *mp; 289 register int mesg; 290 int c, topl, lines, lineb; 291 char *valtop, linebuf[LINESIZE]; 292 FILE *ibuf; 293 294 topl = 5; 295 valtop = value("toplines"); 296 if (valtop != NOSTR) { 297 topl = atoi(valtop); 298 if (topl < 0 || topl > 10000) 299 topl = 5; 300 } 301 lineb = 1; 302 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 303 mesg = *ip; 304 touch(mesg); 305 mp = &message[mesg-1]; 306 dot = mp; 307 if (value("quiet") == NOSTR) 308 printf("Message %2d:\n", mesg); 309 ibuf = setinput(mp); 310 c = mp->m_lines; 311 if (!lineb) 312 printf("\n"); 313 for (lines = 0; lines < c && lines <= topl; lines++) { 314 if (readline(ibuf, linebuf) <= 0) 315 break; 316 puts(linebuf); 317 lineb = blankline(linebuf); 318 } 319 } 320 return(0); 321 } 322 323 /* 324 * Touch all the given messages so that they will 325 * get mboxed. 326 */ 327 328 stouch(msgvec) 329 int msgvec[]; 330 { 331 register int *ip; 332 333 for (ip = msgvec; *ip != 0; ip++) { 334 touch(*ip); 335 dot = &message[*ip-1]; 336 dot->m_flag &= ~MPRESERVE; 337 } 338 return(0); 339 } 340