⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imap4d.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
fetchCmd(char *tg, char *cmd){	fetchUCmd(tg, cmd, 0);}static voidfetchUCmd(char *tg, char *cmd, int uids){	Fetch *f;	MsgSet *ms;	MbLock *ml;	char *uid;	ulong max;	int ok;	mustBe(' ');	ms = msgSet(uids);	mustBe(' ');	f = fetchWhat();	crnl();	uid = "";	if(uids)		uid = "uid ";	max = selected->max;	ml = checkBox(selected, 1);	if(ml != nil)		forMsgs(selected, ms, max, uids, fetchSeen, f);	closeImp(selected, ml);	ok = ml != nil && forMsgs(selected, ms, max, uids, fetchMsg, f);	status(uids, uids);	if(ok)		Bprint(&bout, "%s OK %s%s completed\r\n", tg, uid, cmd);	else		Bprint(&bout, "%s NO %s%s failed\r\n", tg, uid, cmd);}static voididleCmd(char *tg, char *cmd){	int c, pid;	crnl();	Bprint(&bout, "+ idling, waiting for done\r\n");	if(Bflush(&bout) < 0)		writeErr();	if(idlepid < 0){		pid = rfork(RFPROC|RFMEM|RFNOWAIT);		if(pid == 0){			for(;;){				qlock(&imaplock);				if(exiting)					break;				/*				 * parent may have changed curDir, but it doesn't change our .				 */				resetCurDir();				check();				if(Bflush(&bout) < 0)					writeErr();				qunlock(&imaplock);				sleep(15*1000);				enableForwarding();			}_exits("rob3");			_exits(0);		}		idlepid = pid;	}	qunlock(&imaplock);	/*	 * clear out the next line, which is supposed to contain (case-insensitive)	 * done\n	 * this is special code since it has to dance with the idle polling proc	 * and handle exiting correctly.	 */	for(;;){		c = getc();		if(c < 0){			qlock(&imaplock);			if(!exiting)				cleaner();_exits("rob4");			_exits(0);		}		if(c == '\n')			break;	}	qlock(&imaplock);	if(exiting){_exits("rob5");		_exits(0);}	/*	 * child may have changed curDir, but it doesn't change our .	 */	resetCurDir();	check();	Bprint(&bout, "%s OK %s terminated\r\n", tg, cmd);}static voidlistCmd(char *tg, char *cmd){	char *s, *t, *ss, *ref, *mbox;	int n;	mustBe(' ');	s = astring();	mustBe(' ');	t = listmbox();	crnl();	check();	ref = mutf7str(s);	mbox = mutf7str(t);	if(ref == nil || mbox == nil){		Bprint(&bout, "%s BAD %s mailbox name not in modified utf-7\r\n", tg, cmd);		return;	}	/*	 * special request for hierarchy delimiter and root name	 * root name appears to be name up to and including any delimiter,	 * or the empty string, if there is no delimiter.	 *	 * this must change if the # namespace convention is supported.	 */	if(*mbox == '\0'){		s = strchr(ref, '/');		if(s == nil)			ref = "";		else			s[1] = '\0';		Bprint(&bout, "* %s (\\Noselect) \"/\" \"%s\"\r\n", cmd, ref);		Bprint(&bout, "%s OK %s\r\n", tg, cmd);		return;	}	/*	 * massage the listing name:	 * clean up the components individually,	 * then rip off componenets from the ref to	 * take care of leading ..'s in the mbox.	 *	 * the cleanup can wipe out * followed by a ..	 * tough luck if such a stupid pattern is given.	 */	cleanname(mbox);	if(strcmp(mbox, ".") == 0)		*mbox = '\0';	if(mbox[0] == '/')		*ref = '\0';	else if(*ref != '\0'){		cleanname(ref);		if(strcmp(ref, ".") == 0)			*ref = '\0';	}else		*ref = '\0';	while(*ref && isdotdot(mbox)){		s = strrchr(ref, '/');		if(s == nil)			s = ref;		if(isdotdot(s))			break;		*s = '\0';		mbox += 2;		if(*mbox == '/')			mbox++;	}	if(*ref == '\0'){		s = mbox;		ss = s;	}else{		n = strlen(ref) + strlen(mbox) + 2;		t = binalloc(&parseBin, n, 0);		if(t == nil)			parseErr("out of memory");		snprint(t, n, "%s/%s", ref, mbox);		s = t;		ss = s + strlen(ref);	}	/*	 * only allow activity in /mail/box	 */	if(s[0] == '/' || isdotdot(s)){		Bprint(&bout, "%s NO illegal mailbox pattern\r\n", tg);		return;	}	if(cistrcmp(cmd, "lsub") == 0)		lsubBoxes(cmd, s, ss);	else		listBoxes(cmd, s, ss);	Bprint(&bout, "%s OK %s completed\r\n", tg, cmd);}static char*passCR(char*u, char*p){	static char Ebadch[] = "can't get challenge";	static char nchall[64];	static char response[64];	static Chalstate *ch = nil;	AuthInfo *ai;again:	if (ch == nil){		if(!(ch = auth_challenge("proto=p9cr role=server user=%q", u)))			return Ebadch;		snprint(nchall, 64, " encrypt challenge: %s", ch->chal);		return nchall;	} else {		strncpy(response, p, 64);		ch->resp = response;		ch->nresp = strlen(response);		ai = auth_response(ch);		auth_freechal(ch);		ch = nil;		if (ai == nil)			goto again;		setupuser(ai);		return nil;	}		}static voidloginCmd(char *tg, char *cmd){	char *s, *t;	AuthInfo *ai;	char*r;	mustBe(' ');	s = astring();	/* uid */	mustBe(' ');	t = astring();	/* password */	crnl();	if(allowCR){		if ((r = passCR(s, t)) == nil){			Bprint(&bout, "%s OK %s succeeded\r\n", tg, cmd);			imapState = SAuthed;		} else {			Bprint(&bout, "* NO [ALERT] %s\r\n", r);			Bprint(&bout, "%s NO %s succeeded\r\n", tg, cmd);		}		return;	}	else if(allowPass){		if(ai = passLogin(s, t)){			setupuser(ai);			Bprint(&bout, "%s OK %s succeeded\r\n", tg, cmd);			imapState = SAuthed;		}else			Bprint(&bout, "%s NO %s failed check\r\n", tg, cmd);		return;	}	Bprint(&bout, "%s NO %s plaintext passwords disallowed\r\n", tg, cmd);}/* * logout or x-exit, which doesn't expunge the mailbox */static voidlogoutCmd(char *tg, char *cmd){	crnl();	if(cmd[0] != 'x' && selected){		closeBox(selected, 1);		selected = nil;	}	Bprint(&bout, "* bye\r\n");	Bprint(&bout, "%s OK %s completed\r\n", tg, cmd);exits("rob6");	exits(0);}static voidnamespaceCmd(char *tg, char *cmd){	crnl();	check();	/*	 * personal, other users, shared namespaces	 * send back nil or descriptions of (prefix heirarchy-delim) for each case	 */	Bprint(&bout, "* NAMESPACE ((\"\" \"/\")) nil nil\r\n");	Bprint(&bout, "%s OK %s completed\r\n", tg, cmd);}static voidnoopCmd(char *tg, char *cmd){	crnl();	check();	Bprint(&bout, "%s OK %s completed\r\n", tg, cmd);	enableForwarding();}/* * this is only a partial implementation * should copy files to other directories, * and copy & truncate inbox */static voidrenameCmd(char *tg, char *cmd){	char *from, *to;	int ok;	mustBe(' ');	from = astring();	mustBe(' ');	to = astring();	crnl();	check();	to = mboxName(to);	if(to == nil || !okMbox(to) || cistrcmp(to, "inbox") == 0){		Bprint(&bout, "%s NO %s bad mailbox destination name\r\n", tg, cmd);		return;	}	if(access(to, AEXIST) >= 0){		Bprint(&bout, "%s NO %s mailbox already exists\r\n", tg, cmd);		return;	}	from = mboxName(from);	if(from == nil || !okMbox(from)){		Bprint(&bout, "%s NO %s bad mailbox destination name\r\n", tg, cmd);		return;	}	if(cistrcmp(from, "inbox") == 0)		ok = copyBox(from, to, 0);	else		ok = moveBox(from, to);	if(ok)		Bprint(&bout, "%s OK %s completed\r\n", tg, cmd);	else		Bprint(&bout, "%s NO %s failed\r\n", tg, cmd);}static voidsearchCmd(char *tg, char *cmd){	searchUCmd(tg, cmd, 0);}static voidsearchUCmd(char *tg, char *cmd, int uids){	Search rock;	Msg *m;	char *uid;	ulong id;	mustBe(' ');	rock.next = nil;	searchKeys(1, &rock);	crnl();	uid = "";	if(uids)		uid = "uid ";	if(rock.next != nil && rock.next->key == SKCharset){		if(cistrstr(rock.next->s, "utf-8") != 0		&& cistrcmp(rock.next->s, "us-ascii") != 0){			Bprint(&bout, "%s NO [BADCHARSET] (\"US-ASCII\" \"UTF-8\") %s%s failed\r\n", tg, uid, cmd);			checkBox(selected, 0);			status(uids, uids);			return;		}		rock.next = rock.next->next;	}	Bprint(&bout, "* search");	for(m = selected->msgs; m != nil; m = m->next)		m->matched = searchMsg(m, rock.next);	for(m = selected->msgs; m != nil; m = m->next){		if(m->matched){			if(uids)				id = m->uid;			else				id = m->seq;			Bprint(&bout, " %lud", id);		}	}	Bprint(&bout, "\r\n");	checkBox(selected, 0);	status(uids, uids);	Bprint(&bout, "%s OK %s%s completed\r\n", tg, uid, cmd);}static voidselectCmd(char *tg, char *cmd){	Msg *m;	char *s, *mbox;	mustBe(' ');	mbox = astring();	crnl();	if(selected){		imapState = SAuthed;		closeBox(selected, 1);		selected = nil;	}	mbox = mboxName(mbox);	if(mbox == nil || !okMbox(mbox)){		Bprint(&bout, "%s NO %s bad mailbox\r\n", tg, cmd);		return;	}	selected = openBox(mbox, "imap", cistrcmp(cmd, "select") == 0);	if(selected == nil){		Bprint(&bout, "%s NO %s can't open mailbox %s: %r\r\n", tg, cmd, mbox);		return;	}	imapState = SSelected;	Bprint(&bout, "* FLAGS (\\Seen \\Answered \\Flagged \\Deleted \\Draft)\r\n");	Bprint(&bout, "* %lud EXISTS\r\n", selected->max);	selected->toldMax = selected->max;	Bprint(&bout, "* %lud RECENT\r\n", selected->recent);	selected->toldRecent = selected->recent;	for(m = selected->msgs; m != nil; m = m->next){		if(!m->expunged && (m->flags & MSeen) != MSeen){			Bprint(&bout, "* OK [UNSEEN %ld]\r\n", m->seq);			break;		}	}	Bprint(&bout, "* OK [PERMANENTFLAGS (\\Seen \\Answered \\Flagged \\Draft \\Deleted)]\r\n");	Bprint(&bout, "* OK [UIDNEXT %ld]\r\n", selected->uidnext);	Bprint(&bout, "* OK [UIDVALIDITY %ld]\r\n", selected->uidvalidity);	s = "READ-ONLY";	if(selected->writable)		s = "READ-WRITE";	Bprint(&bout, "%s OK [%s] %s %s completed\r\n", tg, s, cmd, mbox);}static NamedInt	statusItems[] ={	{"MESSAGES",	SMessages},	{"RECENT",	SRecent},	{"UIDNEXT",	SUidNext},	{"UIDVALIDITY",	SUidValidity},	{"UNSEEN",	SUnseen},	{nil,		0}};static voidstatusCmd(char *tg, char *cmd){	Box *box;	Msg *m;	char *s, *mbox;	ulong v;	int si, i;	mustBe(' ');	mbox = astring();	mustBe(' ');	mustBe('(');	si = 0;	for(;;){		s = atom();		i = mapInt(statusItems, s);		if(i == 0)			parseErr("illegal status item");		si |= i;		if(peekc() == ')')			break;		mustBe(' ');	}	mustBe(')');	crnl();	mbox = mboxName(mbox);	if(mbox == nil || !okMbox(mbox)){		check();		Bprint(&bout, "%s NO %s bad mailbox\r\n", tg, cmd);		return;	}	box = openBox(mbox, "status", 1);	if(box == nil){		check();		Bprint(&bout, "%s NO [TRYCREATE] %s can't open mailbox %s: %r\r\n", tg, cmd, mbox);		return;	}	Bprint(&bout, "* STATUS (");	s = "";	for(i = 0; statusItems[i].name != nil; i++){		if(si & statusItems[i].v){			v = 0;			switch(statusItems[i].v){			case SMessages:				v = box->max;				break;			case SRecent:				v = box->recent;				break;			case SUidNext:				v = box->uidnext;				break;			case SUidValidity:				v = box->uidvalidity;				break;			case SUnseen:				v = 0;				for(m = box->msgs; m != nil; m = m->next)					if((m->flags & MSeen) != MSeen)						v++;				break;			default:				Bprint(&bout, ")");				bye("internal error: status item not implemented");				break;			}			Bprint(&bout, "%s%s %lud", s, statusItems[i].name, v);			s = " ";		}	}	Bprint(&bout, ")\r\n");	closeBox(box, 1);	check();	Bprint(&bout, "%s OK %s completed\r\n", tg, cmd);}static voidstoreCmd(char *tg, char *cmd){	storeUCmd(tg, cmd, 0);}static voidstoreUCmd(char *tg, char *cmd, int uids){	Store *st;	MsgSet *ms;	MbLock *ml;	char *uid;	ulong max;	int ok;	mustBe(' ');	ms = msgSet(uids);	mustBe(' ');	st = storeWhat();	crnl();	uid = "";	if(uids)		uid = "uid ";	max = selected->max;	ml = checkBox(selected, 1);	ok = ml != nil && forMsgs(selected, ms, max, uids, storeMsg, st);	closeImp(selected, ml);	status(uids, uids);	if(ok)		Bprint(&bout, "%s OK %s%s completed\r\n", tg, uid, cmd);	else		Bprint(&bout, "%s NO %s%s failed\r\n", tg, uid, cmd);}/* * minimal implementation of subscribe * all folders are automatically subscribed, * and can't be unsubscribed */static voidsubscribeCmd(char *tg, char *cmd){	Box *box;	char *mbox;	int ok;	mustBe(' ');	mbox = astring();	crnl();	check();	mbox = mboxName(mbox);	ok = 0;	if(mbox != nil && okMbox(mbox)){		box = openBox(mbox, "subscribe", 0);		if(box != nil){			ok = subscribe(mbox, 's');			closeBox(box, 1);		}	}	if(!ok)		Bprint(&bout, "%s NO %s bad mailbox\r\n", tg, cmd);	else		Bprint(&bout, "%s OK %s completed\r\n", tg, cmd);}static voiduidCmd(char *tg, char *cmd){	char *sub;	mustBe(' ');	sub = atom();	if(cistrcmp(sub, "copy") == 0)		copyUCmd(tg, sub, 1);	else if(cistrcmp(sub, "fetch") == 0)		fetchUCmd(tg, sub, 1);	else if(cistrcmp(sub, "search") == 0)		searchUCmd(tg, sub, 1);	else if(cistrcmp(sub, "store") == 0)		storeUCmd(tg, sub, 1);	else{		clearcmd();		Bprint(&bout, "%s BAD %s illegal uid command %s\r\n", tg, cmd, sub);	}}static voidunsubscribeCmd(char *tg, char *cmd){	char *mbox;	mustBe(' ');	mbox = astring();	crnl();	check();	mbox = mboxName(mbox);	if(mbox == nil || !okMbox(mbox) || !subscribe(mbox, 'u'))		Bprint(&bout, "%s NO %s can't unsubscribe\r\n", tg, cmd);	else		Bprint(&bout, "%s OK %s completed\r\n", tg, cmd);}static voidbadsyn(void){	parseErr("bad syntax");}static voidclearcmd(void){	int c;	for(;;){		c = getc();		if(c < 0)			bye("end of input");		if(c == '\n')			return;	}}static voidcrnl(void){	int c;	c = getc();	if(c == '\n')		return;	if(c != '\r' || getc() != '\n')		badsyn();}static voidmustBe(int c){	if(getc() != c){		ungetc();		badsyn();	}}/* * flaglist	: '(' ')' | '(' flags ')' */static intflagList(void){	int f;	mustBe('(');	f = 0;	if(peekc() != ')')		f = flags();	mustBe(')');

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -