1: /* m_gmsg.c - read a folder */ 2: 3: #include "../h/mh.h" 4: #include <stdio.h> 5: #include <sys/types.h> 6: #include <sys/stat.h> 7: #ifndef BSD42 8: #ifndef SYS5 9: #include <ndir.h> 10: #else SYS5 11: #include <dir.h> 12: #endif SYS5 13: #else BSD42 14: #include <sys/dir.h> 15: #endif BSD42 16: 17: 18: #define NINFO (MAXFOLDER / 5) /* PLEASE be non-trivial... */ 19: struct info { 20: int msgno; 21: short stats; 22: char pad[sizeof (int) - sizeof (short)]; 23: }; 24: 25: static int len; 26: static struct info *head; 27: 28: /* */ 29: 30: struct msgs *m_gmsg (name) 31: register char *name; 32: { 33: #ifdef COMPAT 34: register int cur, 35: fd; 36: #endif COMPAT 37: register int i, 38: j; 39: register struct info *rover, 40: *tail; 41: #ifdef COMPAT 42: register char *cp; 43: char buffer[BUFSIZ]; 44: #endif COMPAT 45: register struct msgs *mp; 46: register struct direct *dp; 47: register DIR * dd; 48: struct stat st; 49: 50: if ((dd = opendir (name = m_mailpath (name))) == NULL) { 51: free (name); 52: return NULL; 53: } 54: (void) fstat (dd -> dd_fd, &st); 55: 56: mp = (struct msgs *) malloc (MSIZE (mp, 0, 0)); 57: if (mp == NULL) 58: adios (NULLCP, "unable to allocate folder storage"); 59: mp -> lowmsg = mp -> hghmsg = mp -> nummsg = 0; 60: mp -> curmsg = 0; 61: mp -> lowsel = mp -> hghsel = mp -> numsel = 0; 62: mp -> foldpath = name; 63: mp -> msgflags = NULL; 64: if (st.st_uid != getuid () || access (name, 02) == NOTOK) 65: mp -> msgflags |= READONLY; 66: #ifdef COMPAT 67: cur = 0; 68: #endif COMPAT 69: j = strlen (SBACKUP); 70: if (head == NULL) 71: if ((head = (struct info *) 72: malloc ((unsigned) ((len = NINFO) * sizeof *head))) == NULL) 73: adios (NULLCP, "unable to allocate info storage"); 74: tail = (rover = head) + len; 75: 76: while (dp = readdir (dd)) 77: if (i = m_atoi (dp -> d_name)) { 78: if (rover >= tail) { 79: register int curlen = tail - head; 80: 81: if ((tail = (struct info *) realloc ((char *) head, 82: (unsigned) ((len += NINFO) * sizeof *head))) 83: == NULL) 84: adios (NULLCP, "unable to allocate info storage"); 85: else 86: rover = tail + curlen, head = tail, tail += len; 87: } 88: if (i > mp -> hghmsg) 89: mp -> hghmsg = i; 90: mp -> nummsg++; 91: if (mp -> lowmsg == 0 || i < mp -> lowmsg) 92: mp -> lowmsg = i; 93: rover -> msgno = i; 94: rover -> stats = EXISTS; 95: #ifdef notdef 96: rover -> stats &= ~DELETED; 97: #endif notdef 98: rover++; 99: } 100: else 101: switch (dp -> d_name[0]) { 102: case '.': 103: continue; 104: 105: case ',': 106: #ifdef notdef 107: if ((i = m_atoi (dp -> d_name + 1)) { 108: register struct info *l; 109: 110: for (l = head; l < rover; l++) 111: if (l -> msgno == i) { 112: if (!(l -> stats & EXISTS)) 113: l -> stats |= DELETED; 114: break; 115: } 116: } 117: #endif notdef 118: continue; 119: 120: #ifdef MHE 121: case '+': 122: continue; 123: #endif MHE 124: 125: #ifdef UCI 126: case '_': 127: case '#': 128: continue; 129: #endif UCI 130: 131: default: 132: #ifdef COMPAT 133: if (strcmp (dp -> d_name, current) == 0) { 134: cur++; 135: continue; 136: } 137: #endif COMPAT 138: if (strcmp (dp -> d_name, LINK) == 0 139: || strncmp (dp -> d_name, SBACKUP, j) == 0) 140: continue; 141: mp -> msgflags |= OTHERS; 142: continue; 143: } 144: 145: closedir (dd); 146: 147: /* */ 148: 149: #ifdef COMPAT 150: (void) sprintf (buffer, "%s-%s", current, name); 151: if (cp = m_find (buffer)) { 152: i = m_atoi (cp); 153: (void) m_delete(buffer); 154: if (i > 0) 155: mp -> curmsg = i; 156: } 157: if (mp -> curmsg == 0 && cur && (fd = open (current, 0)) != NOTOK) { 158: if ((i = read (fd, buffer, sizeof buffer)) > 0) { 159: if (cp = index (buffer, '\n')) 160: *cp = NULL; 161: if ((i = m_atoi (buffer)) > 0) 162: mp -> curmsg = i; 163: } 164: (void) close (fd); 165: } 166: if (cur && !(mp -> msgflags & READONLY)){ /* sneaky... */ 167: (void) sprintf (buffer, "%s/%s", name, current); 168: (void) unlink (buffer); 169: } 170: #endif COMPAT 171: 172: #ifndef MTR 173: mp -> lowoff = 1; 174: #else MTR 175: mp -> lowoff = mp -> lowmsg; 176: #endif MTR 177: mp -> hghoff = mp -> hghmsg + 1;/* for "new" in m_convert */ 178: 179: mp = (struct msgs *) 180: realloc ((char *) mp, MSIZE (mp, mp -> lowoff, mp -> hghoff)); 181: if (mp == NULL) 182: adios (NULLCP, "unable to allocate folder storage"); 183: #ifndef MTR 184: for (i = mp -> lowmsg; i <= mp -> hghmsg; i++) 185: mp -> msgstats[i] = 0; 186: #else MTR 187: mp -> msgstats = (short *) 188: calloc ((unsigned) 1, MSIZEX (mp, mp -> lowmsg, mp -> hghmsg)); 189: if (mp -> msgstats == NULL) 190: adios (NULLCP, "unable to allocate messages storage"); 191: mp -> msgstats = (mp -> msgbase = mp -> msgstats) - mp -> lowoff; 192: if (mp -> msgstats < 0) 193: adios (NULLCP, "m_gmsg() botch -- you lose big"); 194: #endif MTR 195: for (tail = head; tail < rover; tail++) 196: mp -> msgstats[tail -> msgno] = tail -> stats; 197: m_getatr (mp); 198: 199: return mp; 200: } 201: 202: /* */ 203: 204: static m_getatr (mp) 205: register struct msgs *mp; 206: { 207: int alen, 208: bits, 209: i, 210: j, 211: plen, 212: state; 213: register char *cp; 214: char name[NAMESZ], 215: field[BUFSIZ]; 216: register struct node *np; 217: register FILE * fp; 218: 219: bits = FFATTRSLOT; 220: 221: mp -> msgattrs[i = 0] = getcpy (current); 222: mp -> msgattrs[++i] = NULL; 223: mp -> attrstats = 0; /* initially, all public */ 224: 225: m_getdefs (); 226: if (mh_seq == NULL || *mh_seq == NULL) 227: goto private_only; 228: 229: (void) sprintf (field, "%s/%s", mp -> foldpath, mh_seq); 230: if (fp = fopen (field, "r")) { 231: for (state = FLD;;) { 232: switch (state = m_getfld (state, name, field, sizeof field, fp)) { 233: case FLD: 234: case FLDEOF: 235: (void) m_setatr (mp, getcpy (name), trimcpy (field)); 236: if (state == FLDEOF) 237: break; 238: continue; 239: 240: case BODY: 241: case BODYEOF: 242: adios (NULLCP, 243: "no blank lines are permitted in %s/%s", 244: mp -> foldpath, mh_seq);/* fall */ 245: 246: case FILEEOF: 247: break; 248: 249: default: 250: adios (NULLCP, "%s/%s is poorly formatted", 251: mp -> foldpath, mh_seq); 252: } 253: break; 254: } 255: (void) fclose (fp); 256: } 257: 258: private_only: ; 259: alen = strlen ("atr-"); 260: plen = strlen (mp -> foldpath) + 1; 261: 262: for (np = m_defs; np; np = np -> n_next) 263: if (ssequal ("atr-", np -> n_name) 264: && (j = strlen (np -> n_name) - plen) > alen 265: && *(np -> n_name + j) == '-' 266: && strcmp (mp -> foldpath, np -> n_name + j + 1) == 0) { 267: cp = getcpy (np -> n_name + alen); 268: *(cp + j - alen) = NULL; 269: if ((i = m_setatr (mp, cp, getcpy (np -> n_field))) != NOTOK) 270: mp -> attrstats |= 1 << (bits + i);/* private */ 271: } 272: } 273: 274: /* */ 275: 276: static int m_setatr (mp, name, field) 277: register struct msgs *mp; 278: register char *name, 279: *field; 280: { 281: int bits, 282: hack; 283: register int i, 284: j, 285: k; 286: register char *cp, 287: **ap; 288: 289: bits = FFATTRSLOT; 290: hack = strcmp (current, name) == 0;/* hack... */ 291: 292: for (i = 0; mp -> msgattrs[i]; i++) 293: if (strcmp (mp -> msgattrs[i], name) == 0) { 294: for (j = mp -> lowmsg; j <= mp -> hghmsg; j++) 295: mp -> msgstats[j] &= ~(1 << (bits + i)); 296: break; 297: } 298: if (i >= NATTRS) { 299: free (name); 300: free (field); 301: return NOTOK; 302: } 303: 304: if (mp -> msgattrs[i] == NULL) { 305: mp -> msgattrs[i] = name; 306: mp -> msgattrs[i + 1] = NULL; 307: } 308: else 309: free (name); 310: 311: for (ap = brkstring (field, " ", "\n"); 312: *ap; 313: ap++) { 314: if (cp = index (*ap, '-')) 315: *cp++ = NULL; 316: if ((j = m_atoi (*ap)) > 0) { 317: #ifdef notdef 318: if (hack && j >= mp -> lowmsg && j <= mp -> hghmsg 319: && (mp -> msgstats[j] & EXISTS)) 320: mp -> curmsg = j; 321: #else not notdef 322: if (hack) 323: mp -> curmsg = j; 324: #endif not notdef 325: for (k = cp ? m_atoi (cp) : j; j <= k; j++) 326: if (j >= mp -> lowmsg && j <= mp -> hghmsg 327: && (mp -> msgstats[j] & EXISTS)) 328: mp -> msgstats[j] |= 1 << (bits + i); 329: } 330: } 331: free (field); 332: 333: return i; 334: }