1: #include "parms.h" 2: #include "structs.h" 3: #include <sys/types.h> 4: #include <sys/stat.h> 5: 6: #ifdef RCSIDENT 7: static char rcsid[] = "$Header: buildnf.c,v 1.7.0.2 86/05/22 11:19:09 notes Rel $"; 8: #endif RCSIDENT 9: 10: /* 11: * buildnf 12: * 13: * A subroutine which creates notesfiles. Given the (1) name of 14: * the new notesfile and (2) the anonymous, open, and 15: * networked flags this routine will create a new notesfile, 16: * provided that it does not exist already. 17: * 18: * This routine will blindly create the notesfile. It does not 19: * check the real uid to see if it should create a notesfile or 20: * not. 21: * 22: * Returns: 0 Notesfile created 23: * -1 Error in notesfile creation 24: * -2 Notesfile exists 25: * 26: * Extracted from old "mknf" mainline. Modified mknf so it 27: * calls this routine. 28: * Also put conditional code into newsinput.c to create the 29: * new notesfile if desired. 30: * 31: * Original Coding: Ray Essick October 13, 1982 32: */ 33: #define N_UMASK 0 /* when making nf's */ 34: 35: buildnf (nfname, basedir, Aflag, Oflag, Nflag) 36: char *nfname; 37: char *basedir; /* nf directory */ 38: int Aflag, 39: Oflag, 40: Nflag; 41: { 42: struct io_f io; 43: char *p; /* misc. pointer */ 44: int i; /* misc counter */ 45: int fid; /* misc file id */ 46: struct daddr_f freetext; /* for writing */ 47: struct descr_f descr; /* for writing, too */ 48: struct perm_f perms[NPERMS]; 49: struct perm_f pentry; /* single entry */ 50: struct auth_f me; /* for access list */ 51: char cmdline[WDLEN]; /* for mkdir */ 52: char pathname[WDLEN]; /* for filenames */ 53: char filename[WDLEN]; /* for filenames */ 54: FILE * seqfile; 55: FILE * pfile; /* access list mods */ 56: struct stat statval; /* testing existence */ 57: unsigned short restoremode; 58: int old_umask; /* save his mask */ 59: 60: if (chkpath (nfname)) 61: { 62: printf ("Invalid notesfile name: `%s'\n", nfname); 63: return (-1); /* bad return */ 64: } 65: 66: if (stat (basedir, &statval) == -1) /* can we read basedir? */ 67: { 68: printf ("can't stat (assumed directory) %s\n", basedir); 69: return (-1); /* error in creation */ 70: } 71: 72: sprintf (pathname, "%s/%s", basedir, nfname); 73: if (stat (pathname, &statval) == 0) /* check existence */ 74: { 75: printf ("Notesfile already exists\n"); 76: /* 77: * Could talk about whether it's a file or directory... 78: * but probably not worth it. 79: */ 80: return (-2); /* already exists */ 81: } 82: 83: old_umask = umask (N_UMASK); /* clear mask */ 84: #ifdef BSD42 85: { 86: /* 87: * take advantage of 4.2 bsd system call... 88: */ 89: mkdir (pathname, 0770); /* make the directory */ 90: } 91: #else 92: { 93: /* 94: * do it the hard way ... by forking children 95: */ 96: #ifdef USG 97: /* 98: * make sure we can create the directory; restore it later 99: */ 100: if (stat (basedir, &statval) == 0) 101: restoremode = statval.st_mode; 102: else 103: restoremode = 0775; 104: chmod (basedir, 0777); 105: #else 106: /* 107: * under non-USG boxes, we can do setuid(geteuid()) and have it 108: * make the real uid match the effective uid 109: */ 110: globuid = Notesuid; /* must be notes to work */ 111: #endif USG 112: 113: #ifndef FASTFORK 114: sprintf (cmdline, "mkdir %s", pathname); /* build command */ 115: dounix (cmdline, 1, 0); /* execute, captain */ 116: #ifdef USG 117: /* 118: * fix owner on USG boxes where setuid(geteuid()) doesn't do 119: * what it does on V7 and BSd boxes (set both to the effective) 120: */ 121: sprintf (cmdline, "chgrp %s %s", NOTESGRP, pathname);/* fix group */ 122: dounix (cmdline, 1, 0); 123: sprintf (cmdline, "chown %s %s", NOTES, pathname);/* fix owner */ 124: dounix (cmdline, 1, 0); 125: #endif USG 126: #else 127: dounix (1, 0, "/bin/mkdir", pathname, 0, 0, 0); 128: #ifdef USG 129: /* 130: * atone for the USG behavior of setuid(geteuid()) 131: */ 132: dounix (1, 0, "/bin/chgrp", NOTESGRP, pathname, 0, 0); 133: dounix (1, 0, "/bin/chown", NOTES, pathname, 0, 0); 134: #endif USG 135: #endif FASTFORK 136: /* 137: * done making things. set the right permissions on 138: * basedir (if we screwed with it) and pathname. 139: */ 140: #ifdef USG 141: chmod (basedir, restoremode); 142: #endif USG 143: chmod (pathname, 0770); 144: } 145: #endif BSD42 146: 147: /* 148: * Now build the files within the directory 149: * Build a default notesfile descriptor and then override with 150: * his specific values. 151: */ 152: 153: 154: initdescr (&descr); /* make default */ 155: 156: glocknf (&io, SEQLOCK); /* grab sequence # */ 157: sprintf (cmdline, "%s/%s", Mstdir, SEQ); 158: x ((seqfile = fopen (cmdline, "r")) == NULL, "mknf: open unique"); 159: x (fscanf (seqfile, "%d", &i) != 1, "mknf: unique read"); 160: descr.d_nfnum = i++; 161: fclose (seqfile); /* close it and */ 162: x ((seqfile = fopen (cmdline, "w")) == NULL, "mknf: reopen unique"); 163: fprintf (seqfile, "%d\n", i); /* update */ 164: fclose (seqfile); 165: gunlocknf (&io, SEQLOCK); /* release file */ 166: 167: strncpy (descr.d_title, nfname, NNLEN); 168: descr.d_title[NNLEN - 1] = '\0'; /* null it */ 169: 170: if (Aflag) /* he wants anon */ 171: descr.d_stat |= ANONOK; 172: if (Oflag) /* open */ 173: descr.d_stat |= OPEN; 174: if (Nflag) /* networkable */ 175: descr.d_stat |= NETWRKD; 176: 177: 178: sprintf (filename, "%s/%s", pathname, INDEXN); /* make the file */ 179: x ((fid = creat (filename, 0660)) < 0, "build: Cant create note.indx"); 180: x (write (fid, &descr, sizeof descr) != sizeof descr, 181: "build: Cant write note.indx"); 182: x (close (fid) < 0, "build: bad note.indx close"); 183: 184: /* 185: * Now create the text file 186: */ 187: 188: sprintf (filename, "%s/%s", pathname, TEXT); 189: x ((fid = creat (filename, 0660)) < 0, "build: Cant create text"); 190: freetext.addr = sizeof freetext; /* past address slot */ 191: if (freetext.addr & 1) /* odd (shouldn't be) */ 192: freetext.addr++; /* make it even */ 193: x (write (fid, &freetext, sizeof freetext) != sizeof freetext, 194: "build: Cant write text"); 195: 196: x (close (fid) < 0, "build: bad text close"); 197: 198: /* 199: * Now the response index file. 200: */ 201: 202: sprintf (filename, "%s/%s", pathname, INDEXR); 203: x ((fid = creat (filename, 0660)) < 0, "build: Cant create resp.indx"); 204: i = 0; /* resp 0 slot free */ 205: x (write (fid, &i, sizeof i) != sizeof i, "build: Cant write resp.indx"); 206: x (close (fid) < 0, "build: bad close of resp.indx"); 207: 208: /* 209: * Build the access list. This is a two phase operation. 210: * The first phase builds a default access list. This 211: * is set up with one director (the notes signon) and 212: * a group "Other" with read/write. System "Other" also 213: * has read/write privileges. This is basically a wide-open 214: * policy. 215: * The second phase is customization. This step uses the 216: * contents of the file ..../notes/.utilities/access-template 217: * as a batch of access specifications (like nfaccess) 218: * to add/modify specific permissions. 219: */ 220: 221: sprintf (filename, "%s/%s", pathname, ACCESS); /* build simple */ 222: x ((fid = creat (filename, 0660)) < 0, "build: couldnt create access"); 223: getname (&me, 0); /* grab "notes" */ 224: perms[0].ptype = PERMUSER; 225: strcpy (perms[0].name, me.aname); 226: perms[0].perms = READOK + WRITOK + RESPOK + DRCTOK; 227: perms[1].ptype = PERMGROUP; 228: strcpy (perms[1].name, "Other"); 229: perms[1].perms = DFLTPERMS; 230: perms[2].ptype = PERMSYSTEM; 231: strcpy (perms[2].name, "Other"); 232: perms[2].perms = DFLTPERMS; 233: 234: x (write (fid, perms, 3 * sizeof pentry) != 3 * sizeof pentry, 235: "build: bad access write"); 236: x (close (fid) < 0, "build: close access broke"); 237: 238: /* 239: * Now, process any extra specifications from utilities/access-template 240: * Don't do anything unless the file exists. 241: */ 242: 243: sprintf (filename, "%s/%s/%s-template", Mstdir, UTILITY, ACCESS); 244: if ((pfile = fopen (filename, "r")) != NULL) 245: { 246: char pline[BUFSIZ]; 247: int nmodes, 248: zapindex; 249: 250: 251: nmodes = 0; /* load perms[] */ 252: while (fgets (pline, sizeof pline, pfile) != NULL) 253: { 254: if (pline[0] == '#') /* comment */ 255: continue; 256: if (nmodes == NPERMS) /* full list */ 257: break; 258: zapindex = strlen (pline); 259: if (pline[zapindex] == '\n') 260: pline[zapindex] = '\0'; /* zap newline */ 261: if (parsemode (pline, &perms[nmodes], 0) == 0)/* worked? */ 262: nmodes++; /* bump counter */ 263: } 264: fclose (pfile); /* done with template */ 265: if (init (&io, pathname) >= 0) /* open the nf */ 266: { 267: addmodes (&io, nmodes, perms, 0); /* add them */ 268: closenf (&io); 269: } 270: } 271: 272: x (umask (old_umask) != N_UMASK, "buildnf: reset umask");/* restore umask */ 273: return 0; /* all's well */ 274: } 275: 276: /* 277: * initdescr(&descr_f) 278: * 279: * Load a descriptor with a lot of default information 280: * Other people will load things like titles and specific 281: * values of flags. 282: */ 283: 284: initdescr (descr) 285: struct descr_f *descr; 286: { 287: register int i; 288: register char *p; 289: 290: descr -> d_format = DBVERSION; /* version */ 291: strcpy (descr -> d_title, "** Notesfile Title **"); 292: strcpy (descr -> d_drmes, "** director message **"); 293: descr -> d_plcy = 0; /* no policy note */ 294: descr -> d_id.uniqid = 0; /* unique within nf */ 295: strcpy (descr -> d_id.sys, System); /* and system name */ 296: 297: gettime (&descr -> d_lstxmit); /* last network xmit */ 298: gettime (&descr -> d_lastm); /* last modified now */ 299: gettime (&descr -> d_created); /* creation date */ 300: gettime (&descr -> d_lastuse); /* for days online */ 301: descr -> d_daysused = 1; /* count making it ! */ 302: descr -> d_stat = 0; /* no special status */ 303: descr -> d_nnote = 0; /* no notes in file */ 304: descr -> d_delnote = descr -> d_delresp = 0; /* no holes */ 305: descr -> d_archtime = 0; /* default time */ 306: descr -> d_workset = 0; /* working set */ 307: descr -> d_archkeep = KEEPDFLT; /* keep/delete */ 308: descr -> d_dmesgstat = DIRDFLT; /* dirmsg to expire */ 309: 310: descr -> d_rspwrit = descr -> d_notwrit = 0; /* initialize stats */ 311: descr -> d_rspread = descr -> d_notread = 0; 312: descr -> d_notdrop = descr -> d_rspdrop = 0; 313: descr -> d_orphans = 0; /* orphan chains */ 314: descr -> d_adopted = 0; /* chains adopted */ 315: descr -> entries = 0; /* user entries */ 316: descr -> walltime = 0; 317: descr -> d_rspxmit = descr -> d_notxmit = 0; /* network activity */ 318: descr -> d_rsprcvd = descr -> d_notrcvd = 0; 319: descr -> netwrkouts = descr -> netwrkins = 0; 320: descr -> d_longnote = MAXMSG; /* longest permitted */ 321: }