1 # 2 3 #include "rcv.h" 4 #include <sys/stat.h> 5 6 /* 7 * Mail -- a mail program 8 * 9 * More user commands. 10 */ 11 12 static char *SccsId = "@(#)cmd2.c 1.4 03/20/81"; 13 14 /* 15 * If any arguments were given, go to the next applicable argument 16 * following dot, otherwise, go to the next applicable message. 17 * If given as first command with no arguments, print first message. 18 */ 19 20 next(msgvec) 21 int *msgvec; 22 { 23 register struct message *mp; 24 register int *ip, *ip2; 25 int list[2], mdot; 26 27 if (*msgvec != NULL) { 28 29 /* 30 * If some messages were supplied, find the 31 * first applicable one following dot using 32 * wrap around. 33 */ 34 35 mdot = dot - &message[0] + 1; 36 37 /* 38 * Find the first message in the supplied 39 * message list which follows dot. 40 */ 41 42 for (ip = msgvec; *ip != NULL; ip++) 43 if (*ip > mdot) 44 break; 45 if (*ip == NULL) 46 ip = msgvec; 47 ip2 = ip; 48 do { 49 mp = &message[*ip2 - 1]; 50 if ((mp->m_flag & MDELETED) == 0) { 51 dot = mp; 52 goto hitit; 53 } 54 if (*ip2 != NULL) 55 ip2++; 56 if (*ip2 == NULL) 57 ip2 = msgvec; 58 } while (ip2 != ip); 59 printf("No messages applicable\n"); 60 return(1); 61 } 62 63 /* 64 * If this is the first command, select message 1. 65 * Note that this must exist for us to get here at all. 66 */ 67 68 if (!sawcom) 69 goto hitit; 70 71 /* 72 * Just find the next good message after dot, no 73 * wraparound. 74 */ 75 76 for (mp = dot+1; mp < &message[msgCount]; mp++) 77 if ((mp->m_flag & (MDELETED|MSAVED)) == 0) 78 break; 79 if (mp >= &message[msgCount]) { 80 printf("At EOF\n"); 81 return(0); 82 } 83 dot = mp; 84 hitit: 85 /* 86 * Print dot. 87 */ 88 89 list[0] = dot - &message[0] + 1; 90 list[1] = NULL; 91 return(type(list)); 92 } 93 94 /* 95 * Save the indicated messages at the end of the passed file name. 96 */ 97 98 save(str) 99 char str[]; 100 { 101 register int *ip, mesg; 102 register struct message *mp; 103 char *file, *disp; 104 int f, *msgvec, lc, cc, t; 105 FILE *obuf; 106 struct stat statb; 107 108 msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec); 109 if ((file = snarf(str, &f)) == NOSTR) 110 return(1); 111 if (!f) { 112 *msgvec = first(0, MMNORM); 113 if (*msgvec == NULL) { 114 printf("No messages to save.\n"); 115 return(1); 116 } 117 msgvec[1] = NULL; 118 } 119 if (f && getmsglist(str, msgvec, 0) < 0) 120 return(1); 121 if ((file = expand(file)) == NOSTR) 122 return(1); 123 printf("\"%s\" ", file); 124 flush(); 125 if (stat(file, &statb) >= 0) 126 disp = "[Appended]"; 127 else 128 disp = "[New file]"; 129 if ((obuf = fopen(file, "a")) == NULL) { 130 perror(NOSTR); 131 return(1); 132 } 133 cc = lc = 0; 134 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 135 mesg = *ip; 136 touch(mesg); 137 mp = &message[mesg-1]; 138 if ((t = send(mp, obuf)) < 0) { 139 perror(file); 140 fclose(obuf); 141 return(1); 142 } 143 lc += t; 144 cc += msize(mp); 145 mp->m_flag |= MSAVED; 146 } 147 fflush(obuf); 148 if (ferror(obuf)) 149 perror(file); 150 fclose(obuf); 151 printf("%s %d/%d\n", disp, lc, cc); 152 return(0); 153 } 154 155 /* 156 * Write the indicated messages at the end of the passed 157 * file name, minus header and trailing blank line. 158 */ 159 160 swrite(str) 161 char str[]; 162 { 163 register int *ip, mesg; 164 register struct message *mp; 165 register char *file, *disp; 166 char linebuf[BUFSIZ]; 167 int f, *msgvec, lc, cc, t; 168 FILE *obuf, *mesf; 169 struct stat statb; 170 171 msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec); 172 if ((file = snarf(str, &f)) == NOSTR) 173 return(1); 174 if ((file = expand(file)) == NOSTR) 175 return(1); 176 if (!f) { 177 *msgvec = first(0, MMNORM); 178 if (*msgvec == NULL) { 179 printf("No messages to write.\n"); 180 return(1); 181 } 182 msgvec[1] = NULL; 183 } 184 if (f && getmsglist(str, msgvec, 0) < 0) 185 return(1); 186 printf("\"%s\" ", file); 187 flush(); 188 if (stat(file, &statb) >= 0) 189 disp = "[Appended]"; 190 else 191 disp = "[New file]"; 192 if ((obuf = fopen(file, "a")) == NULL) { 193 perror(NOSTR); 194 return(1); 195 } 196 cc = lc = 0; 197 for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) { 198 mesg = *ip; 199 touch(mesg); 200 mp = &message[mesg-1]; 201 mesf = setinput(mp); 202 t = mp->m_lines - 2; 203 readline(mesf, linebuf); 204 while (t-- > 0) { 205 fgets(linebuf, BUFSIZ, mesf); 206 fputs(linebuf, obuf); 207 cc += strlen(linebuf); 208 } 209 lc += mp->m_lines - 2; 210 mp->m_flag |= MSAVED; 211 } 212 fflush(obuf); 213 if (ferror(obuf)) 214 perror(file); 215 fclose(obuf); 216 printf("%s %d/%d\n", disp, lc, cc); 217 return(0); 218 } 219 220 /* 221 * Snarf the file from the end of the command line and 222 * return a pointer to it. If there is no file attached, 223 * just return NOSTR. Put a null in front of the file 224 * name so that the message list processing won't see it, 225 * unless the file name is the only thing on the line, in 226 * which case, return 0 in the reference flag variable. 227 */ 228 229 char * 230 snarf(linebuf, flag) 231 char linebuf[]; 232 int *flag; 233 { 234 register char *cp; 235 236 *flag = 1; 237 cp = strlen(linebuf) + linebuf - 1; 238 239 /* 240 * Strip away trailing blanks. 241 */ 242 243 while (*cp == ' ' && cp > linebuf) 244 cp--; 245 *++cp = 0; 246 247 /* 248 * Now search for the beginning of the file name. 249 */ 250 251 while (cp > linebuf && !any(*cp, "\t ")) 252 cp--; 253 if (*cp == '\0') { 254 printf("No file specified.\n"); 255 return(NOSTR); 256 } 257 if (any(*cp, " \t")) 258 *cp++ = 0; 259 else 260 *flag = 0; 261 return(cp); 262 } 263 264 /* 265 * Delete messages. 266 */ 267 268 delete(msgvec) 269 int msgvec[]; 270 { 271 return(delm(msgvec)); 272 } 273 274 /* 275 * Delete messages, then type the new dot. 276 */ 277 278 deltype(msgvec) 279 int msgvec[]; 280 { 281 int list[2]; 282 283 if (delm(msgvec) >= 0) { 284 list[0] = dot - &message[0]; 285 list[0]++; 286 touch(list[0]); 287 list[1] = NULL; 288 return(type(list)); 289 } 290 else { 291 printf("No more messages\n"); 292 return(0); 293 } 294 } 295 296 /* 297 * Delete the indicated messages. 298 * Set dot to some nice place afterwards. 299 * Internal interface. 300 */ 301 302 delm(msgvec) 303 int *msgvec; 304 { 305 register struct message *mp; 306 register *ip, mesg; 307 int last; 308 309 last = NULL; 310 for (ip = msgvec; *ip != NULL; ip++) { 311 mesg = *ip; 312 touch(mesg); 313 mp = &message[mesg-1]; 314 mp->m_flag |= MDELETED|MTOUCH; 315 mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX); 316 last = mesg; 317 } 318 if (last != NULL) { 319 dot = &message[last-1]; 320 last = first(0, MDELETED); 321 if (last != NULL) { 322 dot = &message[last-1]; 323 return(0); 324 } 325 else { 326 dot = &message[0]; 327 return(-1); 328 } 329 } 330 331 /* 332 * Following can't happen -- it keeps lint happy 333 */ 334 335 return(-1); 336 } 337 338 /* 339 * Undelete the indicated messages. 340 */ 341 342 undelete(msgvec) 343 int *msgvec; 344 { 345 register struct message *mp; 346 register *ip, mesg; 347 348 for (ip = msgvec; ip-msgvec < msgCount; ip++) { 349 mesg = *ip; 350 if (mesg == 0) 351 return; 352 touch(mesg); 353 mp = &message[mesg-1]; 354 dot = mp; 355 mp->m_flag &= ~MDELETED; 356 } 357 } 358 359 /* 360 * Interactively dump core on "core" 361 */ 362 363 core() 364 { 365 register int pid; 366 int status; 367 368 if ((pid = vfork()) == -1) { 369 perror("fork"); 370 return(1); 371 } 372 if (pid == 0) { 373 abort(); 374 _exit(1); 375 } 376 printf("Okie dokie"); 377 fflush(stdout); 378 while (wait(&status) != pid) 379 ; 380 if (status & 0200) 381 printf(" -- Core dumped\n"); 382 else 383 printf("\n"); 384 } 385