Annotation of capa/capa51/pProj/capaCommon.c, revision 1.1.1.1
1.1 albertel 1: /* =||>|===================== capaCommon.c =====================|<||= */
2: /* created 1994 by Isaac Tsai */
3: /* 1994, 1995, 1996, 1997, 1998, 1999 copyrighted by Isaac Tsai */
4: /* TODO: restructure capa_check_ans*() calls into one */
5: /* =||>|===================== capaCommon.c =====================|<||= */
6: #include <ctype.h>
7: #if defined(__sun) || defined(linux) || defined(__alpha) || defined(hpux) || defined(AIX) || defined(IRIX)
8: #include <unistd.h> /* lockf() */
9: #endif
10: #include <sys/types.h>
11: #include <sys/stat.h>
12: #include <fcntl.h>
13: #include "capaParser.h"
14: #include "capaToken.h"
15: #include "capaCommon.h"
16: #include "ranlib.h"
17:
18:
19: /*----------------------------------------------------------*/
20: /* flock() in SUN is in BSD compatibility lib */
21: /* #include <sys/file.h> */
22: /*----------------------------------------------------------*/
23:
24: int yyparse();
25: extern FILE *yyin;
26: extern void yyrestart();
27:
28: /*----------------------------------------------------------*/
29: /* RETURN: -1 file error */
30: /* 0 success */
31: /* INPUT: if section == 0, for all students in class */
32: /* set : 1, 2, 3, ... */
33: /* prob: 1, 2, 3, ... */
34: /*----------------------------------------------------------*/
35: int
36: capa_excuse(int set,int prob,int section)
37: {
38: int nq;
39: T_header header;
40: T_entry entry;
41: T_student *student_p, *s1_p;
42: char tmp_number[MAX_STUDENT_NUMBER+1];
43: long offset;
44: int num_students;
45:
46: /* Calculate parameters */
47: if (capa_get_header(&header,set)) return (-1);
48: sscanf(header.num_questions,"%d", &nq);
49: capa_mfree(header.weight);
50: capa_mfree(header.partial_credit);
51:
52: if( ( prob > nq ) || (section < 0 ) || (section > MAX_SECTION_COUNT) ) return (-1);
53: num_students= 0;
54: if ( (num_students = capa_get_section(&student_p, section))== -1 ) return (-1);
55: for ( s1_p = student_p ; s1_p ; s1_p = (s1_p->s_next)) {
56: sprintf(tmp_number,"%s",s1_p->s_sn);
57: offset = capa_get_entry(&entry,tmp_number,set);
58: if(offset < 0 ) offset = -offset;
59: switch(entry.answers[prob-1]) {
60: case '-': entry.answers[prob-1] = 'E'; break;
61: case 'N': entry.answers[prob-1] = 'E'; break;
62: case 'n': entry.answers[prob-1] = 'e'; break;
63: default : break;
64: }
65: capa_set_entry(&entry,tmp_number,set,offset);
66: capa_mfree(entry.answers); entry.answers = NULL;
67: capa_mfree(entry.tries); entry.tries = NULL;
68: }
69: free_students(student_p);
70: return (0);
71: }
72:
73: /*----------------------------------------------------------*/
74: /* Lock file shared */
75: /* lock the file specified by file stream pointer sp */
76: /*----------------------------------------------------------*/
77: int
78: flockstream_sh(sp) FILE *sp;
79: {
80: int fd;
81:
82: fd = fileno(sp);
83:
84: #if defined(__sun) || defined(hpux) || defined(AIX)
85: return ( lockf(fd,F_LOCK, 0L) );
86: #else
87: return (flock(fd,LOCK_SH));
88: #endif
89: }
90: /*----------------------------------------------------------*/
91: int
92: flockstream(sp) FILE *sp;
93: {
94: int fd;
95:
96: fd = fileno(sp);
97:
98: #if defined(__sun) || defined(hpux) || defined(AIX)
99: return ( lockf(fd,F_LOCK, 0L) );
100: #else
101: return (flock(fd,LOCK_EX));
102: #endif
103: }
104: /*----------------------------------------------------------*/
105: int
106: funlockstream(sp) FILE *sp;
107: {
108: int fd;
109:
110: fd = fileno(sp);
111:
112: #if defined(__sun) || defined(hpux) || defined(AIX)
113: return ( lockf(fd,F_ULOCK, 0L) );
114: #else
115: return ( flock(fd,LOCK_UN) );
116: #endif
117: }
118:
119: int
120: inquery_a_lock(sp,cmd,type,offset,whence,len)
121: FILE *sp;int cmd;off_t offset;int whence;off_t len;
122: {
123: struct flock lock;
124: int fd;
125: lock.l_type = type; lock.l_start = offset;
126: lock.l_whence = whence; lock.l_len = len;
127: fd=fileno(sp);
128: return (fcntl(fd,cmd,&lock));
129: }
130: #define Blocked_Write_Lock(sp) \
131: inquery_a_lock(sp,F_SETLK,F_WRLCK,0,0,0)
132:
133: #define Blocked_Write_Lock(sp) \
134: inquery_a_lock(sp,F_SETLK,F_WRLCK,0,0,0)
135:
136: #define Un_Lock(sp) \
137: inquery_a_lock(sp,F_SETLK,F_UNLCK,0,0,0)
138:
139:
140: /*----------------------------------------------------------*/
141: /* INPUT: set problem set number */
142: /* RETURN: -1 no records/setX.db file or file error */
143: /* 0 success */
144: /* OUTPUT: header pointer to T_header structure */
145: /*----------------------------------------------------------*/
146: int
147: capa_set_header(header, set) T_header *header;int set;
148: {
149: FILE *fp;
150: char *big_buf=NULL, filename[FILE_NAME_LENGTH], cr=0, oneline[TMP_LINE_LENGTH];
151: int nq, len, errcode, fd, item_cnt, exists=1;
152: T_header oldheader;
153: long orig_size, new_size, big_buf_size;
154:
155: sprintf(filename,"records/set%d.db",set);
156: if ((fp=fopen(filename,"r+"))==NULL) {
157: exists=0;
158: if ((fp=fopen(filename,"w"))==NULL) { /* create if non-existant */
159: /*printf("Error: can't open %s\n",filename);*/ return (-1);
160: }
161: }
162: sscanf(header->num_questions,"%d",&nq);
163: /* sprintf(oneline,"%d,%s,%s,%s\n",nq,header->open_date,header->due_date,header->answer_date); */
164: sprintf(oneline,"%d\n",nq);
165: len = strlen(oneline);
166: flockstream(fp); errcode = 0;
167:
168: if (exists) {
169: /*get file size*/
170: fseek(fp,0L,SEEK_END);
171: orig_size = ftell(fp);
172: big_buf_size = orig_size; /*the amt we need to read is less then the file's size*/
173: big_buf = capa_malloc(big_buf_size,1);
174: fseek(fp,0L,SEEK_SET);
175:
176: /*read in old header*/
177: fscanf(fp,"%d",&nq);
178: while ( cr != '\n' && cr != EOF ) { cr=fgetc(fp); }
179: oldheader.weight=capa_malloc(nq+1,1);
180: oldheader.partial_credit=capa_malloc(nq+1,1);
181: if (!fread(oldheader.weight, sizeof(char), nq, fp)) errcode = -2;
182: if (EOF==(cr=fgetc(fp))) errcode = -3;
183: if (!fread(oldheader.partial_credit, sizeof(char), nq, fp)) errcode = -4;
184: if (EOF==(cr=fgetc(fp))) errcode = -5;
185: capa_mfree(oldheader.weight);
186: capa_mfree(oldheader.partial_credit);
187:
188: /*read rest of file*/
189: item_cnt=fread(big_buf,1,big_buf_size, fp);
190: }
191:
192: /*write new header*/
193: fseek(fp,0L,SEEK_SET);
194: if (!fwrite(oneline, len, 1, fp)) {errcode = -6;}
195: if ( header->weight != NULL ) {
196: if (!fwrite((char *)(header->weight), strlen(header->weight), 1, fp)) errcode=-7;
197: }
198:
199: if (EOF==(!fputc('\n', fp))) errcode = -8;
200: if (header->partial_credit != NULL) {
201: if (!fwrite((char *)(header->partial_credit), strlen(header->partial_credit),
202: 1, fp)) { errcode = -9; }
203: }
204: if (EOF==(!fputc('\n', fp))) errcode = -10;
205:
206: if (exists) {
207: /*write out rest of file*/
208: if (item_cnt >= 0 ) {
209: big_buf[item_cnt]=0;
210: if (!fwrite(big_buf,item_cnt,1,fp) ) errcode= -11;
211: new_size = ftell(fp);
212: if (new_size < orig_size ) {
213: fd = fileno(fp);
214: ftruncate(fd,new_size);
215: }
216: }
217: }
218:
219: fflush(fp);
220: funlockstream(fp); fclose(fp);
221: if (big_buf!=NULL) capa_mfree(big_buf);
222: return (errcode);
223: }
224:
225: /*----------------------------------------------------------*/
226: /* INPUT: set problem set number */
227: /* RETURN: -1 file error */
228: /* 0 success */
229: /* OUTPUT: header pointer to T_header structure */
230: /* Note: allocates space for the partial_credit and weight */
231: /* fields of the passed in header, caller needs to */
232: /* eventually free them with capa_mfree */
233: /*----------------------------------------------------------*/
234: int
235: capa_get_header(header, set) T_header *header;int set;
236: {
237: FILE *fp;
238: char filename[FILE_NAME_LENGTH];
239: char cr;
240: int nq=0, errcode;
241:
242: sprintf(filename,"records/set%d.db",set);
243: if ((fp=fopen(filename,"r"))==NULL) {
244: /*printf("Error capa_get_header(): can't open %s\n",filename);*/
245: return (-1);
246: }
247:
248: flockstream(fp); errcode = 0;
249: fscanf(fp,"%d",&nq);
250: cr='\0';
251: while ( cr != '\n' && cr != EOF ) { cr=fgetc(fp); }
252: header->weight=capa_malloc(nq+1,1);
253: header->partial_credit=capa_malloc(nq+1,1);
254: if (nq > 0 ) {
255: if (!fread(header->weight, sizeof(char), nq, fp)) errcode = -1;
256: }
257: if (EOF==(cr=fgetc(fp))) errcode = -1;
258: if (nq > 0 ) {
259: if (!fread(header->partial_credit, sizeof(char), nq, fp)) errcode = -1;
260: }
261:
262: funlockstream(fp); fclose(fp);
263: header->weight[nq]='\0'; header->partial_credit[nq]='\0';
264: sprintf(header->num_questions,"%d",nq);
265: return (errcode);
266: }
267: /*----------------------------------------------------------*/
268: /* ----------- previous version, obsolete as of May 1997
269: int
270: capa_set_entry(entry, student_number, set, offset)
271: T_entry *entry;
272: char *student_number;
273: int set;
274: long offset;
275: {
276: FILE *fp;
277: int errcode=0;
278: int len;
279: char filename[FILE_NAME_LENGTH];
280: char a_line[TMP_LINE_LENGTH];
281:
282: sprintf(filename,"records/set%d.db",set);
283: if ((fp=fopen(filename,"r+"))==NULL) {
284: return (-1);
285: }
286: sprintf(a_line,"%s %s,%s\n",entry->student_number,entry->answers,entry->tries);
287: len = strlen(a_line);
288: flockstream(fp);
289: fseek(fp,offset,0);
290: if (!fwrite(a_line,len,1,fp) ) {
291: printf("Error writing data to file\n");
292: errcode= (-1);
293: }
294: fflush(fp);
295: funlockstream(fp);
296: fclose(fp);
297: return (errcode);
298: }
299: ---------- */
300:
301: int
302: capa_set_entry(entry, student_number, set, offset)
303: T_entry *entry;
304: char *student_number;
305: int set;
306: long offset;
307: {
308: FILE *fp;
309: int fd;
310: int errcode=0;
311: int done, len, new_len, item_cnt;
312: long next_r, orig_size, new_size, big_buf_size;
313: char filename[FILE_NAME_LENGTH];
314: char *a_line, tmpline[TMP_LINE_LENGTH],
315: tmp_sn[MAX_STUDENT_NUMBER+1], fmtbuf[SMALL_LINE_BUFFER];
316: char *big_buf;
317:
318: sprintf(filename,"records/set%d.db",set);
319: if ((fp=fopen(filename,"r+"))==NULL) {
320: /* printf("Error capa_set_entry(): can't open %s\n",filename); */ return (-1);
321: }
322: /* entry->answers*3 == entry->tries, + fudge factor*/
323: a_line=capa_malloc(strlen(entry->tries)*5+MAX_STUDENT_NUMBER,1);
324: sprintf(a_line,"%s %s,%s\n",entry->student_number,entry->answers,entry->tries);
325: new_len = strlen(a_line);
326: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
327: flockstream(fp); /* <==== lock the setX.db file */
328: fseek(fp,0L,SEEK_END);
329: orig_size = ftell(fp);
330: big_buf_size = orig_size + new_len;
331: big_buf = capa_malloc(big_buf_size,1);
332: fseek(fp,0L,SEEK_SET); /* rewind to beginning of file */
333: fgets(tmpline,TMP_LINE_LENGTH-1,fp); /* skip weight line, including \n */
334: fgets(tmpline,TMP_LINE_LENGTH-1,fp); /* hand grading */
335: done = 0;
336: while(!done) {
337: done = !fgets(tmpline,TMP_LINE_LENGTH-1,fp); len = strlen(tmpline);
338: if( !done ) {
339: sscanf(tmpline,fmtbuf,tmp_sn);
340: if( !strncasecmp(tmp_sn,student_number,MAX_STUDENT_NUMBER) ) { /* Found */
341: next_r = ftell(fp); offset = next_r - len; done = 1;
342: item_cnt=fread(big_buf,1,big_buf_size, fp); /* read remaining lines into buffer */
343: if(item_cnt >= 0 ) { /* no error reading remaining lines */
344: big_buf[item_cnt]=0; /* terminate the buffer, for sure */
345: fseek(fp,offset,SEEK_SET); /* reposition file pointer to the record */
346: if (!fwrite(a_line,new_len,1,fp) ) { /* write out the records */
347: /* printf("Error writing data to file\n"); */
348: errcode= (-1);
349: }
350: if (item_cnt != 0) {
351: if (!fwrite(big_buf,item_cnt,1,fp) ){/*write out the remainings*/
352: /* printf("Error writing data to file\n"); */
353: errcode= (-1);
354: }
355: }
356: new_size = ftell(fp);
357: if(new_size < orig_size ) {
358: fd = fileno(fp);
359: ftruncate(fd,new_size);
360: }
361: }
362: }
363: } else { /* end of file */
364: fseek(fp,0L,SEEK_END);
365: offset = ftell(fp); /* last byte, if last byte is cr, back up one */
366: fseek(fp,-1L,SEEK_END);
367: while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); }
368: offset = offset +2; /* last char and cr */
369: done=1;
370: fseek(fp,offset,SEEK_SET);
371: if (!fwrite(a_line,new_len,1,fp) ) { /* write out the records */
372: /* printf("Error writing data to file\n"); */
373: errcode= (-1);
374: }
375: }
376: }
377: fflush(fp);
378: funlockstream(fp); /* <======= unlock the file */
379: fclose(fp);
380: capa_mfree(big_buf); /* free up the buffer */
381: return (errcode);
382: }
383:
384: /* for all elements in entry->answers that aren't ? it changes the
385: file to have the new values (except if student has a Y and for all
386: entries in entry->tries that don't have the value -1 it changes the
387: file to have the new value */
388:
389: int
390: capa_change_entry(entry, student_number, set)
391: T_entry *entry;
392: char *student_number;
393: int set;
394: {
395: FILE *fp;
396: int fd;
397: int errcode=0,offset=0;
398: int done, len, new_len, item_cnt,i,j;
399: long next_r, orig_size, new_size, big_buf_size;
400: char filename[FILE_NAME_LENGTH];
401: char *a_line, tmpline[TMP_LINE_LENGTH],
402: tmp_sn[MAX_STUDENT_NUMBER+1], fmtbuf[SMALL_LINE_BUFFER];
403: char *big_buf;
404:
405: sprintf(filename,"records/set%d.db",set);
406: if ((fp=fopen(filename,"r+"))==NULL) {
407: /* printf("Error capa_set_entry(): can't open %s\n",filename); */ return (-1);
408: }
409: /* entry->answers*3 == entry->tries, + fudge factor*/
410: a_line=capa_malloc(strlen(entry->tries)*5+MAX_STUDENT_NUMBER,1);
411: sprintf(a_line,"%s %s,%s\n",entry->student_number,entry->answers,entry->tries);
412: new_len = strlen(a_line);
413: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
414: flockstream(fp); /* <==== lock the setX.db file */
415: fseek(fp,0L,SEEK_END);
416: orig_size = ftell(fp);
417: big_buf_size = orig_size + new_len;
418: big_buf = capa_malloc(big_buf_size,1);
419: fseek(fp,0L,SEEK_SET); /* rewind to beginning of file */
420: fgets(tmpline,TMP_LINE_LENGTH-1,fp); /* skip weight line, including \n */
421: fgets(tmpline,TMP_LINE_LENGTH-1,fp); /* hand grading */
422: done = 0;
423: while(!done) {
424: done = !fgets(tmpline,TMP_LINE_LENGTH-1,fp); len = strlen(tmpline);
425: if( !done ) {
426: sscanf(tmpline,fmtbuf,tmp_sn);
427: if( !strncasecmp(tmp_sn,student_number,MAX_STUDENT_NUMBER) ) { /* Found */
428: next_r = ftell(fp); offset = next_r - len; done = 1;
429: item_cnt=fread(big_buf,1,big_buf_size,fp); /*read remaining lines into buffer*/
430: if(item_cnt >= 0 ) { /* no error reading remaining lines */
431: big_buf[item_cnt]=0; /* terminate the buffer, for sure */
432: fseek(fp,offset,SEEK_SET); /* reposition file pointer to the record */
433: for(i=0;i<entry->e_probs;i++) {
434: /*if entry has been updated, and student doesn't have a Y yet*/
435: if ((entry->answers[i]!='?') &&
436: (tmpline[MAX_STUDENT_NUMBER+1+i]!='Y'))
437: tmpline[MAX_STUDENT_NUMBER+1+i]=entry->answers[i];
438: j = atoi(&(entry->tries[i*3]));
439: if ( j > -1 ) {
440: tmpline[MAX_STUDENT_NUMBER+1+entry->e_probs+1+i*3]=entry->tries[i*3];
441: tmpline[MAX_STUDENT_NUMBER+1+entry->e_probs+1+i*3+1]=entry->tries[i*3+1];
442: }
443: }
444: if (!fwrite(tmpline,new_len,1,fp) ) { errcode= (-1); }
445: if (item_cnt != 0) {
446: if (!fwrite(big_buf,item_cnt,1,fp) ){/*write out the remainings*/
447: /* printf("Error writing data to file\n"); */
448: errcode= (-1);
449: }
450: }
451: new_size = ftell(fp);
452: if(new_size < orig_size ) {
453: fd = fileno(fp);
454: ftruncate(fd,new_size);
455: }
456: }
457: }
458: } else { /* end of file */
459: fseek(fp,0L,SEEK_END);
460: offset = ftell(fp); /* last byte, if last byte is cr, back up one */
461: fseek(fp,-1L,SEEK_END);
462: while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); }
463: offset = offset +2; /* last char and cr */
464: done=1;
465: fseek(fp,offset,SEEK_SET);
466: if (!fwrite(a_line,new_len,1,fp) ) { /* write out the records */
467: /* printf("Error writing data to file\n"); */
468: errcode= (-1);
469: }
470: }
471: }
472: fflush(fp);
473: funlockstream(fp); /* <======= unlock the file */
474: fclose(fp);
475: capa_mfree(big_buf); /* free up the buffer */
476: return (errcode);
477: }
478:
479: /* -------------------------------------------------- */
480: /* append a entry record to the very end of the file */
481: long
482: capa_append_entry(entry, student_number, set)
483: T_entry *entry;
484: char *student_number;
485: int set;
486: {
487: FILE *fp;
488: int len;
489: char filename[FILE_NAME_LENGTH];
490: char a_line[TMP_LINE_LENGTH];
491: long offset;
492:
493: sprintf(filename,"records/set%d.db",set);
494: if ((fp=fopen(filename,"r+"))==NULL) {
495: /* printf("Error capa_set_entry(): can't open %s\n",filename); */
496: return (-1);
497: }
498: sprintf(a_line,"%s %s,%s\n",entry->student_number,entry->answers,entry->tries);
499: len = strlen(a_line);
500:
501: flockstream(fp); /* <==== lock the setX.db file */
502: fseek(fp,0L,SEEK_END);
503: offset = ftell(fp);
504: fseek(fp,-1L,SEEK_END);
505: while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); }
506: offset = offset +2;
507: fseek(fp,offset,SEEK_SET);
508: if (!fwrite(a_line,len,1,fp) ) {
509: /* printf("Error writing data to file\n"); */
510: return (-1);
511: }
512: fflush(fp);
513: funlockstream(fp);
514: fclose(fp);
515: return (offset);
516: }
517:
518: /*----------------------------------------------------------*/
519:
520: long /* RETURNS: byte offset to start of record, 0 if error,
521: -offset if not found & newly created */
522: capa_get_entry(entry, student_number, set)
523: T_entry *entry;
524: char *student_number;
525: int set;
526: {
527: char filename[FILE_NAME_LENGTH];
528: FILE *fp;
529: int len, nq;
530: char *ans_p, *tries_p, oneline[TMP_LINE_LENGTH],fmtbuf[SMALL_LINE_BUFFER];
531: long offset = 0, next_r;
532: int ii, done, found = 0;
533: char a_sn[MAX_STUDENT_NUMBER+1];
534:
535: sprintf(filename,"records/set%d.db",set);
536: if ((fp=fopen(filename,"r"))==NULL) {
537: /*printf("Error capa_get_entry(): can't open %s\n",filename);*/
538: return (0);
539: }
540: sprintf(entry->student_number,"%s",student_number);
541: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
542: flockstream(fp);
543: fgets(oneline,TMP_LINE_LENGTH-1,fp); len = strlen(oneline); sscanf(oneline,"%d",&nq);
544: fgets(oneline,TMP_LINE_LENGTH-1,fp); /* skip weight line, including \n */
545: fgets(oneline,TMP_LINE_LENGTH-1,fp); /* hand grading */
546: done = 0;
547: while(!done) {
548: done = !fgets(oneline,TMP_LINE_LENGTH-1,fp); len = strlen(oneline);
549: if( !done ) {
550: sscanf(oneline,fmtbuf,a_sn);
551: if( !strncasecmp(a_sn,student_number,MAX_STUDENT_NUMBER) ) { /* Found */
552: next_r = ftell(fp); offset = next_r - len; done = 1; found = 1;
553: }
554: } else { /* end of file */
555: fseek(fp,0L,SEEK_END);
556: offset = ftell(fp); /* last byte, if last bye is cr, back up one */
557: fseek(fp,-1L,SEEK_END);
558: while(fgetc(fp) == '\n' ) { offset--; fseek(fp,offset,SEEK_SET); }
559: offset = offset +2; /* last char and cr */
560: found = 0; done=1;
561: }
562: }
563: funlockstream(fp); fclose(fp);
564: if(!found) {
565: ans_p = capa_malloc(nq+1,1);
566: tries_p = capa_malloc(3*nq+2,1); /* space and \0 */
567: for(ii=0;ii<nq;ii++) { /* Initialize answer string and tries string */
568: ans_p[ii] = '-'; tries_p[3*ii] = ' '; tries_p[3*ii + 1] = '0';
569: if(ii < nq-1) tries_p[3*ii + 2] = ',';
570: }
571: entry->answers = ans_p;
572: entry->tries = tries_p;
573: entry->e_probs = nq;
574: offset = capa_append_entry(entry,student_number,set);
575: } else { /* grows records shorter than nq to nq in length*/
576: char *comma;
577: int length;
578: comma=index(oneline,',');
579: length=((int)(comma-oneline))-(MAX_STUDENT_NUMBER+1);
580: if (length < nq) {
581: ans_p = capa_malloc(nq+1,1);
582: tries_p = capa_malloc(3*nq+2,1); /* space and \0 */
583: } else {
584: ans_p = capa_malloc(length+1,1);
585: tries_p = capa_malloc(3*length+2,1); /* space and \0 */
586: }
587: sprintf(fmtbuf, "%%%dc",length);
588: sscanf(oneline + MAX_STUDENT_NUMBER+1,fmtbuf,ans_p);
589: sprintf(fmtbuf, "%%%dc",(3*length-1));
590: sscanf(oneline + MAX_STUDENT_NUMBER+1+length+1,fmtbuf,tries_p);
591: entry->answers = ans_p;
592: entry->tries = tries_p;
593: entry->e_probs = nq;
594: if (length < nq) {
595: for(ii=length;ii<nq;ii++) {
596: ans_p[ii] = '-'; tries_p[3*ii] = ' '; tries_p[3*ii + 1] = '0';
597: if(ii < nq-1) tries_p[3*ii + 2] = ',';
598: }
599: ans_p[nq]='\0';tries_p[3*(nq)+2]='\0';tries_p[3*length-1]=',';
600: }
601: }
602: return (offset);
603: }
604: /*----------------------------------------------------------*/
605: /* Constants defining the column number for each fields */
606: /* in classl file */
607: /*----------------------------------------------------------*/
608: #define SECTION_BEGIN_COLUMN 10
609: #define SN_BEGIN_COLUMN 14
610: #define NAME_BEGIN_COLUMN 24
611: #define EMAIL_BEGIN_COLUMN 60
612: #define CAPAID_BEGIN_COLUMN 100
613: /*----------------------------------------------------------*/
614: /* Retrieve a linked list of students with specified */
615: /* section in classl file */
616: /* If the input section number is 0, students in the whole */
617: /* classl will be retrieved. */
618: /* The resulting linked list is ordered according to the */
619: /* order in classl */
620: /* Remember to use free_students() to free up the linked */
621: /* list once done with it. */
622: /*----------------------------------------------------------*/
623: /* INPUT: section section number */
624: /* 0 means to load the whole class */
625: /* OUTPUT: student_pp */
626: /* pointer to pointer of structure T_student */
627: /* RETURN: number of students in specified section */
628: /*----------------------------------------------------------*/
629: int
630: capa_get_section(student_pp, section)
631: T_student **student_pp;
632: int section;
633: {
634: FILE *fp;
635: char line[SMALL_LINE_BUFFER],fmtbuf[SMALL_LINE_BUFFER], *cp;
636: int i, line_len;
637: int tmp_sec, student_cnt, tmp_capaid;
638: T_student *s1_p, *s2_p, *s3_p;
639:
640: if ((fp=fopen("classl","r"))==NULL) {
641: /*printf("Error: Can't open classlist file\n");*/
642: return (-1);
643: }
644: student_cnt = 0; s1_p = s2_p = s3_p = (T_student *)NULL;
645: while (fgets(line,SMALL_LINE_BUFFER-1,fp)) {
646: line_len = strlen(line);
647: if(line_len > 25 ) { /* contains valid information, instead of only cr */
648: sscanf(line+SECTION_BEGIN_COLUMN,"%d", &tmp_sec);
649: if (!section || tmp_sec == section) {
650: s3_p = (T_student *)capa_malloc(sizeof(T_student),1);
651: s3_p->s_sec = tmp_sec;
652: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
653: sscanf(line+SN_BEGIN_COLUMN,fmtbuf,s3_p->s_sn);
654: cp = (char *)&line[NAME_BEGIN_COLUMN];
655: for(i=0;i<MAX_NAME_CHAR;i++) s3_p->s_nm[i]=' ';
656: i=0;
657: while( (i < MAX_NAME_CHAR) &&
658: ( isalnum(cp[i]) || cp[i] == ',' || cp[i] == '.' || cp[i] == '\'' ||
659: cp[i] == ' ' || cp[i] == '\t'|| cp[i] == '-' ) ) {
660: s3_p->s_nm[i]=cp[i]; i++;
661: }
662: s3_p->s_nm[MAX_NAME_CHAR]='\0';
663: s3_p->s_email[0]=0;
664: if( line_len > EMAIL_BEGIN_COLUMN ) { /* contains email */
665: cp = (char *)&line[EMAIL_BEGIN_COLUMN];
666: for(i=0;i<MAX_EMAIL_CHAR;i++) s3_p->s_email[i]=' ';
667: i=0;
668: while( (i < MAX_EMAIL_CHAR) &&
669: ( isalnum(cp[i]) || cp[i] == '@' || cp[i] == '.' ) ) {
670: s3_p->s_email[i]=cp[i]; i++;
671: }
672: s3_p->s_email[i]='\0'; /* terminate the email string with the string length */
673: if( line_len > CAPAID_BEGIN_COLUMN ) { /* contains capa id */
674: sscanf(line+CAPAID_BEGIN_COLUMN,"%d", &tmp_capaid);
675: if(tmp_capaid > 0 ) {
676: s3_p->s_capaid = tmp_capaid;
677: }
678: }
679: }
680: if( student_cnt == 0 ) {
681: s1_p = s3_p;
682: s3_p->s_prev = s3_p; s3_p->s_next = (T_student *)NULL;
683: s2_p = s3_p;
684: } else {
685: s3_p->s_prev = s2_p; s3_p->s_next = (T_student *)NULL;
686: s2_p->s_next = s3_p;
687: s2_p = s3_p;
688: }
689: student_cnt++;
690: }
691: }
692: }
693: fclose(fp);
694: *student_pp = s1_p;
695: return (student_cnt);
696: }
697: /*----------------------------------------------------------*/
698: /*----------------------------------------------------------*/
699: /* Retrieve a linked list of students with specified */
700: /* section in classl file */
701: /* If the input section number is 0, students in the whole */
702: /* classl will be retrieved. */
703: /* The resulting linked list is ordered according to */
704: /* student name */
705: /* Remember to use free_students() to free up the linked */
706: /* list once done with it. */
707: /*----------------------------------------------------------*/
708: /* INPUT: section section number */
709: /* 0 means to load the whole class */
710: /* OUTPUT: student_pp */
711: /* pointer to pointer of structure T_student */
712: /* RETURN: number of students in specified section */
713: /*----------------------------------------------------------*/
714:
715: int
716: capa_sorted_section(student_pp, section)
717: T_student **student_pp;
718: int section;
719: {
720: int student_cnt;
721: T_student *student_p, *c_sp;
722:
723: student_cnt = capa_get_section(&student_p,section);
724: if( student_cnt > 1 ) {
725: for(c_sp=student_p;c_sp;c_sp=c_sp->s_next){
726: strcpy(c_sp->s_key,c_sp->s_nm);
727: }
728: msort_main(&student_p);
729: }
730: *student_pp = student_p;
731: return (student_cnt);
732: }
733:
734: /*----------------------------------------------------------*/
735: /* INPUT: address of a pointer to T_student structure */
736: /* OUTPUT: address of a pointer to T_student structure */
737: /* */
738: /* RETURN: none */
739: /*----------------------------------------------------------*/
740: void
741: msort_main(head_pp) T_student **head_pp;
742: {
743: T_student *right_p, *out_sp;
744:
745: if( (*head_pp != NULL) && ((*head_pp)->s_next != NULL) ) {
746: msort_split( *head_pp, &right_p);
747: msort_main(head_pp); msort_main(&right_p);
748: msort_merge(*head_pp, right_p, &out_sp);
749: *head_pp = out_sp;
750: }
751: }
752: /*----------------------------------------------------------*/
753: /* INPUT: a_sp pointer to T_student structur */
754: /* OUTPUT: a_sp */
755: /* b_pp address of a pointer to T_student structure */
756: /* */
757: /* RETURN: none */
758: /*----------------------------------------------------------*/
759: void
760: msort_split(a_sp, b_pp) T_student *a_sp; T_student **b_pp;
761: {
762: T_student *c_sp;
763:
764: *b_pp = a_sp;
765: c_sp = a_sp->s_next;
766: c_sp = c_sp->s_next;
767: while( c_sp != NULL ) {
768: c_sp = c_sp->s_next;
769: *b_pp = (*b_pp)->s_next;
770: if( c_sp != NULL ) c_sp = c_sp->s_next;
771: }
772: c_sp = (*b_pp)->s_next;
773: (*b_pp)->s_next = NULL;
774: *b_pp = c_sp;
775: }
776: /*----------------------------------------------------------*/
777: /* INPUT: a_sp pointer to T_student structur */
778: /* b_sp pointer to T_student structur */
779: /* OUTPUT: c_pp address of a pointer to T_student structure */
780: /* */
781: /* RETURN: none */
782: /*----------------------------------------------------------*/
783: void
784: msort_merge(a_sp, b_sp, c_pp) T_student *a_sp, *b_sp, **c_pp;
785: {
786: T_student *d_sp;
787:
788: if( a_sp == NULL || b_sp == NULL ) {
789:
790: } else {
791: if( strcmp(a_sp->s_key, b_sp->s_key) <= 0 ) {
792: *c_pp = a_sp;
793: a_sp = a_sp->s_next;
794: } else {
795: *c_pp = b_sp;
796: b_sp = b_sp->s_next;
797: }
798: d_sp = *c_pp;
799: while( (a_sp != NULL) && (b_sp != NULL) ) {
800: if( strcmp(a_sp->s_key, b_sp->s_key) <= 0) {
801: d_sp->s_next = a_sp;
802: d_sp = a_sp;
803: a_sp = a_sp->s_next;
804: } else {
805: d_sp->s_next = b_sp;
806: d_sp = b_sp;
807: b_sp = b_sp->s_next;
808: }
809: }
810: if( a_sp == NULL ) {
811: d_sp->s_next = b_sp;
812: } else {
813: d_sp->s_next = a_sp;
814: }
815: }
816: }
817:
818: /*----------------------------------------------------------*/
819: /* INPUT: head_p pointer to T_student structure */
820: /* OUTPUT: head_p pointed to sorted linked list */
821: /* */
822: /* RETURN: none */
823: /*----------------------------------------------------------*/
824: void
825: insert_sort(head_p) T_student *head_p;
826: {
827: T_student *tail_p, *i_p, *p_p, *r_p;
828:
829: if( head_p != NULL ) {
830: tail_p = head_p;
831: while( tail_p->s_next != NULL ) {
832: i_p = tail_p->s_next;
833: if( strcmp( i_p->s_key, head_p->s_key) < 0 ) {
834: tail_p->s_next = i_p->s_next;
835: i_p->s_next = head_p;
836: head_p = i_p;
837: } else {
838: r_p = head_p;
839: p_p = r_p->s_next;
840: while( strcmp(i_p->s_key, p_p->s_key) > 0 ) {
841: r_p = p_p;
842: p_p = r_p->s_next;
843: }
844: if( i_p == p_p ) {
845: tail_p = i_p;
846: } else {
847: tail_p->s_next = i_p->s_next;
848: i_p->s_next = p_p;
849: r_p->s_next = i_p;
850: }
851: }
852: }
853: }
854: }
855: /*----------------------------------------------------------*/
856: /* The purpose of this routine is to free up all spaces */
857: /* in the linked list */
858: /*----------------------------------------------------------*/
859: /* INPUT: student_p pointer to T_student structure */
860: /* OUTPUT: none */
861: /* */
862: /* RETURN: none */
863: /*----------------------------------------------------------*/
864:
865: void
866: free_students(student_p) T_student *student_p;
867: {
868: T_student *s_p,*next_p;
869:
870: for (s_p=student_p; s_p; s_p=next_p) {
871: next_p = (s_p->s_next);
872: capa_mfree((char *)s_p);
873: }
874: }
875:
876: /*----------------------------------------------------------*/
877: /* The purpose of this routine is to free up all spaces */
878: /* in the linked list */
879: /*----------------------------------------------------------*/
880: /* INPUT: student_p pointer to T_student structur */
881: /* OUTPUT: none */
882: /* */
883: /* RETURN: -2 file error */
884: /* -1 never login */
885: /* >= 0 score for that set */
886: /*----------------------------------------------------------*/
887: int
888: capa_get_score(student_number,set,valid_scores,answers_pp)
889: char *student_number;int set;int *valid_scores;char **answers_pp;
890: {
891: T_entry a_record;
892: T_header a_header;
893: long offset;
894: int set_scores, set_valids=0, probs_cnt;
895: int ii=0, never_login=1;
896:
897: if( (offset = capa_get_entry(&a_record,student_number,set) ) == 0 ) {
898: return (-2);
899: }
900: probs_cnt = a_record.e_probs;
901: if( capa_get_header(&a_header,set) < 0 ) { return (-2); }
902: if( offset < 0 ) {
903: for(set_valids=0,ii=0;ii<probs_cnt;ii++) {
904: set_valids += (a_header.weight[ii] - '0');
905: }
906: set_scores = -1;
907: *answers_pp = a_record.answers;
908: capa_mfree(a_record.tries); a_record.tries = NULL;
909: } else {
910: for(set_scores=0,ii=0, never_login=1;ii<probs_cnt;ii++) {
911: switch(a_record.answers[ii]) {
912: case 'Y': case 'y': never_login = 0;
913: set_scores += (a_header.weight[ii] - '0');
914: set_valids += (a_header.weight[ii] - '0'); break;
915: case '-': case 'N': case 'n':
916: set_valids += (a_header.weight[ii] - '0'); break;
917: case 'E': case 'e': break;
918: default : if( a_record.answers[ii] >= '0' &&
919: a_record.answers[ii] <= '9' ) {
920: set_scores += (a_record.answers[ii] - '0');
921: set_valids += (a_header.weight[ii] - '0');
922: never_login = 0;
923: } break;
924: }
925: }
926: *answers_pp = a_record.answers;
927: capa_mfree(a_record.tries); a_record.tries = NULL;
928: }
929: capa_mfree(a_header.weight);
930: capa_mfree(a_header.partial_credit);
931: *valid_scores = set_valids;
932: if(never_login) set_scores = -1;
933: return (set_scores);
934: }
935: /*----------------------------------------------------------*/
936: /* Reads the classl file and returns the number of students */
937: /* for each section in cnt_arry[] */
938: /* In cnt_arry[0] is the maximum section number that */
939: /* has at least one student */
940: /*----------------------------------------------------------*/
941: /* INPUT: cnt_arry[] integer array */
942: /* OUTPUT: cnt_arry[] */
943: /* */
944: /* */
945: /* RETURN: -1 file error */
946: /*----------------------------------------------------------*/
947: int
948: capa_get_section_count(cnt_arry) int cnt_arry[];
949: {
950: FILE *fp;
951: char filename[FILE_NAME_LENGTH];
952: char line[TMP_LINE_LENGTH];
953: int sec_num, cnt, i, max;
954:
955: sprintf(filename,"classl");
956: if ((fp=fopen(filename,"r"))==NULL) {
957: /*printf("Error: can't open %s\n",filename);*/
958: return (-1);
959: }
960: for(i=0;i<MAX_SECTION_COUNT;i++) cnt_arry[i]=0;
961: max = 0;
962: while ( fgets(line,TMP_LINE_LENGTH-1,fp) && (strlen(line) != 0) ) {
963: sec_num=0;
964: sscanf(line+SECTION_BEGIN_COLUMN,"%d", &sec_num);
965: if( sec_num != 0 ) {
966: max = MAX(sec_num,max);
967: cnt_arry[sec_num]++;
968: }
969: }
970: fclose(fp);
971: cnt = 0;
972: for(i=1; i <= max; i++) {
973: if(cnt_arry[i]) cnt++;
974: }
975: cnt_arry[0] = max;
976: return (cnt);
977: }
978: /*----------------------------------------------------------*/
979: /* lookup student information from classl file by */
980: /* student number */
981: /*----------------------------------------------------------*/
982: /* INPUT: student_number char array of student number */
983: /* OUTPUT: student_p pointer to a T_student structure */
984: /* that contains the student name, */
985: /* student number, section number */
986: /* of the student inquired */
987: /* */
988: /* RETURN: -1 file error */
989: /* 0 no such student */
990: /* >0 success (line number in classl of student)*/
991: /*----------------------------------------------------------*/
992: int
993: capa_get_student(student_number, student_p)
994: char *student_number;
995: T_student *student_p;
996: {
997: FILE *fp;
998: char line[SMALL_LINE_BUFFER],fmtbuf[SMALL_LINE_BUFFER],
999: sNumber[MAX_STUDENT_NUMBER+1],
1000: aNumber[MAX_STUDENT_NUMBER+1];
1001: int i,found,line_len,tmp_capaid,linenum=0;
1002: char *cp;
1003:
1004: strncpy(sNumber, student_number,MAX_STUDENT_NUMBER+1);
1005: if ((fp=fopen("classl","r"))==NULL) {
1006: /*printf("Error: Can't open classlist file\n");*/
1007: return (-1);
1008: }
1009: found = 0;
1010: while (!found && fgets(line,SMALL_LINE_BUFFER-1,fp)) {
1011: linenum++;
1012: line_len = strlen(line);
1013: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
1014: sscanf(line+SN_BEGIN_COLUMN,fmtbuf,aNumber);
1015: if(!strncasecmp(sNumber,aNumber, MAX_STUDENT_NUMBER)) {
1016: found = 1;
1017: i=0;
1018: strncpy(student_p->s_sn, student_number,MAX_STUDENT_NUMBER+1);
1019: cp = (char *)&line[NAME_BEGIN_COLUMN];
1020: while( (i< MAX_NAME_CHAR) &&
1021: (isalnum(cp[i]) || cp[i] == ',' || cp[i] == '.' || cp[i] == '\'' ||
1022: cp[i] == ' ' || cp[i] == '\t'|| cp[i] == '-' || cp[i] == '_' || cp[i] == '~' ) ) {
1023: student_p->s_nm[i]=cp[i]; i++;
1024: }
1025: student_p->s_nm[i]='\0';
1026: sscanf(line+SECTION_BEGIN_COLUMN,"%d", &(student_p->s_sec));
1027: student_p->s_email[0]=0;
1028: if( line_len > EMAIL_BEGIN_COLUMN ) { /* contains email */
1029: cp = (char *)&line[EMAIL_BEGIN_COLUMN];
1030: for(i=0;i<MAX_EMAIL_CHAR;i++) student_p->s_email[i]=' ';
1031: i=0;
1032: while( (i < MAX_EMAIL_CHAR) &&
1033: ( isalnum(cp[i]) || cp[i] == '@' || cp[i] == '.' || cp[i] == '!' || cp[i] == '=' ||
1034: cp[i] == '_' || cp[i] == '-' || cp[i] == '+' || cp[i] == '^' || cp[i] == '|' ) ) {
1035: student_p->s_email[i]=cp[i]; i++;
1036: }
1037: student_p->s_email[i]='\0'; /* terminate the email string with the string length */
1038: if( line_len > CAPAID_BEGIN_COLUMN ) { /* contains capa id */
1039: sscanf(line+CAPAID_BEGIN_COLUMN,"%d", &tmp_capaid);
1040: if(tmp_capaid > 0 ) {
1041: student_p->s_capaid = tmp_capaid;
1042: }
1043: }
1044: }
1045: }
1046: }
1047: fclose(fp);
1048: if (found > 0) found=linenum;
1049: return (found);
1050: }
1051: /*----------------------------------------------------------*/
1052: /* lookup student information from classl file by */
1053: /* student name */
1054: /*----------------------------------------------------------*/
1055: /* INPUT: student_name char array of student name */
1056: /* OUTPUT: student_p pointer to a T_student structure */
1057: /* that contains the student name, */
1058: /* student number, section number */
1059: /* of the student inquired */
1060: /* */
1061: /* RETURN: -1 file error */
1062: /* 0 no such student */
1063: /* 1 success */
1064: /*----------------------------------------------------------*/
1065: int
1066: capa_student_byname(student_name, student_p)
1067: char *student_name;
1068: T_student *student_p;
1069: {
1070: FILE *fp;
1071: char line[SMALL_LINE_BUFFER],fmtbuf[SMALL_LINE_BUFFER],
1072: sName[MAX_NAME_CHAR+1],
1073: aName[MAX_NAME_CHAR+1];
1074: int i,found, len, line_len,tmp_capaid;
1075: char *cp;
1076:
1077: len = strlen(student_name);
1078: strncpy(sName, student_name,MAX_NAME_CHAR+1);
1079: if ((fp=fopen("classl","r"))==NULL) {
1080: /*printf("Error: Can't open classlist file\n");*/
1081: return (-1);
1082: }
1083: found = 0;
1084: while (fgets(line,SMALL_LINE_BUFFER-1,fp)) {
1085: i=0;
1086: cp = (char *)&line[NAME_BEGIN_COLUMN];
1087: while( (i < MAX_NAME_CHAR) &&
1088: (isalnum(cp[i]) || cp[i] == ',' || cp[i] == '.' || cp[i] == '\'' ||
1089: cp[i] == ' ' || cp[i] == '\t' || cp[i] == '-' || cp[i] == '_' || cp[i] == '~') ) {
1090: aName[i]=cp[i]; i++;
1091: }
1092: aName[i]='\0';
1093: if(!strncasecmp(sName,aName,len)) {
1094: found = 1;
1095: strcpy(student_p->s_nm,aName);
1096: sscanf(line+SECTION_BEGIN_COLUMN,"%d", &(student_p->s_sec));
1097: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
1098: sscanf(line+SN_BEGIN_COLUMN,fmtbuf,student_p->s_sn);
1099: student_p->s_email[0]=0;
1100: line_len=strlen(line);
1101: if( line_len > EMAIL_BEGIN_COLUMN ) { /* contains email */
1102: cp = (char *)&line[EMAIL_BEGIN_COLUMN];
1103: for(i=0;i<MAX_EMAIL_CHAR;i++) student_p->s_email[i]=' ';
1104: i=0;
1105: while( (i < MAX_EMAIL_CHAR) &&
1106: ( isalnum(cp[i]) || cp[i] == '@' || cp[i] == '.' || cp[i] == '!' || cp[i] == '=' ||
1107: cp[i] == '_' || cp[i] == '-' || cp[i] == '+' || cp[i] == '^' || cp[i] == '|' ) ) {
1108: student_p->s_email[i]=cp[i]; i++;
1109: }
1110: student_p->s_email[i]='\0'; /* terminate the email string with the string length */
1111: if( line_len > CAPAID_BEGIN_COLUMN ) { /* contains capa id */
1112: sscanf(line+CAPAID_BEGIN_COLUMN,"%d", &tmp_capaid);
1113: if(tmp_capaid > 0 ) {
1114: student_p->s_capaid = tmp_capaid;
1115: }
1116: }
1117: }
1118: }
1119: }
1120: fclose(fp);
1121: return (found);
1122: }
1123: /*----------------------------------------------------------*/
1124: /* Randomly selected a student from classl file specified */
1125: /* by section */
1126: /*----------------------------------------------------------*/
1127: /* INPUT: section section number */
1128: /* OUTPUT: student_p pointer to a T_student structure */
1129: /* that contains the student name, */
1130: /* student number, section number */
1131: /* of the student inquired */
1132: /* */
1133: /* RETURN: -1 file error */
1134: /* 0 no such student */
1135: /* 1 success */
1136: /*----------------------------------------------------------*/
1137: int
1138: capa_pick_student(section, student_p)
1139: int section;
1140: T_student *student_p;
1141: {
1142: T_student *s1_p, *s2_p;
1143: int student_cnt, idx, pick=-1;
1144:
1145: student_cnt = capa_get_section(&s1_p,section);
1146: if(student_cnt > 0 ) {
1147: srand(time(NULL));
1148: pick = rand() % student_cnt;
1149: for(s2_p = s1_p, idx=0; s2_p && idx < pick; idx++) {
1150: s2_p = s2_p->s_next;
1151: }
1152: strcpy(student_p->s_sn,s2_p->s_sn);
1153: strcpy(student_p->s_nm,s2_p->s_nm);
1154: strcpy(student_p->s_email,s2_p->s_email);
1155: student_p->s_capaid=s2_p->s_capaid;
1156: student_p->s_sec = s2_p->s_sec;
1157: free_students(s1_p);
1158: }
1159: return (pick);
1160: }
1161: /* -------------------------------------------------- */
1162: /* add a student to the class file */
1163: /* check duplicated student id */
1164: /* student name? */
1165: /* Returns: 0 success */
1166: /* 1 there is an duplicate entry */
1167: /* -------------------------------------------------- */
1168: int
1169: capa_add_student(student_p)
1170: T_student *student_p;
1171: {
1172: FILE *fp;
1173: char line[SMALL_LINE_BUFFER], fmtbuf1[SMALL_LINE_BUFFER],
1174: tmp_nm[MAX_STUDENT_NUMBER+1],
1175: tmp_nu[MAX_NAME_CHAR+1];
1176: int i,found, len;
1177: char *class, *cp;
1178: char cid[4],cn[4];
1179: #if defined(NeXT)
1180: char cwd[FILE_NAME_LENGTH];
1181: #endif
1182:
1183: #if defined(NeXT)
1184: class = getwd(cwd);
1185: if( class == NULL ) { class = cwd; }
1186: #else
1187: class = getcwd(NULL,255);
1188: #endif
1189:
1190: if( class == NULL ) { printf("capa_add_student(): Current working directory unknown!\n"); }
1191: len=strlen(class); cp=class; cp=cp+(len-8);
1192: for(i=0;i<3;i++) {
1193: cid[i] = cp[i+3];
1194: cn[i] = cp[i];
1195: }
1196: cid[3]=cn[3]=0;
1197: if ((fp=fopen("classl","r+"))==NULL) {
1198: /*printf("Error: Can't open classlist file\n");*/
1199: return (-1);
1200: }
1201: found = 0;
1202: sprintf(fmtbuf1, "%%%dc",MAX_STUDENT_NUMBER);
1203: while (fgets(line,SMALL_LINE_BUFFER-1,fp)) {
1204: sscanf(line+SN_BEGIN_COLUMN,fmtbuf1,tmp_nu);
1205: tmp_nu[MAX_STUDENT_NUMBER]='\0';
1206: if(!strncasecmp(student_p->s_sn,tmp_nu, MAX_STUDENT_NUMBER)) {
1207: found = 1; break;
1208: }
1209: i=0; cp = (char *)&line[NAME_BEGIN_COLUMN];
1210: while( (i < MAX_NAME_CHAR) &&
1211: (isalnum(cp[i]) || cp[i] == ',' || cp[i] == '.' || cp[i] == '\'' ||
1212: cp[i] == ' ' || cp[i] == '\t'|| cp[i] == '-' || cp[i] == '_' || cp[i] == '~') ) {
1213: tmp_nm[i]=cp[i]; i++;
1214: }
1215: tmp_nm[i]='\0';
1216: len=strlen(tmp_nm);
1217: if(!strncasecmp(student_p->s_nm,tmp_nm,len)) {
1218: found = 1; break;
1219: }
1220: }
1221: if(!found) {
1222: sprintf(line,"%s %s %03d %s %s\n",
1223: cn,cid,student_p->s_sec,student_p->s_sn,student_p->s_nm);
1224: len = strlen(line);
1225: fseek(fp,0L,SEEK_END);
1226: if (!fwrite(line,len,1,fp) ) {
1227: /*printf("Error writing data to file\n");*/
1228: found = -1;
1229: }
1230: fflush(fp);
1231: }
1232: fclose(fp);
1233: free(class);
1234: return (found);
1235: }
1236: /*----------------------------------------------------------*/
1237: /* INPUT: student_number char array of student number */
1238: /* set the X in logX.db */
1239: /* OUTPUT: none */
1240: /* */
1241: /* RETURN: -1 file error */
1242: /* 0 no login */
1243: /* >0 number of logins in that logX.db file */
1244: /*----------------------------------------------------------*/
1245: int
1246: capa_get_login_count(student_number,set)
1247: char *student_number;
1248: int set;
1249: {
1250: char filename[FILE_NAME_LENGTH],
1251: sNumber[MAX_STUDENT_NUMBER+1],
1252: aNumber[MAX_STUDENT_NUMBER+1];
1253: FILE *fp;
1254: char line[MAX_BUFFER_SIZE],fmtbuf[MAX_BUFFER_SIZE];
1255: int num;
1256:
1257: strncpy(sNumber, student_number,MAX_STUDENT_NUMBER+1);
1258: sprintf(filename,"records/log%d.db",set);
1259: if( !capa_access(filename, F_OK) ) {
1260: if ((fp=fopen(filename,"r"))==NULL) {
1261: /*printf("Error: can't open %s\n",filename);*/
1262: return (-1);
1263: }
1264: } else {
1265: return (-1);
1266: }
1267: num = 0;
1268: while (fgets(line,MAX_BUFFER_SIZE-1,fp)) {
1269: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
1270: sscanf(line,fmtbuf,aNumber);
1271: if(!strncasecmp(sNumber,aNumber, MAX_STUDENT_NUMBER)) num++;
1272: }
1273: fclose(fp);
1274: return (num);
1275: }
1276: /*----------------------------------------------------------*/
1277: /* INPUT: set the X in logX.db */
1278: /* OUTPUT: none */
1279: /* */
1280: /* RETURN: -1 file error */
1281: /* 0 no login */
1282: /* >0 number of logins in that logX.db file */
1283: /*----------------------------------------------------------*/
1284: #define ANSWER_BEGIN_COLUMN 35
1285: int
1286: capa_get_login_db(login_item,num_probs,set)
1287: T_entry login_item[];
1288: int *num_probs;
1289: int set;
1290: {
1291: FILE *fp;
1292: char filename[FILE_NAME_LENGTH];
1293: char line[MAX_BUFFER_SIZE],fmtbuf[SMALL_LINE_BUFFER];
1294: T_header header;
1295: int num_q, count, len;
1296:
1297: if(capa_get_header(&header,set)) return (0);
1298: sscanf(header.num_questions,"%d",&num_q);
1299: *num_probs = num_q;
1300: capa_mfree(header.weight);
1301: capa_mfree(header.partial_credit);
1302:
1303: sprintf(filename,"records/log%d.db",set);
1304: if((fp=fopen(filename,"r"))==NULL) {
1305: /*printf("Error: can't open %s\n",filename);*/
1306: return (-1);
1307: }
1308: count=0;
1309: while ( fgets(line,MAX_BUFFER_SIZE,fp) && (strlen(line) != 0 )) {
1310: len = strlen(line);
1311: if(len > ANSWER_BEGIN_COLUMN ) {
1312: sprintf(fmtbuf, "%%%dc",MAX_STUDENT_NUMBER);
1313: sscanf(line,fmtbuf, login_item[count].student_number);
1314: login_item[count].answers = capa_malloc(num_q,1);
1315: sprintf(fmtbuf, "%%%dc",num_q);
1316: sscanf(line+ANSWER_BEGIN_COLUMN,fmtbuf, login_item[count].answers);
1317: count++;
1318: }
1319: }
1320: fclose(fp);
1321: return (count);
1322: }
1323:
1324: /*----------------------------------------------------------*/
1325: /* INPUT: option the option the check */
1326: /* set the X in dateX.db */
1327: /* section which section to check for */
1328: /* */
1329: /* OUTPUT: none */
1330: /* */
1331: /* RETURN: -2 invalid option */
1332: /* -1 capa_get_section_dates error */
1333: /* 0 no */
1334: /* 1 yes */
1335: /*----------------------------------------------------------*/
1336: int capa_check_option(int option,int set,int section)
1337: {
1338: T_dates* dates;
1339: int result;
1340:
1341: result=capa_get_section_dates(section,set,&dates);
1342: if (result < 0) return -1;
1343: switch(option) {
1344: case OPTION_INHIBIT_RESPONSE: result=dates->inhibit_response;break;
1345: case OPTION_VIEW_PROBLEMS_AFTER_DUE: result=dates->view_problems_after_due;break;
1346: default: result=-2;
1347: }
1348: capa_mfree((char*)dates);
1349: return result;
1350: }
1351:
1352: /*----------------------------------------------------------*/
1353: /* INPUT: set the X in logX.db */
1354: /* OUTPUT: none */
1355: /* */
1356: /* RETURN: -1 file error */
1357: /* 0 no login */
1358: /* >0 number of logins in that logX.db file */
1359: /*----------------------------------------------------------*/
1360: int
1361: compare_datetime(time,datetime)
1362: time_t time;
1363: char *datetime;
1364: {
1365: char dateStr[16], timeStr[16];
1366: time_t time2;
1367: char *t_ptr;
1368: int idx;
1369:
1370: /* sscanf(datetime,"%s %s",dateStr,timeStr); */
1371: t_ptr = index(datetime,' '); t_ptr++; /*** hpux complained */
1372: for(idx=0;idx<10;idx++) dateStr[idx] = datetime[idx];
1373: dateStr[10] = 0;
1374: for(idx=0;idx<5;idx++) timeStr[idx] = t_ptr[idx];
1375: timeStr[5] = 0;
1376: time2 = convertTime(dateStr,timeStr);
1377: if(time == time2 ) return (0);
1378: return ( (time > time2)? 1 : -1 );
1379: }
1380:
1381: /* --------------------------------- */
1382: /* check if records/dateX.db exists */
1383: /* read the section open date, answer date, due date info */
1384: /* What if: [7,3] date_info */
1385: /* [3,7] date_info */
1386: /* 4 date_info */
1387:
1388: int capa_check_date(int which,char *student_number, int section,int set)
1389: {
1390: int result;
1391: char date_str[TMP_LINE_LENGTH];
1392: time_t curtime;
1393:
1394: time(&curtime);
1395:
1396: result = capa_get_date(which,student_number,section,set,date_str);
1397: if ( result == 1 ) { result = compare_datetime(curtime,date_str); }
1398: return result;
1399: }
1400:
1401: time_t capa_convert_duration(char *duration)
1402: {
1403: int hour, minute;
1404: sscanf(duration,"%d:%d",&hour,&minute);
1405: return ((hour*60)+minute)*60;
1406: }
1407:
1408: void capa_get_due_date(char *date_str,T_dates *current,char *student_number,int set)
1409: {
1410: time_t duration=capa_convert_duration(current->duration);
1411: time_t duetime=0;
1412: time_t logintime;
1413: struct tm *due_time_tm;
1414: if ((duration > 0) && (student_number!=NULL)) {
1415: if (capa_get_login_time(student_number,set,&logintime)==1) {
1416: duetime=logintime+duration;
1417: due_time_tm=localtime(&duetime);
1418: sprintf(date_str,"%04d/%02d/%02d %02d:%02d",((due_time_tm->tm_year)+1900),
1419: due_time_tm->tm_mon+1,due_time_tm->tm_mday,due_time_tm->tm_hour,
1420: due_time_tm->tm_min);
1421: return;
1422: }
1423: }
1424: strncpy(date_str,current->due_date,DATE_BUFFER);
1425: }
1426:
1427: /* student_number can be NULL, if it isn't NULL it is used by get_due_date */
1428: /* to assign a due date based on the time the student first accessed the */
1429: /* set if duration is non-zero */
1430: int
1431: capa_get_date(int which,char *student_number,int section,int set,char *date_str)
1432: {
1433: T_dates *current;
1434: int result;
1435: result=capa_get_section_dates(section,set,¤t);
1436: if (result<0) return result;
1437: result=1;
1438: switch(which) {
1439: case CHECK_OPEN_DATE: strncpy(date_str,current->open_date,DATE_BUFFER); break;
1440: case CHECK_DUE_DATE: capa_get_due_date(date_str,current,student_number,set); break;
1441: case CHECK_ANS_DATE: strncpy(date_str,current->answer_date,DATE_BUFFER); break;
1442: default: strncpy(date_str,current->open_date,DATE_BUFFER); result=-4;break;
1443: }
1444: capa_mfree((char*)current);
1445: return result;
1446: }
1447:
1448: int
1449: capa_get_duration(char *student_number,int section,int set)
1450: {
1451: T_dates *current;
1452: int duration=0,result;
1453: result=capa_get_section_dates(section,set,¤t);
1454: if (result<0) return result;
1455: duration=capa_convert_duration(current->duration);
1456: capa_mfree((char*)current);
1457: return duration;
1458: }
1459:
1460: int
1461: capa_get_section_dates(int section,int set,T_dates** dates)
1462: {
1463: register int c;
1464: FILE *fp;
1465: int result = 0, done;
1466: int tmp_low, tmp_high, sec_mode;
1467: char filename[FILE_NAME_LENGTH], tmpline[TMP_LINE_LENGTH],
1468: default_line[TMP_LINE_LENGTH];
1469:
1470: sprintf(filename,"records/date%d.db",set);
1471: if( capa_access(filename, F_OK) != 0 ) { result = -2; } else {
1472: if ((fp=fopen(filename,"r")) == NULL) { result = -2; } else {
1473: done = 0; result = -3;
1474: /* first non-comment line is assumed to be the default line */
1475: c_gettype(fp); c_ignorewhite(fp); fgets(default_line,TMP_LINE_LENGTH-1,fp);
1476: do {
1477: c_ignorewhite(fp); c = getc(fp); ungetc(c,fp);
1478: if( c != EOF ) {
1479: sec_mode = c_getsec_range(fp,&tmp_low,&tmp_high);
1480: if( sec_mode > 0 ) { /* no error */
1481: c_ignorewhite(fp); fgets(tmpline,TMP_LINE_LENGTH-1,fp);
1482: if( sec_mode == 1 ) { /* form: sec date_info */
1483: if((result == -3) && (tmp_low == section)) {
1484: result=-4;
1485: *dates=add_date_info(tmp_low,tmp_low,tmpline);
1486: if ( *dates != NULL ) { done = 1; result = 1; }
1487: }
1488: } else { /* form : [low,high] date_info */
1489: if( (result == -3) && ((section>=tmp_low)&&(section<=tmp_high)) ) {
1490: result = -4;
1491: *dates=add_date_info(tmp_low,tmp_high,tmpline);
1492: if ( *dates != NULL ) { done = 1; result = 1; }
1493: }
1494: }
1495: } else { /* error in specify section date */
1496: while ( ((c = getc(fp)) != '\n') && ( c != EOF) ); /* skip to end of line */
1497: }
1498: } else { /* EOF encountered */
1499: done = 1;
1500: }
1501: } while (!done);
1502: /* need to deal with those sections not show up in the dateX.db file */
1503: if( result == -3 ) { /* section not in the dateX.db file, use default */
1504: result = -4;
1505: *dates=add_date_info(DATE_DEFAULTS,DATE_DEFAULTS,default_line);
1506: if ( *dates != NULL ) { result = 1; }
1507: }
1508: }
1509: fclose(fp);
1510: }
1511: return (result);
1512: }
1513:
1514: T_dates* add_date_info(int lowsec,int highsec, char *dateinfo)
1515: {
1516: T_dates *dates;
1517: int result;
1518: dates=(T_dates*)capa_malloc(sizeof(T_dates),1);
1519: result=sscanf(dateinfo,"%16c,%16c,%16c,%s %d,%d",dates->open_date,dates->due_date,
1520: dates->answer_date,dates->duration,&(dates->inhibit_response),
1521: &(dates->view_problems_after_due));
1522: if (result != 6) {
1523: capa_mfree((char*)dates);
1524: dates=NULL;
1525: } else {
1526: dates->section_start=lowsec;
1527: dates->section_end=highsec;
1528: dates->s_next=NULL;
1529: }
1530: return dates;
1531: }
1532: /*----------------------------------------------------------*/
1533: /* INPUT: set the X in dateX.db */
1534: /* dates a pointer to the dates pointer */
1535: /* ACTION: builds a linked list of T_dates containing */
1536: /* the login information */
1537: /* RETURN: <0 file error */
1538: /* >0 success (number of lines successfully */
1539: /* proccessed) */
1540: /*----------------------------------------------------------*/
1541: int capa_get_all_dates (int set,T_dates **dates)
1542: {
1543: T_dates *current;
1544: FILE *fp;
1545: int result = 0, done, tmp_low, tmp_high, sec_mode, c, num=0;
1546: char filename[FILE_NAME_LENGTH], tmpline[TMP_LINE_LENGTH];
1547:
1548: sprintf(filename,"records/date%d.db",set);
1549: if ( ((fp=fopen(filename,"r")) == NULL)) { result = -2; } else {
1550: done = 0; result = -3;
1551: /* first non-comment line is assumed to be the default line */
1552: c_gettype(fp); c_ignorewhite(fp); fgets(tmpline,TMP_LINE_LENGTH-1,fp);
1553: *dates=add_date_info(DATE_DEFAULTS,DATE_DEFAULTS,tmpline);
1554: num++;
1555: if ( NULL == (current=*dates) ) {
1556: result = -3;
1557: } else {
1558: while(1) {
1559: c_ignorewhite(fp); c = getc(fp); ungetc(c,fp);
1560: if( c == EOF ) { break; }
1561: sec_mode = c_getsec_range(fp,&tmp_low,&tmp_high);
1562: if( sec_mode > 0 ) { /* no error */
1563: c_ignorewhite(fp); fgets(tmpline,TMP_LINE_LENGTH-1,fp);
1564: if( sec_mode == 1 ) { /* form: sec date_info */
1565: current->s_next=add_date_info(tmp_low,tmp_low,tmpline);
1566: } else { /* form : [low,high] date_info */
1567: current->s_next=add_date_info(tmp_low,tmp_high,tmpline);
1568: }
1569: current=current->s_next;
1570: num++;
1571: } else { /* error in specify section date */
1572: while ( ((c = getc(fp)) != '\n') && ( c != EOF) ); /* skip to end of line */
1573: }
1574: }
1575: result=num;
1576: }
1577: fclose(fp);
1578: }
1579: return (result);
1580: }
1581:
1582: /*----------------------------------------------------------*/
1583: /* INPUT: dates a pointer to the dates pointer */
1584: /* ACTION: frees a linked list of T_dates */
1585: /*----------------------------------------------------------*/
1586: void free_dates(T_dates *dates)
1587: {
1588: T_dates *current = dates,*next;
1589: while ( current != NULL ) {
1590: next = current->s_next;
1591: capa_mfree((char*)current);
1592: current = next;
1593: }
1594: }
1595:
1596: /*----------------------------------------------------------*/
1597: /* INPUT: set the X in dateX.db */
1598: /* dates a pointer to the dates pointer */
1599: /* ACTION: takes a linked list of date information and */
1600: /* and writes the info to a file */
1601: /* RETURN: -1 file error */
1602: /* 1 success */
1603: /*----------------------------------------------------------*/
1604: int capa_set_all_dates (int set,T_dates *dates)
1605: {
1606: T_dates *current = dates;
1607: int result;
1608: FILE* fp;
1609: char filename[FILE_NAME_LENGTH];
1610:
1611: sprintf(filename,"records/date%d.db",set);
1612: if ( ((fp=fopen(filename,"w")) == NULL) ) { result = -1; } else {
1613: result=1;
1614: while ( current != NULL ) {
1615: if ( current->section_start == DATE_DEFAULTS ) {
1616: fprintf(fp,"<< DEFAULTS >> ");
1617: } else {
1618: fprintf(fp,"[%d, %d] ", current->section_start,current->section_end);
1619: }
1620: fprintf(fp,"%s,%s,%s,%s %d,%d\n", current->open_date,current->due_date,
1621: current->answer_date,current->duration,current->inhibit_response,
1622: current->view_problems_after_due);
1623: current = current->s_next;
1624: }
1625: fclose(fp);
1626: }
1627: return result;
1628: }
1629:
1630: /*----------------------------------------------------------*/
1631: /* INPUT: set the X in logX.db */
1632: /* OUTPUT: none */
1633: /* */
1634: /* RETURN: -1 file error */
1635: /* 0 no login */
1636: /* >0 number of logins in that logX.db file */
1637: /*----------------------------------------------------------*/
1638:
1639: #define FIFTEEN_MINUTES (15*60)
1640: #define TEN_MINUTES (600)
1641: #define ONE_DAY (86400)
1642: int /* RETURNS: 1 first time login, 2 second time login, 0 not ok, -1 file error */
1643: login_check(student_number) /* ARGUMENTS: */
1644: char *student_number; /* Student # */
1645: { /* LOCALS: */
1646: FILE *fp;
1647:
1648: int errcode=0;
1649: int found;
1650: char filename[FILE_NAME_LENGTH];
1651: char line[SMALL_LINE_BUFFER], new_line[SMALL_LINE_BUFFER];
1652: struct tm *theDT;
1653: time_t login_time, record_time;
1654: long offsetL, offsetR, offsetEnd,left_leng;
1655: char s_number[MAX_STUDENT_NUMBER+1];
1656: char tty_name[FILE_NAME_LENGTH];
1657: int log_tries, p_id;
1658: int month, day, year, hour, min, sec;
1659: char *tmp_buffer;
1660:
1661: sprintf(filename,"records/active.log");
1662:
1663: if( capa_access(filename,F_OK) < 0 ) { /*<------------- File not exist */
1664: if ((fp=fopen(filename,"w"))==NULL) { /* create if non-existant */
1665: /*printf("Error: can't create %s\n",filename);*/
1666: return (-1);
1667: }
1668: fclose(fp);
1669: }
1670: if ((fp=fopen(filename,"r"))==NULL) {
1671: /*printf("Error: can't open %s\n",filename);*/
1672: return (-1);
1673: }
1674: flockstream(fp); /* lock exclusively and perform read/write operation */
1675:
1676: found = 0;
1677: while( (!found) && ( fgets(line,SMALL_LINE_BUFFER-1,fp) != NULL) ) {
1678: if( !strncasecmp(line,student_number,MAX_STUDENT_NUMBER) ) found = 1;
1679: }
1680: offsetR = ftell(fp);
1681: offsetL = offsetR - strlen(line);
1682: funlockstream(fp); fclose(fp);
1683:
1684: if( found && (strlen(line) != 0) ) {
1685: /* printf("FOUND:%slen=%d\n",line,strlen(line)); */
1686: sscanf(line,"%s , %d , %d , /dev/%s ,(%d/%d/%d %d:%d:%d)\n", s_number,&log_tries,&p_id,tty_name,&month,&day,&year,&hour,&min,&sec);
1687: record_time = time(NULL);
1688: theDT = localtime(&record_time);
1689: theDT->tm_sec = sec; theDT->tm_min = min;
1690: theDT->tm_hour = hour; theDT->tm_mday = day;
1691: theDT->tm_mon = month-1; theDT->tm_year = year;
1692: theDT->tm_wday = weekday(year,month,day);
1693: theDT->tm_yday = julianday(year,month,day);
1694: record_time = mktime( theDT );
1695: time(&login_time); theDT = localtime(&login_time);
1696: switch(log_tries) {
1697: case 0: log_tries = 1; errcode = 1; break;
1698: case 1: log_tries = 2; errcode = 2;
1699: break;
1700: case 2: log_tries = 3; errcode = 0; break;
1701: case 3: if( (login_time - record_time) >= TEN_MINUTES ) {
1702: log_tries = 1; errcode = 1;
1703: } else {
1704: log_tries = 3; errcode = 2;
1705: return (0);
1706: }
1707: break;
1708: default: printf("ERROR: Number of logins UNKNOWN\n");
1709: log_tries = 1; errcode = 1;
1710: break;
1711: }
1712: sprintf(new_line,"%s , %2d , %5d , %s ,(%02d/%02d/%02d %02d:%02d:%02d)\n", student_number, log_tries, getpid(),ttyname(0), theDT->tm_mon + 1, theDT->tm_mday, theDT->tm_year, theDT->tm_hour, theDT->tm_min ,theDT->tm_sec);
1713: if ((fp=fopen(filename,"r+"))==NULL) {
1714: /*printf("Error: can't open %s\n",filename);*/
1715: return (-1);
1716: }
1717: flockstream(fp);
1718: tmp_buffer = (char *)malloc(8*1024*56);
1719: found = 0;
1720: while( (!found) && ( fgets(line,SMALL_LINE_BUFFER-1,fp) != NULL) ) {
1721: if( !strncasecmp(line,student_number,MAX_STUDENT_NUMBER) ) found = 1;
1722: }
1723: offsetR = ftell(fp); offsetL = offsetR - strlen(line);
1724: fseek(fp,0L,SEEK_END); offsetEnd = ftell(fp);
1725: left_leng = offsetEnd - offsetR;
1726: fseek(fp,offsetR,SEEK_SET);
1727: left_leng = fread(tmp_buffer, 1, left_leng+1, fp);
1728: tmp_buffer[left_leng] = 0;
1729: fseek(fp,offsetL,SEEK_SET);
1730: if ( fprintf(fp,"%s%s",new_line,tmp_buffer) < 0 ) {
1731: /*printf("Error: cannot write active.log\n");*/
1732: errcode = -1;
1733: }
1734: fflush(fp);
1735: free( (char *)tmp_buffer);
1736: funlockstream(fp);
1737: fclose(fp);
1738: } else { /********************************** First time login */
1739: if ((fp=fopen(filename,"a+"))==NULL) {
1740: /*printf("Error: can't open %s\n",filename);*/
1741: return (-1);
1742: }
1743: log_tries = 1;
1744: time(&login_time);
1745: theDT = localtime(&login_time);
1746: sprintf(line,"%s , %2d , %5d , %s ,(%02d/%02d/%02d %02d:%02d:%02d)\n", student_number, log_tries, getpid(),ttyname(0), theDT->tm_mon + 1, theDT->tm_mday, theDT->tm_year, theDT->tm_hour, theDT->tm_min ,theDT->tm_sec);
1747: /*
1748: leng = strlen(line);
1749: for(idx = 0, len_idx = 0; idx<(leng-1); idx++) {
1750: if(line[idx] == '\n' && line[idx+1] == '\n') {
1751: line[idx+1] = 0;
1752: }
1753: }
1754: */
1755: flockstream(fp);
1756: if ( !fwrite((char *)line, strlen(line), 1, fp) ) {
1757: /*printf("ERROR: cannot write active.log\n");*/
1758: errcode = -1;
1759: } else {
1760: errcode = 1;
1761: }
1762: fflush(fp);
1763: funlockstream(fp);
1764: fclose(fp);
1765: }
1766: return (errcode);
1767:
1768: }
1769:
1770: /******************************************************************************/
1771: /* Logout check */
1772: /******************************************************************************/
1773: int /* RETURNS: 1 successful, 0 otherwise, -1 file error */
1774: logout_check(student_number) /* ARGUMENTS: */
1775: char *student_number; /* Student # */
1776: { /* LOCALS: */
1777: FILE *fp;
1778:
1779: int errcode=0;
1780: int found;
1781: char filename[FILE_NAME_LENGTH];
1782: char line[SMALL_LINE_BUFFER];
1783: long offsetL, offsetR, offsetEnd,left_leng;
1784: char s_number[MAX_STUDENT_NUMBER+1];
1785: char tty_name[FILE_NAME_LENGTH];
1786: int log_tries, p_id;
1787: int month, day, year, hour, min, sec;
1788: char *tmp_buffer;
1789:
1790:
1791: sprintf(filename,"records/active.log");
1792: if ((fp=fopen(filename,"r"))==NULL) {
1793: /*printf("Error: can't open %s\n",filename);*/
1794: return (-1);
1795: }
1796: flockstream(fp); /* lock exclusively and perform read/write operation */
1797:
1798: found = 0;
1799: while( (!found) && ( fgets(line,SMALL_LINE_BUFFER-1,fp) != NULL) ) {
1800: if( !strncasecmp(line,student_number,MAX_STUDENT_NUMBER) ) found = 1;
1801: }
1802: offsetR = ftell(fp);
1803: offsetL = offsetR - strlen(line);
1804:
1805: funlockstream(fp);
1806: fclose(fp);
1807:
1808: if( found ) {
1809: #ifdef __alpha
1810: sscanf(line,"%s , %d , %d , /dev/%s ,(%d/%d/%d %d:%d:%d)\n", s_number,&log_tries,&p_id,tty_name,&month,&day,&year,&hour,&min,&sec);
1811: #else
1812: sscanf(line,"%s , %d , %d , /dev/%s ,(%d/%d/%d %d:%d:%d)\n", \
1813: s_number,&log_tries,&p_id,tty_name,&month,&day,&year,&hour,&min,&sec);
1814: #endif
1815: switch(log_tries) {
1816: case 0: log_tries = 0;
1817: break;
1818: case 1: log_tries = 0;
1819: break;
1820: case 2: log_tries = 0;
1821: break;
1822: default: printf("ERROR: Number of logins UNKNOWN\n");
1823: log_tries = 0;
1824: break;
1825: }
1826: #ifdef __alpha
1827: sprintf(line,"%s , %2d , %5d , /dev/%s ,(%02d/%02d/%02d %02d:%02d:%02d)\n", s_number,log_tries, p_id, tty_name, month, day, year, hour, min, sec);
1828: #else
1829: sprintf(line,"%s , %2d , %5d , /dev/%s ,(%02d/%02d/%02d %02d:%02d:%02d)\n", \
1830: s_number,log_tries, p_id, tty_name, month, day, year, hour, min, sec);
1831: #endif
1832:
1833: if ((fp=fopen(filename,"r+"))==NULL) {
1834: /*printf("Error: can't open %s\n",filename);*/
1835: return (-1);
1836: }
1837: flockstream(fp);
1838: tmp_buffer = (char *)malloc(8*1024*56);
1839: fseek(fp,0L,SEEK_END);
1840: offsetEnd = ftell(fp);
1841: left_leng = offsetEnd - offsetR;
1842: fseek(fp,offsetR,SEEK_SET);
1843: fread(tmp_buffer, left_leng, 1, fp);
1844: tmp_buffer[left_leng] = 0;
1845: /*
1846: for(idx=0, l_idx = 0; idx< (left_leng-1); idx++) {
1847: if( tmp_buffer[idx] == '/n' && tmp_buffer[idx+1] == '/n' ) {
1848: }
1849: }
1850: */
1851: fseek(fp,offsetL,SEEK_SET);
1852: if ( fprintf(fp,"%s%s",line,tmp_buffer) < 0 ) {
1853: /*printf("Error: write error\n");*/
1854: errcode = -1;
1855: } else {
1856: errcode = 1;
1857: }
1858: fflush(fp);
1859: free( (char *)tmp_buffer);
1860: funlockstream(fp);
1861: fclose(fp);
1862: } else {
1863: errcode = -1;
1864: }
1865: return (errcode);
1866:
1867: }
1868: /*********************************************/
1869: /* SIZE of char =1, int=4, long=4, double=8 */
1870: void
1871: capa_seed(seed1,seed2,student_number)long *seed1;long *seed2;char *student_number;
1872: {
1873: int class_pin1, class_pin2;
1874: int s_pin1, s_pin2, s_pin3;
1875: int i;
1876: char dest[16], tmpSN[MAX_STUDENT_NUMBER+1];
1877: char *class,*capadefault="capadefault";
1878: long part1, part2;
1879: #if defined(NeXT)
1880: char cwd[FILE_NAME_LENGTH];
1881: #endif
1882: int big_endian;
1883:
1884: big_endian = endian(); /* determine what type of CPU we are on */
1885:
1886: #if defined(NeXT)
1887: class = getwd(cwd);
1888: if( class == NULL ) { class = cwd; }
1889: #else
1890: class = getcwd(NULL,255);
1891: #endif
1892: class_pin1 = class_pin2 = 2;
1893: s_pin1 = s_pin2 = s_pin3 = 2;
1894:
1895: if( class == NULL ) {
1896: printf("capa_seed(): Current working directory unknown! Using capadefault\n");
1897: class=capa_malloc(strlen(capadefault)+1,1);
1898: strcpy(class,capadefault);
1899: }
1900: if( big_endian ) {
1901: for(i=0;i<4;i++) dest[i] = class[strlen(class)-8+i];
1902: for(i=4;i<8;i++) dest[i] = 0;
1903: memcpy((char *)(&class_pin1), dest, 4);
1904: for(i=0;i<4;i++) dest[i] = class[strlen(class)-4+i];
1905: for(i=4;i<8;i++) dest[i] = 0;
1906: memcpy((char *)(&class_pin2), dest, 4);
1907: } else {
1908: for(i=0;i<4;i++) dest[i] = class[strlen(class)-i-5];
1909: for(i=4;i<8;i++) dest[i] = 0;
1910: memcpy((char *)(&class_pin1), dest, 4);
1911: for(i=0;i<4;i++) dest[i] = class[strlen(class)-i-1];
1912: for(i=4;i<8;i++) dest[i] = 0;
1913: memcpy((char *)(&class_pin2), dest, 4);
1914: }
1915: for(i=0;i<MAX_STUDENT_NUMBER;i++) {
1916: if(islower(student_number[i])) {
1917: tmpSN[i] = toupper(student_number[i]);
1918: } else {
1919: tmpSN[i] = student_number[i];
1920: }
1921: }
1922: tmpSN[MAX_STUDENT_NUMBER] = 0;
1923:
1924: if( big_endian ) { /* big endian ** SUN, BlackNeXT 68xxx , PowerPC */
1925: for(i=0;i<4;i++) dest[i] = tmpSN[i];
1926: for(i=4;i<8;i++) dest[i] = 0;
1927: memcpy((char *)(&s_pin1), dest, 4); /* 012345678 -> "0123" */
1928: for(i=0;i<4;i++) dest[i] = tmpSN[i+2];
1929: for(i=4;i<8;i++) dest[i] = 0;
1930: memcpy((char *)(&s_pin2), dest, 4); /* 012345678 -> "2345" */
1931: for(i=0;i<4;i++) dest[i] = tmpSN[i+5];
1932: for(i=4;i<8;i++) dest[i] = 0;
1933: memcpy((char *)(&s_pin3), dest, 4); /* 012345678 -> "5678" */
1934: } else { /* Intel 386, 486 */
1935: for(i=0;i<4;i++) dest[i] = tmpSN[3-i];
1936: for(i=4;i<8;i++) dest[i] = 0;
1937: memcpy((char *)(&s_pin1), dest, 4); /* 012345678 -> "0123" */
1938: for(i=0;i<4;i++) dest[i] = tmpSN[5-i];
1939: for(i=4;i<8;i++) dest[i] = 0;
1940: memcpy((char *)(&s_pin2), dest, 4); /* 012345678 -> "2345" */
1941: for(i=0;i<4;i++) dest[i] = tmpSN[8-i];
1942: for(i=4;i<8;i++) dest[i] = 0;
1943: memcpy((char *)(&s_pin3), dest, 4); /* 012345678 -> "5678" */
1944: }
1945:
1946:
1947: part1 = s_pin1 + s_pin3+ class_pin2; if(part1 < 0) part1 = part1 * (-1);
1948: part2 = s_pin2 + class_pin1; if(part2 < 0) part2 = part2 * (-1);
1949:
1950: #ifdef SEED_DBG
1951: printf("S_PIN(%d,%d, %d) C_PIN(%d,%d)\n",s_pin1, s_pin2, s_pin3, class_pin1, class_pin2);
1952: printf("SEED(%ld,%ld)\n",part1, part2);
1953: #endif
1954: {
1955: extern void gsrgs(long getset,long *qvalue);
1956: static long qrgnin;
1957: gsrgs(0L,&qrgnin);
1958: if(!qrgnin)
1959: setall(part1, part2);
1960: }
1961: (*seed1) = part1;
1962: (*seed2) = part2;
1963: free(class);
1964: }
1965: /* ======================================================= PIN number */
1966: /* pin should only called once for each student. */
1967: /* if not called at the beginning of problem set, try to call it automatically */
1968:
1969: int /* RETURNS: pin number for login set */
1970: capa_PIN(student_number, set, guess) /* ARGUMENTS: */
1971: char *student_number;
1972: int set; /* Problem set number */
1973: int guess;
1974: { /* LOCALS: */
1975: int current=0, /* Current pin for set */
1976: i,j, /* Array indices */
1977: nope,
1978: correct=0,
1979: all_pins[ONE_K];
1980: long part1, part2;
1981: long orig_gen, new_gen;
1982:
1983: capa_seed(&part1, &part2, student_number);
1984: gscgn(GET_GENERATOR, &orig_gen);
1985: new_gen = PIN_G;
1986: gscgn(SET_GENERATOR, &new_gen);
1987: setsd(part1, part2);
1988: /* Generate 4-digit pin (1000-9999) */
1989: for (i=1; i<=set; i++) {
1990: current=1000+ignlgi()%9000;
1991: do {
1992: nope=0;
1993: for (j=1; j<i; j++) {
1994: if (current == all_pins[j]) {
1995: current=1000+ignlgi()%9000;
1996: nope++;
1997: }
1998: }
1999: } while (nope);
2000: all_pins[i]=current;
2001: if (guess && guess==current) correct=i;
2002: }
2003: gscgn(SET_GENERATOR, &orig_gen);
2004: if (guess) return (correct);
2005: return (current);
2006: }
2007:
2008: /* -------------------------------------------------------------------- */
2009: /* returns a longer pin, the first four characters are the same as the */
2010: /* normal capaId, additionally the result is a capa_malloc string */
2011: /* containing the number */
2012: /* NOTE!-> the result is a string of letters where A=1..I=9,J=0 */
2013: /* -------------------------------------------------------------------- */
2014: char*
2015: capa_id_plus(student_number, set, plus)
2016: char *student_number;
2017: int set;
2018: int plus;
2019: {
2020: long part1,part2,orig_gen,new_gen,pin,rout,k,i;
2021: char *result;
2022: char letters[10]={'J','A','B','C','D','E','F','G','H','I'};
2023: capa_seed(&part1, &part2, student_number);
2024: gscgn(GET_GENERATOR, &orig_gen);
2025: new_gen = PIN_G;
2026: gscgn(SET_GENERATOR, &new_gen);
2027: setsd(part1, part2);
2028: pin=capa_PIN(student_number,set,0);
2029: result=(char *)capa_malloc(sizeof(char), plus+MAX_PIN_CHAR+1);
2030: k=1;
2031: for(i=1;i<=MAX_PIN_CHAR;i++) {
2032: result[MAX_PIN_CHAR-i] = letters[(pin%(k*10))/k];
2033: k*=10;
2034: }
2035: for(i=MAX_PIN_CHAR;i<MAX_PIN_CHAR+plus;i++) {
2036: rout = ignlgi()%10;
2037: result[i] = letters[rout];
2038: }
2039: result[i] = '\0';
2040: gscgn(SET_GENERATOR, &orig_gen);
2041: return result;
2042: }
2043: /* -------------------------------------------------------------------- */
2044: /* need to set problem_p = NULL after this call */
2045: /* -------------------------------------------------------------------- */
2046: void
2047: free_problems(problem_p) Problem_t *problem_p;
2048: {
2049: Problem_t *p, *next;
2050:
2051: for (p=problem_p; p!=NULL ; p=next) {
2052: next=p->next;
2053: if (p->question != NULL) capa_mfree(p->question);
2054: if (p->answer != NULL) capa_mfree(p->answer);
2055: if (p->ans_cnt > 1 ) { AnswerInfo_t *a,*b;
2056: for(a = p->ans_list; a != NULL ; a = b) {
2057: b = a->ans_next;
2058: if (a->ans_str != NULL) capa_mfree(a->ans_str);
2059: if (a->ans_id_list != NULL ) capa_mfree(a->ans_id_list);
2060: if (a->ans_pts_list) {
2061: free_ptslist(a->ans_pts_list);
2062: }
2063: if (a->ans_unit) {
2064: freelist_unit_e(a->ans_unit->u_list);
2065: if (a->ans_unit != NULL) capa_mfree((char *)a->ans_unit);
2066: }
2067: capa_mfree((char *)a);
2068: }
2069: }
2070: if (p->id_list != NULL ) capa_mfree(p->id_list);
2071: if (p->pts_list!= NULL ) {
2072: free_ptslist(p->pts_list);
2073: }
2074: if (p->hint != NULL ) capa_mfree(p->hint);
2075: if (p->explain != NULL ) capa_mfree(p->explain);
2076: if (p->ans_unit !=NULL ) {
2077: freelist_unit_e(p->ans_unit->u_list);
2078: capa_mfree((char *)p->ans_unit);
2079: }
2080: capa_mfree((char *)p);
2081: p=NULL;
2082: }
2083: problem_p=NULL;
2084: }
2085:
2086: /******************************************************************************/
2087: /* PARSE SOURCE FILE AND RETURN BLOCKS OF TEXT */
2088: /******************************************************************************/
2089: int
2090: capa_parse(set,problem,student_number,num_questions,func_ptr)
2091: int set;Problem_t **problem;char *student_number;int *num_questions;
2092: void (*func_ptr)();
2093: {
2094: char filename[QUARTER_K];
2095: int errcode;
2096: FILE *fp;
2097: extern FILE *Input_stream[MAX_OPENED_FILE];
2098: extern char Opened_filename[MAX_OPENED_FILE][QUARTER_K];
2099: extern int Lexi_line;
2100: extern int Lexi_qnum;
2101: extern Problem_t *FirstProblem_p;
2102: extern Problem_t *LastProblem_p;
2103: extern Problem_t *LexiProblem_p;
2104: extern char *StartText_p;
2105: extern char *EndText_p;
2106: extern char *ErrorMsg_p;
2107: extern int ErrorMsg_count;
2108: extern char Parse_class[QUARTER_K];
2109: extern int Parse_section;
2110: extern int Parse_set;
2111: extern char Parse_name[MAX_NAME_CHAR+1];
2112: extern char Parse_student_number[MAX_STUDENT_NUMBER+1];
2113: extern int Symb_count;
2114: extern int first_run;
2115: extern int Stop_Parser;
2116: extern void (*Status_Func)();
2117: long seed1, seed2;
2118: T_student a_student;
2119: char *class, *classname, warn_msg[WARN_MSG_LENGTH];
2120: #if defined(NeXT)
2121: char cwd[FILE_NAME_LENGTH];
2122:
2123: class = getwd(cwd);
2124: if( class == NULL ) { class = cwd; }
2125: #else
2126: class = getcwd(NULL,255);
2127:
2128: #endif
2129:
2130: if(class == NULL) { /* printf("capa_parse(): Current working directory unknown!"); */ return (-1); }
2131: classname = rindex(class,'/'); classname++; /*** hpux complained */
2132: sprintf(Parse_class,"%s", classname);
2133: free(class);
2134: if( capa_get_student(student_number, &a_student) < 1 ) {
2135: /*printf("Error: capa_parse() encountered a student which is not in classl file\n"); */
2136: return (-1);
2137: }
2138: sprintf(filename,"capa.config");
2139: if ((fp=fopen(filename,"r"))==NULL) {
2140: /* printf("Error: can't open %s\n",filename);*/
2141: return (-1);
2142: }
2143: u_getunit(fp);
2144: fclose(fp);
2145: strncpy(Parse_name,a_student.s_nm,MAX_NAME_CHAR+1);
2146: strncpy(Parse_student_number,student_number,MAX_STUDENT_NUMBER+1);
2147: Parse_section = a_student.s_sec;
2148: if(ErrorMsg_p) { capa_mfree(ErrorMsg_p); ErrorMsg_p = NULL; }
2149: if(EndText_p) { capa_mfree(EndText_p); EndText_p = NULL; }
2150: if(StartText_p) { capa_mfree(StartText_p); StartText_p = NULL; }
2151: ErrorMsg_p = NULL; first_run = 1; EndText_p = NULL;
2152: free_symtree(); Symb_count = ErrorMsg_count = Lexi_line = Lexi_qnum = 0;
2153: FirstProblem_p = LastProblem_p = NULL;
2154: LexiProblem_p = (Problem_t *)capa_malloc(sizeof(Problem_t),1);
2155: problem_default(LexiProblem_p);
2156: /*LexiProblem_p->capaidplus=NULL;*/
2157: Parse_set = set;
2158: Status_Func=func_ptr;
2159: sprintf(filename,"set%d.qz",set);
2160: #ifdef AVOIDYYINPUT
2161: yyin=fopen(filename,"r");
2162: #else
2163: if ( (Input_stream[0]=fopen(filename,"r")) == NULL) {
2164: /* printf("Error: can't open %s\n",filename);*/
2165: sprintf(warn_msg,"capa_parse(): CANNOT OPEN FILE\"%s\", file does not exist or is not readable.\n", filename);
2166: capa_msg(MESSAGE_ERROR,warn_msg);
2167: return (-1);
2168: }
2169: #endif
2170: sprintf(Opened_filename[0],"%s",filename);
2171:
2172: capa_seed(&seed1, &seed2, student_number); setall(seed1,seed2);
2173:
2174: yyrestart(yyin);
2175: Stop_Parser=0;
2176: if ( !yyparse() ) { errcode = Lexi_qnum; } else { errcode = 0; }
2177: /* fclose(Input_stream[0]);*/ /* The Lexer handles closing this */
2178: /* print_symb_stat(); */
2179: free_symtree();
2180: /*
2181: capa_mfree((char *)LexiProblem_p);
2182: LexiProblem_p = NULL;
2183: */
2184: (*problem) = FirstProblem_p;
2185: (*num_questions) = Lexi_qnum;
2186: return (errcode);
2187: }
2188:
2189: /******************************************************************************/
2190: /* PARSE SOURCE FILE AND RETURN BLOCKS OF TEXT, unlike capa_parse_student */
2191: /******************************************************************************/
2192: int
2193: capa_parse_student(set,problem,a_student,num_questions,func_ptr)
2194: int set;Problem_t **problem;T_student *a_student;int *num_questions;
2195: void (*func_ptr)();
2196: {
2197: char filename[QUARTER_K];
2198: int errcode;
2199: FILE *fp;
2200: extern FILE *Input_stream[MAX_OPENED_FILE];
2201: extern char Opened_filename[MAX_OPENED_FILE][QUARTER_K];
2202: extern int Lexi_line;
2203: extern int Lexi_qnum;
2204: extern Problem_t *FirstProblem_p;
2205: extern Problem_t *LastProblem_p;
2206: extern Problem_t *LexiProblem_p;
2207: extern char *StartText_p;
2208: extern char *EndText_p;
2209: extern char *ErrorMsg_p;
2210: extern int ErrorMsg_count;
2211: extern char Parse_class[QUARTER_K];
2212: extern int Parse_section;
2213: extern int Parse_set;
2214: extern char Parse_name[MAX_NAME_CHAR+1];
2215: extern char Parse_student_number[MAX_STUDENT_NUMBER+1];
2216: extern int Symb_count;
2217: extern int first_run;
2218: extern void (*Status_Func)();
2219: long seed1, seed2;
2220: char *class, *classname, warn_msg[WARN_MSG_LENGTH];
2221:
2222: #if defined(NeXT)
2223: char cwd[FILE_NAME_LENGTH];
2224:
2225: class = getwd(cwd);
2226: if( class == NULL ) { class = cwd; }
2227: #else
2228: class = getcwd(NULL,255);
2229:
2230: #endif
2231:
2232: if(class == NULL) { /* printf("capa_parse(): Current working directory unknown!"); */ return (-1); }
2233: classname = rindex(class,'/'); classname++; /*** hpux complained */
2234: sprintf(Parse_class,"%s", classname);
2235: free(class);
2236:
2237: sprintf(filename,"capa.config");
2238: if ((fp=fopen(filename,"r"))==NULL) {
2239: /* printf("Error: can't open %s\n",filename);*/
2240: sprintf(warn_msg,"capa_parse(): CANNOT OPEN FILE\"%s\", file does not exist or is not readable.\n", filename);
2241: capa_msg(MESSAGE_ERROR,warn_msg);
2242: return (-1);
2243: }
2244: u_getunit(fp);
2245: fclose(fp);
2246: strncpy(Parse_name,a_student->s_nm,MAX_NAME_CHAR+1);
2247: strncpy(Parse_student_number,a_student->s_sn,MAX_STUDENT_NUMBER+1);
2248: Parse_section = a_student->s_sec;
2249: if(ErrorMsg_p) { capa_mfree(ErrorMsg_p); ErrorMsg_p = NULL; }
2250: if(EndText_p) { capa_mfree(EndText_p); EndText_p = NULL; }
2251: if(StartText_p) { capa_mfree(StartText_p); StartText_p = NULL; }
2252: ErrorMsg_p = NULL; first_run = 1; EndText_p = NULL;
2253: free_symtree(); Symb_count = ErrorMsg_count = Lexi_line = Lexi_qnum = 0;
2254: FirstProblem_p = LastProblem_p = NULL;
2255: LexiProblem_p = (Problem_t *)capa_malloc(sizeof(Problem_t),1);
2256: problem_default(LexiProblem_p);
2257: /*LexiProblem_p->capaidplus=NULL;*/
2258: Parse_set = set;
2259: Status_Func=func_ptr;
2260: sprintf(filename,"set%d.qz",set);
2261: #ifdef AVOIDYYINPUT
2262: yyin=fopen(filename,"r");
2263: #else
2264: if ( (Input_stream[0]=fopen(filename,"r")) == NULL) {
2265: /* printf("Error: can't open %s\n",filename);*/
2266: sprintf(warn_msg,"capa_parse(): CANNOT OPEN FILE\"%s\", file does not exist or is not readable.\n", filename);
2267: capa_msg(MESSAGE_ERROR,warn_msg);
2268: return (-1);
2269: }
2270: #endif
2271: sprintf(Opened_filename[0],"%s",filename);
2272:
2273: capa_seed(&seed1, &seed2, a_student->s_sn); setall(seed1,seed2);
2274:
2275: yyrestart(yyin);
2276: if ( !yyparse() ) { errcode = Lexi_qnum; } else { errcode = 0; }
2277: /* fclose(Input_stream[0]);*/ /*The Lexer handles closing this*/
2278: /* print_symb_stat(); */
2279: free_symtree();
2280: /*
2281: capa_mfree((char *)LexiProblem_p);
2282: LexiProblem_p = NULL;
2283: */
2284: (*problem) = FirstProblem_p;
2285: (*num_questions) = Lexi_qnum;
2286: return (errcode);
2287: }
2288:
2289: /* =================================================================== */
2290: /* A utility method to convert a date string and time string to time_t */
2291: /* dateStr: yyyy/mm/dd */
2292: /* timeStr: hh:mm */
2293: time_t
2294: convertTime(dateStr,timeStr)char *dateStr; char *timeStr;
2295: {
2296: struct tm *theTimeData;
2297: time_t result;
2298: int dateTime[5];
2299: int year, month, day, mm, hh;
2300:
2301: sscanf(dateStr,"%4d/%2d/%2d",&year,&month,&day);
2302: dateTime[0] = month;
2303: dateTime[1] = day;
2304: dateTime[2] = year;
2305: sscanf(timeStr,"%2d:%2d",&hh,&mm);
2306: dateTime[3] = hh;
2307: dateTime[4] = mm;
2308: result = time(NULL);
2309: theTimeData = localtime(&result);
2310: theTimeData->tm_sec = 0;
2311: theTimeData->tm_min = dateTime[4];
2312: theTimeData->tm_hour = dateTime[3];
2313: theTimeData->tm_mday = dateTime[1];
2314: theTimeData->tm_mon = dateTime[0]-1;
2315: theTimeData->tm_year = dateTime[2]-1900;/* tm_year is years since 1900 */
2316: /* these fields are ignored by mktime
2317: theTimeData->tm_wday = weekday(year,month,day);
2318: theTimeData->tm_yday = julianday(year,month,day);
2319: */
2320: result = mktime( theTimeData );
2321: return (result);
2322: }
2323:
2324: int
2325: weekday( year, month, day) int year; int month; int day;
2326: {
2327: register int dow;
2328: #if defined(hpux)
2329: int juldays[13];
2330: juldays[0]=0;juldays[1]=0;juldays[2]=31;juldays[3]=59;
2331: juldays[4]=90;juldays[5]=120;juldays[6]=151;juldays[7]=181;
2332: juldays[8]=212;juldays[9]=243;juldays[10]=273;juldays[11]=304;juldays[12]=334;
2333: #else
2334: int juldays[13] = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
2335: #endif
2336:
2337: dow = 7 + year + year/4 - year/100 + year/400 + juldays[month] + day;
2338: if( (month < 3) && ( leap_year(year) ) ) dow--;
2339: dow %= 7;
2340: return (dow);
2341: } /* weekday */
2342:
2343: int
2344: julianday( year, month, day)int year;int month;int day;
2345: {
2346: register int doy;
2347: #if defined(hpux)
2348: int juldays[13];
2349: juldays[0]=0;juldays[1]=0;juldays[2]=31;juldays[3]=59;
2350: juldays[4]=90;juldays[5]=120;juldays[6]=151;juldays[7]=181;
2351: juldays[8]=212;juldays[9]=243;juldays[10]=273;juldays[11]=304;juldays[12]=334;
2352: #else
2353: int juldays[13] = {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
2354: #endif
2355:
2356: doy = juldays[month];
2357: if((month > 2) && (leap_year(year)) ) doy++;
2358: doy += day;
2359: return (doy);
2360: } /* julianday */
2361:
2362: int
2363: check_int( an_int ) char *an_int;
2364: {
2365: int ii, leng;
2366: int result=0;
2367:
2368: if( (an_int[0] == '-') || (an_int[0]== '+') ) an_int++;
2369: leng = strlen(an_int);
2370: for(ii=0;ii<leng;ii++) {
2371: if( !isdigit(an_int[ii]) ) result = 1;
2372: }
2373: return (result);
2374: }
2375: /* --------------------------- */
2376: /* 0 OK , 1 NOT a real number */
2377: int
2378: check_real( a_real ) char *a_real;
2379: {
2380: int ii, leng;
2381: int result=0;
2382:
2383: if( (a_real[0] == '-') || (a_real[0]== '+') ) a_real++;
2384: leng = strlen(a_real);
2385: for(ii=0;ii<leng;ii++) {
2386: if( (!isdigit(a_real[ii])) && (a_real[ii]!='e') && (a_real[ii]!='E') &&
2387: (a_real[ii]!='.') && (a_real[ii]!='+') && (a_real[ii]!='-') ) result = 1;
2388: }
2389: return (result);
2390: }
2391:
2392: int
2393: check_input_usymb(u_symb)char *u_symb;
2394: {
2395: int result=0;
2396:
2397:
2398: return (result);
2399: }
2400:
2401: /* <== This routine determine emperically where to split a character */
2402: /* string into two portions, one for numerical answer and the */
2403: /* other for units */
2404: /* ----------------------------------------------------------------- */
2405: /* inputs : buf : answer string */
2406: /* outputs: num : the numerical part */
2407: /* num_p : the numerical part in string */
2408: /* unit_p : the unit string */
2409: /* num_p is used to calculate sig figs */
2410: /* return : 0 empty string */
2411: /* 1 number without units */
2412: /* 2 empty number with units */
2413: /* 3 number with units */
2414: /* */
2415: int split_num_unit(buf,num,num_p,unit_p)
2416: char *buf;double *num; char *num_p; char *unit_p;
2417: {
2418: char num_str[ANSWER_STRING_LENG], unit_str[ANSWER_STRING_LENG];
2419: char base_str[ANSWER_STRING_LENG], exp_str[ANSWER_STRING_LENG];
2420: int idx=0, errcode=0;
2421: int len, ii, n_idx=0, b_idx=0, e_idx=0, u_idx=0;
2422: double n_part, x_part, b_part, e_part, result;
2423:
2424: unit_str[0]=0; /* initialize unit_str[] */
2425: len = strlen(buf);
2426: while( isspace(buf[idx]) ) { idx++; } /* ignore white spaces */
2427: num_str[n_idx]=0; /* initialize number string */
2428: if( buf[idx] == '+' || buf[idx] == '-' ) {
2429: /* the first char is either '+' or '-' */
2430: num_str[n_idx++]= buf[idx++];
2431: }
2432: /* skip over alphabet char and those that are not '.' */
2433: while( (!isdigit( buf[idx] )) && buf[idx] != '.' ) { idx++; }
2434: while( isdigit( buf[idx] ) || buf[idx] == '.' ) { /* collect decimal numbers */
2435: num_str[n_idx++]= buf[idx++];
2436: }
2437: num_str[n_idx] = 0; /* end the string with a '\0' */
2438: sprintf(num_p,"%s",num_str); /* put the collected numerical string in num_p */
2439: /* skip over white spaces */
2440: while( isspace(buf[idx]) ) { idx++; }
2441: if( buf[idx] == 'e' || buf[idx] == 'E' ) { /* optional e or E part */
2442: /* peek further one char to see if it belongs to one of the following */
2443: if( buf[idx+1] == '-' || buf[idx+1] == '+' || isspace(buf[idx+1]) || isdigit(buf[idx+1])) {
2444: num_str[n_idx++] = buf[idx++]; /* should be 'e' or 'E' */
2445: while( isspace(buf[idx]) ) { idx++; } /* skip over spaces */
2446: num_str[n_idx++] = buf[idx++]; /* the second char '-', '+' or digit */
2447: while( isdigit(buf[idx]) ) { /* only integer is allowed, not '.' */
2448: num_str[n_idx++] = buf[idx++];
2449: }
2450: }
2451: num_str[n_idx] = 0; /* terminiate the numerical string */
2452: while( isspace(buf[idx]) ) { idx++; }
2453: sscanf(num_str, "%lg", &result); /* put the numerical value into a double variable */
2454: errcode = errcode | 1;
2455: } else if( buf[idx] == 'x' || buf[idx] == 'X') { /* optional x or X part */
2456: idx++; /* skip x or X */
2457: while( isspace(buf[idx]) ) { idx++; }
2458:
2459: e_part = 1.0; /* default power */
2460: base_str[b_idx] = 0; /* initialize base_str[] */
2461: while( isdigit(buf[idx]) || buf[idx] == '.' ) { /* should start with a digit or . */
2462: base_str[b_idx++] = buf[idx++];
2463: }
2464: base_str[b_idx] = 0; /* terminate base_str[] */
2465: while( isspace(buf[idx]) ) { idx++; } /* skip over white spaces */
2466: if( buf[idx] == '^' ) { /* power */
2467: idx++;
2468: exp_str[e_idx] = 0; /* initialize exp_str[] */
2469: while( isspace(buf[idx]) ) { idx++; }
2470: if( buf[idx] == '{'|| buf[idx] == '(' ) { /* matching right bracket */
2471: idx++;
2472: }
2473: while( isspace(buf[idx]) ) { idx++; }
2474: if( isdigit(buf[idx]) || buf[idx] == '+' || buf[idx] == '-' ) {
2475: exp_str[e_idx] = 0; /* initialize exp_str[], again */
2476: while( isdigit(buf[idx]) || buf[idx] == '.' || buf[idx] == '+' || buf[idx] == '-' ) {
2477: exp_str[e_idx++] = buf[idx++];
2478: }
2479: exp_str[e_idx] = 0; /* terminate exp_str[] */
2480: }
2481: while( isspace(buf[idx]) ) { idx++; }
2482: if( buf[idx] == '}' || buf[idx] == ')' ) {
2483: idx++;
2484: }
2485: sscanf(exp_str, "%lg", &e_part);
2486: }
2487: if( strlen(base_str) > 0 ) {
2488: sscanf(base_str, "%lg", &b_part);
2489: x_part = pow(b_part, e_part);
2490: } else {
2491: x_part = 0.0;
2492: }
2493: if( strlen(num_str) > 0 ) {
2494: sscanf(num_str, "%lg", &n_part);
2495: } else {
2496: n_part=0.0;
2497: }
2498: result = n_part * x_part;
2499: errcode = errcode | 1;
2500: } else if ( buf[idx] == '^' ) { /* number ^ */
2501: idx++;
2502: e_part = 1.0;
2503: while( isspace(buf[idx]) ) { idx++; }
2504: if( buf[idx] == '{'|| buf[idx] == '(' ) { /* matching right bracket */
2505: idx++;
2506: }
2507: while( isspace(buf[idx]) ) { idx++; }
2508: if( isdigit(buf[idx]) || buf[idx] == '+' || buf[idx] == '-' ) {
2509: exp_str[e_idx] = 0;
2510: while( isdigit(buf[idx]) || buf[idx] == '.' || buf[idx] == '+' || buf[idx] == '-' ) {
2511: exp_str[e_idx++] = buf[idx++];
2512: }
2513: exp_str[e_idx] = 0;
2514: }
2515: while( isspace(buf[idx]) ) { idx++; }
2516: if( buf[idx] == '}' || buf[idx] == ')' ) {
2517: idx++;
2518: }
2519: sscanf(exp_str, "%lg", &e_part);
2520: sscanf(num_str, "%lg", &n_part);
2521: result = pow(n_part,e_part);
2522: errcode = errcode | 1;
2523: } else { /* number unit */
2524: if( strlen(num_str) > 0 ) {
2525: sscanf(num_str, "%lg", &result);
2526: errcode = errcode | 1;
2527: }
2528: }
2529:
2530: if( idx < len ) { /* collect the rest as unit string */
2531: for(ii=idx;ii< len; ii++ ) {
2532:
2533: unit_str[u_idx++] = buf[ii];
2534: }
2535: unit_str[u_idx]=0; /* terminate unit_str[] */
2536: if(u_idx>0) {
2537: errcode = errcode | 2;
2538: }
2539: }
2540: if( strlen(num_str) > 0 ) {
2541: *num = result;
2542: } else { /* empty number string */
2543: *num = 0.0;
2544: }
2545: sprintf(unit_p,"%s", unit_str);
2546: return (errcode);
2547: }
2548:
2549: char *
2550: answers_string(mode, p)int mode;Problem_t *p;
2551: {
2552: char *fmted_ans, lower[ANSWER_STRING_LENG], upper[ANSWER_STRING_LENG];
2553: char *str_aa, *str_bb, *str_cc, *ans_str, *sub_ans_str, *tmp_str;
2554: int len_aa=0, len_bb=0, len_cc=0,len_dd=0, total_len, num_answer;
2555: double d_answer;
2556:
2557: if( p->ans_type == ANSWER_IS_SUBJECTIVE ) {
2558: char *a="Subjective Answer\n";
2559: ans_str = (char *)capa_malloc(strlen(a)+1,1);
2560: strcpy(ans_str,a);
2561: return (ans_str);
2562: }
2563: num_answer = calc_ansrange(p->ans_type,p->calc, p->answer, p->ans_fmt, p->tol_type,
2564: p->tolerance, lower, upper);
2565:
2566: if( p->ans_type == ANSWER_IS_FLOAT ) {
2567: fmted_ans = capa_malloc(SMALL_LINE_BUFFER,1);
2568: d_answer = (double)atof(p->answer);
2569: sprintf(fmted_ans,p->ans_fmt,d_answer);
2570: } else {
2571: fmted_ans = capa_malloc(strlen(p->answer)+2,1);
2572: strcpy(fmted_ans,p->answer);
2573: }
2574:
2575: len_aa = strlen(fmted_ans);
2576: if (lower != NULL ) len_bb = strlen(lower); else len_bb = 0;
2577: if (upper != NULL ) len_cc = strlen(upper); else len_cc = 0;
2578: if ( p->unit_str != NULL ) len_dd = strlen(p->unit_str); else len_dd = 0;
2579:
2580: switch(mode) {
2581: case TeX_MODE:
2582: if(num_answer==2) {
2583: /* 16 is by adding up characters ' [,] \n\n' and others */
2584: str_aa = format_toTeX(fmted_ans);
2585: total_len = strlen(str_aa) + len_dd + 16;
2586: str_bb = format_toTeX(lower);
2587: total_len += strlen(str_bb);
2588: str_cc = format_toTeX(upper);
2589: total_len += strlen(str_cc);
2590: ans_str = (char *)capa_malloc(total_len,1);
2591: if(len_dd == 0 ) { /* no unit_str */
2592: sprintf(ans_str," %s [%s,%s]\n\n", str_aa,str_bb,str_cc);
2593: } else {
2594: sprintf(ans_str," %s [%s,%s] $%s$\n\n", str_aa,str_bb,str_cc,p->unit_str);
2595: }
2596: capa_mfree((char *)str_aa);
2597: capa_mfree((char *)str_bb);
2598: capa_mfree((char *)str_cc);
2599: } else { /* only one answer */
2600: if ( (p->ans_type == ANSWER_IS_INTEGER) ||
2601: (p->ans_type == ANSWER_IS_FLOAT )) {
2602: str_bb = format_toTeX(lower);
2603: } else { /* answer could be string, choice */
2604: str_bb = (char *)capa_malloc(strlen(lower)+MAX_BUFFER_SIZE,1);
2605: if (p->ans_type == ANSWER_IS_FORMULA || 1)
2606: sprintf(str_bb,"\\begin{verbatim}%s\\end{verbatim}",lower);
2607: else
2608: strcpy(str_bb,lower);
2609: }
2610: total_len = strlen(str_bb) + len_dd + 8;
2611: /* 4 is by adding up characters ' \\\n' plus four */
2612: ans_str = (char *)capa_malloc(sizeof(char),total_len);
2613: if(len_dd == 0 ) { /* no unit_str */
2614: sprintf(ans_str," %s\n", str_bb);
2615: } else {
2616: sprintf(ans_str," %s $%s$\n", str_bb,p->unit_str);
2617: }
2618: capa_mfree((char *)str_bb);
2619: }
2620: break;
2621: case ASCII_MODE:
2622: total_len = len_aa + len_bb + len_cc + len_dd + 8;
2623: /* 8 is by adding up characters ' [,] \n\n' plus one */
2624: ans_str = (char *)capa_malloc(sizeof(char),total_len);
2625: if(num_answer==2) {
2626: if(len_dd == 0 ) { /* no unit_str */
2627: sprintf(ans_str,"%s [%s,%s]\n\n", fmted_ans,lower,upper);
2628: } else {
2629: sprintf(ans_str,"%s [%s,%s] %s\n\n", fmted_ans,lower,upper,p->unit_str);
2630: }
2631: } else {
2632: if(len_dd == 0 ) { /* no unit_str */
2633: sprintf(ans_str,"%s\n\n", lower);
2634: } else {
2635: sprintf(ans_str,"%s %s\n\n", lower,p->unit_str);
2636: }
2637: }
2638: break;
2639: case ANSWER_STRING_MODE:
2640: total_len = len_aa + len_bb + len_cc + len_dd + 8;
2641: /* 8 is by adding up characters ' [,] \n\n' plus one */
2642: ans_str = (char *)capa_malloc(sizeof(char),total_len);
2643: if(num_answer==2) {
2644: if(len_dd == 0 ) { /* no unit_str */
2645: sprintf(ans_str,"%s", fmted_ans);
2646: } else {
2647: sprintf(ans_str,"%s %s", fmted_ans,p->unit_str);
2648: }
2649: } else {
2650: if(len_dd == 0 ) { /* no unit_str */
2651: sprintf(ans_str,"%s", lower);
2652: } else {
2653: sprintf(ans_str,"%s %s", lower,p->unit_str);
2654: }
2655: }
2656: break;
2657: case HTML_MODE:
2658: if(num_answer==2) { /* this indicates that answer should be either float or int
2659: */
2660: str_aa = format_toHTML(fmted_ans);
2661: total_len = strlen(str_aa) + len_dd + 8;
2662: str_bb = format_toHTML(lower);
2663: total_len += strlen(str_bb);
2664: str_cc = format_toHTML(upper);
2665: total_len += strlen(str_cc);
2666: /* 8 is by adding up characters ' [,] \n\n' plus one */
2667: ans_str = (char *)capa_malloc(sizeof(char),total_len);
2668: if(len_dd == 0 ) { /* no unit_str */
2669: sprintf(ans_str,"%s [%s,%s]\n\n", str_aa,str_bb,str_cc);
2670: } else {
2671: sprintf(ans_str,"%s [%s,%s] %s\n\n", str_aa,str_bb,str_cc,p->unit_str);
2672: }
2673: capa_mfree((char *)str_aa); capa_mfree((char *)str_bb); capa_mfree((char
2674: *)str_cc);
2675: } else {
2676: if ( (p->ans_type == ANSWER_IS_INTEGER) ||
2677: (p->ans_type == ANSWER_IS_FLOAT )) {
2678: str_bb = format_toHTML(lower);
2679: } else { /* answer could be string, choice */
2680: str_bb = (char *)capa_malloc(strlen(lower)+MAX_BUFFER_SIZE,1);
2681: if (p->ans_type == ANSWER_IS_FORMULA || 1)
2682: sprintf(str_bb,"<PRE>\n%s\n</PRE>",lower);
2683: else
2684: strcpy(str_bb,lower);
2685: }
2686: total_len = strlen(str_bb) + len_dd + 4;
2687: /* 4 is by adding up characters ' \n\n' plus one */
2688: ans_str = (char *)capa_malloc(sizeof(char),total_len);
2689: if(len_dd == 0 ) { /* no unit_str */
2690: sprintf(ans_str,"%s\n\n", str_bb);
2691: } else {
2692: sprintf(ans_str,"%s %s\n\n", str_bb,p->unit_str);
2693: }
2694: capa_mfree((char *)str_bb);
2695: }
2696: break;
2697: }
2698: capa_mfree(fmted_ans);
2699:
2700: if( p->ans_cnt > 1 ) {
2701: AnswerInfo_t *ai;
2702: for( ai = p->ans_list; ai; ai = ai->ans_next) {
2703: num_answer = calc_ansrange(ai->ans_type,ai->ans_calc, ai->ans_str, ai->ans_fmt,
2704: ai->ans_tol_type,ai->ans_tol,lower,upper);
2705: if( ai->ans_type == ANSWER_IS_FLOAT ) {
2706: fmted_ans = capa_malloc(SMALL_LINE_BUFFER,1);
2707: d_answer = (double)atof(ai->ans_str);
2708: sprintf(fmted_ans,ai->ans_fmt,d_answer);
2709: } else {
2710: fmted_ans = capa_malloc(strlen(ai->ans_str)+2,1);
2711: strcpy(fmted_ans,ai->ans_str);
2712: }
2713: len_aa = strlen(fmted_ans);
2714: len_bb = strlen(lower);
2715: len_cc = strlen(upper);
2716: len_dd = strlen(ai->ans_unit_str);
2717: switch(mode) {
2718: case TeX_MODE:
2719: if(num_answer==2) {
2720: /* 16 is by adding up characters ' [,] \n\n' and others */
2721:
2722: str_aa = format_toTeX(fmted_ans);
2723: total_len = strlen(str_aa) + len_dd + 16;
2724: str_bb = format_toTeX(lower);
2725: total_len += strlen(str_bb);
2726: str_cc = format_toTeX(upper);
2727: total_len += strlen(str_cc);
2728:
2729: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
2730:
2731: if(len_dd == 0 ) { /* no unit_str */
2732: sprintf(sub_ans_str," %s [%s,%s]\n\n", str_aa,str_bb,str_cc);
2733: } else {
2734: sprintf(sub_ans_str," %s [%s,%s] $%s$\n\n",
2735: str_aa,str_bb,str_cc,ai->ans_unit_str);
2736: }
2737: capa_mfree((char *)str_aa); capa_mfree((char *)str_bb); capa_mfree((char *)str_cc);
2738: } else { /* only one answer */
2739: if ( (ai->ans_type == ANSWER_IS_INTEGER) ||
2740: (ai->ans_type == ANSWER_IS_FLOAT )) {
2741: str_bb = format_toTeX(lower);
2742: } else { /* answer could be string, choice */
2743: str_bb = (char *)capa_malloc(strlen(lower)+MAX_BUFFER_SIZE,1);
2744: if (ai->ans_type == ANSWER_IS_FORMULA || 1)
2745: sprintf(str_bb,"\\begin{verbatim}%s\\end{verbatim}",lower);
2746: else
2747: strcpy(str_bb,lower);
2748: }
2749: total_len = strlen(str_bb) + len_dd + 8;
2750: /* 4 is by adding up characters ' \\\n' plus four */
2751: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
2752: if(len_dd == 0 ) { /* no unit_str */
2753: sprintf(sub_ans_str," %s\n", str_bb);
2754: } else {
2755: sprintf(sub_ans_str," %s $%s$\n", str_bb,ai->ans_unit_str);
2756: }
2757: capa_mfree((char *)str_bb);
2758: }
2759: break;
2760: case ASCII_MODE:
2761: total_len = len_aa + len_bb + len_cc + len_dd + 8;
2762: /* 8 is by adding up characters ' [,] \n\n' plus one */
2763: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
2764: if(num_answer==2) {
2765: if(len_dd == 0 ) { /* no unit_str */
2766: sprintf(sub_ans_str,"%s [%s,%s]\n\n", fmted_ans,lower,upper);
2767: } else {
2768: sprintf(sub_ans_str,"%s [%s,%s] %s\n\n",
2769: fmted_ans,lower,upper,ai->ans_unit_str);
2770: }
2771: } else {
2772: if(len_dd == 0 ) { /* no unit_str */
2773: sprintf(sub_ans_str,"%s\n\n", lower);
2774: } else {
2775: sprintf(sub_ans_str,"%s %s\n\n", lower,ai->ans_unit_str);
2776: }
2777: }
2778: break;
2779: case ANSWER_STRING_MODE:
2780: total_len = len_aa + len_bb + len_cc + len_dd + 8;
2781: /* 8 is by adding up characters ' [,] \n\n' plus one */
2782: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
2783: if(num_answer==2) {
2784: if(len_dd == 0 ) { /* no unit_str */
2785: sprintf(sub_ans_str,", %s", fmted_ans);
2786: } else {
2787: sprintf(sub_ans_str,", %s %s", fmted_ans,ai->ans_unit_str);
2788: }
2789: } else {
2790: if(len_dd == 0 ) { /* no unit_str */
2791: sprintf(sub_ans_str,", %s", lower);
2792: } else {
2793: sprintf(sub_ans_str,", %s %s", lower,ai->ans_unit_str);
2794: }
2795: }
2796: break;
2797: case HTML_MODE:
2798: if(num_answer==2) {
2799: str_aa = format_toHTML(fmted_ans);
2800: total_len = strlen(str_aa) + len_dd + 8;
2801: str_bb = format_toHTML(lower);
2802: total_len += strlen(str_bb);
2803: str_cc = format_toHTML(upper);
2804: total_len += strlen(str_cc);
2805: /* 8 is by adding up characters ' [,] \n\n' plus one */
2806: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
2807: if(len_dd == 0 ) { /* no unit_str */
2808: sprintf(sub_ans_str,"%s [%s,%s]\n\n", str_aa,str_bb,str_cc);
2809: } else {
2810: sprintf(sub_ans_str,"%s [%s,%s] %s\n\n",
2811: str_aa,str_bb,str_cc,ai->ans_unit_str);
2812: }
2813: capa_mfree((char *)str_aa); capa_mfree((char *)str_bb); capa_mfree((char
2814: *)str_cc);
2815: } else {
2816: if ( (ai->ans_type == ANSWER_IS_INTEGER) ||
2817: (ai->ans_type == ANSWER_IS_FLOAT )) {
2818: str_bb = format_toHTML(lower);
2819: } else { /* answer could be string, choice */
2820: str_bb = (char *)capa_malloc(strlen(lower)+MAX_BUFFER_SIZE,1);
2821: if (ai->ans_type == ANSWER_IS_FORMULA || 1)
2822: sprintf(str_bb,"<PRE>\n%s\n</PRE>",lower);
2823: else
2824: strcpy(str_bb,lower);
2825: }
2826: total_len = strlen(str_bb) + len_dd + 4;
2827: /* 4 is by adding up characters ' \n\n' plus one */
2828: sub_ans_str = (char *)capa_malloc(sizeof(char),total_len);
2829: if(len_dd == 0 ) { /* no unit_str */
2830: sprintf(sub_ans_str,"%s\n\n", str_bb);
2831: } else {
2832: sprintf(sub_ans_str,"%s %s\n\n", str_bb,ai->ans_unit_str);
2833: }
2834: capa_mfree((char *)str_bb);
2835: }
2836: break;
2837: } /* end of switch */
2838: total_len = strlen(ans_str);
2839: total_len += (strlen(sub_ans_str) + 1);
2840: tmp_str = (char *)capa_malloc(sizeof(char),total_len);
2841: strncpy(tmp_str, ans_str, strlen(ans_str)+1);
2842: strcat(tmp_str, sub_ans_str);
2843: capa_mfree(ans_str); capa_mfree(sub_ans_str);
2844: capa_mfree(fmted_ans);
2845: ans_str = tmp_str;
2846: } /* end of for */
2847: } /* end of if */
2848:
2849: return (ans_str); /* the calling routing needs to deallocate it */
2850: }
2851:
2852:
2853:
2854: /* ------------------------------ called from capalogin */
2855: /* impose stronger checking on the user input string *answer */
2856: /* */
2857:
2858: /* <== This routine checks user input string *ans against correct answer *s ==> */
2859: int
2860: capa_check_ans(ai,ans) AnswerInfo_t *ai; char *ans;
2861: {
2862: int t; /* ans_type */
2863: char *s; /* ans_str */
2864: int c; /* ans_calc */
2865: int tt; /* ans_tol_type */
2866: double to; /* ans_tol */
2867: int su; /* ans_sig_ub */
2868: int sl; /* ans_sig_lb */
2869: char *fm; /* ans_fmt */
2870: char *us; /* ans_unit_str */
2871: Unit_t *u_p; /* ans_unit */
2872: int input_len, all_alphabet = 1, idx, ii, type;
2873: int outcome, result = INCORRECT;
2874: int sig, corr_len;
2875: int choice[ANSWER_STRING_LENG];
2876: char num_str[ANSWER_STRING_LENG], unit_str[ANSWER_STRING_LENG];
2877: char fmted[ANSWER_STRING_LENG], correct[ANSWER_STRING_LENG], answer[ANSWER_STRING_LENG];
2878: double n_part;
2879: double given, target, ratio, fmted_target, target_u, target_l, scale=1.0;
2880: double delta;
2881:
2882: t = ai->ans_type; s = ai->ans_str; c = ai->ans_calc;
2883: tt = ai->ans_tol_type; to = ai->ans_tol;
2884: su = ai->ans_sig_ub; sl = ai->ans_sig_lb;
2885: fm = ai->ans_fmt;
2886: us = ai->ans_unit_str; u_p = ai->ans_unit;
2887:
2888: switch(t) {
2889: case ANSWER_IS_INTEGER:
2890: case ANSWER_IS_FLOAT:
2891: {
2892: input_len = strlen(ans);
2893: all_alphabet = 1;
2894: for(idx=0;idx<input_len;idx++) {
2895: if( isdigit(ans[idx]) ) {
2896: all_alphabet = 0;
2897: }
2898: }
2899: if( !all_alphabet ) { /* answer string is not all alphabets */
2900: outcome = split_num_unit(ans,&n_part,num_str,unit_str);
2901: if( outcome > 1 ) { /* with both num and unit parts or only unit part */
2902: if( u_p != NULL ) {
2903: result = check_correct_unit(unit_str,u_p,&scale);
2904: } else { /* what to do when no unit is specified but student entered a unit? */
2905: result = UNIT_NOTNEEDED;
2906: }
2907: } else {
2908: if( u_p != NULL ) {
2909: result = NO_UNIT;
2910: }
2911: }
2912: if( (result != NO_UNIT) && (result != UNIT_FAIL) && ( result != UNIT_NOTNEEDED) ) {
2913: if( t == ANSWER_IS_FLOAT ) {
2914: target = (double)atof(s); /* real number */
2915: } else {
2916: target = (double)atol(s); /* Integer answer */
2917: }
2918: given = n_part * scale; /* convert the given answer into proper scale for units */
2919: sig = calc_sig( num_str );
2920: if( (sig < sl) || (sig > su) ) {
2921: result = SIG_FAIL;
2922: } else {
2923: switch( tt ) { /* tolerence type */
2924: case TOL_ABSOLUTE:
2925: fmted_target = target; /* if answer type is integer */
2926: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
2927: sprintf(fmted, fm, target);
2928: fmted_target = (double)atof(fmted);
2929: }
2930: to = fabs(to); /* tol must be positive */
2931: if( c == CALC_FORMATED) {
2932: target_l = fmted_target - to; target_u = fmted_target + to;
2933: } else {
2934: target_l = target - to; target_u = target + to;
2935: }
2936: if( (given >= target_l) && (given <= target_u) ) {
2937: result = APPROX_ANS;
2938: } else { result = INCORRECT; }
2939: break;
2940: case TOL_PERCENTAGE:
2941: if( target != 0.0 ) {
2942: ratio = (double)(to / 100.0);
2943: fmted_target = target; /* if answer type is integer */
2944: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
2945: sprintf(fmted, fm, target);
2946: fmted_target = (double)atof(fmted);
2947: }
2948: delta = (double)fabs((double)ratio*target);
2949: if( c == CALC_FORMATED) {
2950: target_l = fmted_target - delta; target_u = fmted_target + delta;
2951: } else {
2952: target_l = target - delta; target_u = target + delta;
2953: }
2954: } else { target_l = target_u = target; }
2955: if ( (given >= target_l) && (given <= target_u) ) {
2956: result = APPROX_ANS;
2957: } else { result = INCORRECT; }
2958: break;
2959: }
2960: } /* end sig check */
2961: } /* end if unit check */
2962: } else { /* user entered alphabets, but no number */
2963: result = INCORRECT;
2964: }
2965: }
2966: break;
2967: case ANSWER_IS_CHOICE:
2968: {
2969: corr_len = strlen(s); input_len = strlen(ans);
2970: if( corr_len == input_len ) {
2971: for(idx=0;idx<ANSWER_STRING_LENG;idx++) choice[idx] = 0;
2972: result = EXACT_ANS;
2973: for(ii=0;ii<corr_len; ii++) {
2974: idx = toupper(correct[ii]) - 'A'; choice[idx] = 1;
2975: }
2976: for(ii=0;ii<input_len;ii++) {
2977: idx = toupper(answer[ii]) - 'A';
2978: if(choice[idx] != 1 ) result = INCORRECT;
2979: }
2980: } else { result = INCORRECT; }
2981: break;
2982: }
2983: case ANSWER_IS_STRING_CI:
2984: if (strcasecmp(ans, s)) { result = INCORRECT; } else { result = EXACT_ANS; }
2985: break;
2986: case ANSWER_IS_STRING_CS:
2987: if (strcmp(ans, s)) { result = INCORRECT; } else { result = EXACT_ANS; }
2988: break;
2989: case ANSWER_IS_FORMULA:
2990: result = check_formula_ans(s,ans,ai->ans_id_list,ai->ans_pts_list,tt,to);
2991: break;
2992: case ANSWER_IS_EXTERNAL: /* Not yet implemented */
2993: break;
2994: }
2995: return (result);
2996: }
2997:
2998: /* =============================================================================== */
2999: /* calling sequence capa_check_answers() --> capa_check_answer() */
3000: /* --> capa_check_ans() */
3001:
3002:
3003: /* How we check the correct answer against user input string */
3004: /*
3005: If the correct answer is a number (either integer or real number)
3006: check if user input string consists of only alphabet characters
3007: use split_num_unit() heuristic function to split the input string into two parts
3008: numerical part and units part.
3009: if the outcome contains units, check if the units is correct or not
3010:
3011: */
3012:
3013:
3014: int
3015: capa_check_answer(p, answer) Problem_t *p; char *answer;
3016: {
3017: int type;
3018: char *correct;
3019: char input[ANSWER_STRING_LENG], unit_str[ANSWER_STRING_LENG];
3020: int tol_type, calc_type;
3021: double tol, n_part;
3022: int sig_l;
3023: int sig_u;
3024: char *fmt;
3025: int choice[ANSWER_STRING_LENG], ii, idx, corr_len, input_len;
3026: int result = INCORRECT, sig, outcome, all_alphabet;
3027: char fmted[FORMAT_STRING_LENG];
3028: double given, target, ratio, fmted_target, target_u, target_l, scale=1.0;
3029: double delta;
3030:
3031: type = p->ans_type;
3032: correct = p->answer;
3033: tol_type = p->tol_type;
3034: tol = p->tolerance;
3035: sig_l = p->sig_lbound;
3036: sig_u = p->sig_ubound;
3037: fmt = p->ans_fmt;
3038: calc_type = p->calc;
3039: unit_str[0]=0;
3040:
3041: switch(type) {
3042: case ANSWER_IS_INTEGER:
3043: case ANSWER_IS_FLOAT:
3044: {
3045: input_len = strlen(answer);
3046: all_alphabet = 1;
3047: for(idx=0;idx<input_len;idx++) {
3048: if( isdigit(answer[idx]) ) {
3049: all_alphabet = 0;
3050: }
3051: }
3052: if( !all_alphabet ) {
3053: outcome = split_num_unit(answer,&n_part,input,unit_str);
3054: if( outcome > 1 ) { /* with both num and unit parts or only unit part */
3055: if( p->ans_unit != NULL ) {
3056: result = check_correct_unit(unit_str,p->ans_unit,&scale);
3057:
3058: } else { /* what to do when no unit is specified but student entered a unit? */
3059: result = UNIT_NOTNEEDED;
3060: }
3061: } else {
3062: if( p->ans_unit != NULL ) {
3063: result = NO_UNIT;
3064: }
3065: }
3066: if( (result != NO_UNIT) && (result != UNIT_FAIL) && ( result != UNIT_NOTNEEDED) ) {
3067: if( type == ANSWER_IS_FLOAT ) {
3068: target = (double)atof(correct); /* real number */
3069: } else {
3070: target = (double)atol(correct); /* Integer answer */
3071: }
3072: given = n_part * scale; /* convert the given answer into proper scale for units */
3073: sig = calc_sig( input );
3074: if( (sig < sig_l) || (sig > sig_u) ) {
3075: result = SIG_FAIL;
3076: } else {
3077: switch( tol_type ) {
3078: case TOL_ABSOLUTE:
3079: fmted_target = target; /* if answer type is integer */
3080: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
3081: sprintf(fmted, fmt, target);
3082: fmted_target = (double)atof(fmted);
3083: }
3084: tol = fabs(tol); /* tol must be positive */
3085: if( calc_type == CALC_FORMATED) {
3086: target_l = fmted_target - tol; target_u = fmted_target + tol;
3087: } else {
3088: target_l = target - tol; target_u = target + tol;
3089: }
3090: if( (given >= target_l) && (given <= target_u) ) {
3091: result = APPROX_ANS;
3092: } else { result = INCORRECT; }
3093: break;
3094: case TOL_PERCENTAGE:
3095: if( target != 0.0 ) {
3096: ratio = (double)(tol / 100.0);
3097: fmted_target = target; /* if answer type is integer */
3098: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
3099: sprintf(fmted, fmt, target);
3100: fmted_target = (double)atof(fmted);
3101: }
3102: delta = (double)fabs((double)ratio*target);
3103: if( calc_type == CALC_FORMATED) {
3104: target_l = fmted_target - delta; target_u = fmted_target + delta;
3105: } else {
3106: target_l = target - delta; target_u = target + delta;
3107: }
3108: } else { target_l = target_u = target; }
3109: if ( (given >= target_l) && (given <= target_u) ) {
3110: result = APPROX_ANS;
3111: } else { result = INCORRECT; }
3112: break;
3113: }
3114: } /* end sig check */
3115: } /* end if unit check */
3116: } else { /* user entered alphabet, but no number */
3117: result = INCORRECT;
3118: }
3119: }
3120: break;
3121: case ANSWER_IS_CHOICE:
3122: {
3123: corr_len = strlen(correct); input_len = strlen(answer);
3124: if( corr_len == input_len ) {
3125: for(ii=0;ii<ANSWER_STRING_LENG;ii++) choice[ii] = 0; result = EXACT_ANS;
3126: for(ii=0;ii<corr_len; ii++) {
3127: idx = toupper(correct[ii]) - 'A'; choice[idx] = 1;
3128: }
3129: for(ii=0;ii<input_len;ii++) {
3130: idx = toupper(answer[ii]) - 'A';
3131: if(choice[idx] != 1 ) result = INCORRECT;
3132: }
3133: } else { result = INCORRECT; }
3134: break;
3135: }
3136: case ANSWER_IS_STRING_CI:
3137: if (strcasecmp(answer, correct)) { result = INCORRECT; } else { result = EXACT_ANS; }
3138: break;
3139: case ANSWER_IS_STRING_CS:
3140: if (strcmp(answer, correct)) { result = INCORRECT; } else { result = EXACT_ANS; }
3141: break;
3142: case ANSWER_IS_FORMULA:
3143: result = check_formula_ans(correct,answer,p->id_list,p->pts_list,tol_type,tol);
3144: break;
3145: case ANSWER_IS_EXTERNAL: /* not yet implemented */
3146: break;
3147:
3148: }
3149: return (result);
3150: }
3151:
3152: /* ----------------------------------------------------------------------------------- */
3153: /* assumming the formula is *fml_str and the student input is *input_str */
3154: /* according to the type of tolerance, we form the final formula as */
3155: /* absolute tolerance: (*fml_str) - (*input_str) */
3156: /* relative tolerance: (*input_str) / (*fml_str) */
3157: int
3158: check_formula_ans(fml_str,input_str,var_list,pts_list,tol_type,tol)
3159: char *fml_str;char *input_str;char *var_list;PointsList_t *pts_list;int tol_type; double tol;
3160: {
3161: char *check_fml_str;
3162: int f_len, i_len, outcome, error_code;
3163: PointsList_t *pt, *next;
3164: double formula_val, diff;
3165:
3166: f_len = strlen(fml_str);
3167: i_len = strlen(input_str);
3168:
3169: check_fml_str = (char *)capa_malloc((f_len + i_len + 16), sizeof(char));
3170: if( tol_type == TOL_ABSOLUTE ) {
3171: sprintf(check_fml_str,"abs((%s) - (%s))",fml_str, input_str);
3172: } else {
3173: sprintf(check_fml_str,"(%s) / (%s)",input_str,fml_str);
3174: }
3175: outcome = APPROX_ANS;
3176: for(pt= pts_list; pt!=NULL ; pt=next) {
3177: next=pt->pts_next;
3178: error_code = f_eval_formula(&formula_val,check_fml_str, var_list, pt->pts_str);
3179: if( ! error_code ) {
3180: if( tol_type == TOL_ABSOLUTE ) {
3181: diff = tol - formula_val;
3182: if( diff < 0.0 ) {
3183: outcome = INCORRECT;
3184: }
3185: } else {
3186: diff = abs(1.0 - formula_val) * 100.0 ;
3187: if( diff < tol ) {
3188: outcome = INCORRECT;
3189: }
3190: }
3191: } else {
3192: outcome = BAD_FORMULA;
3193: break;
3194: }
3195: }
3196: capa_mfree((char *)check_fml_str);
3197:
3198: return (outcome);
3199:
3200: }
3201: /* inputs: type :: answer type, calc_type :: input string format string tolerance type */
3202: /* returns: lower upper */
3203:
3204: int
3205: calc_ansrange(type, calc_type, input, fmt, tol_type, tol, lower, upper)
3206: int type;int calc_type;char *input;char *fmt;
3207: int tol_type;double tol;char *lower;char *upper;
3208: {
3209: int result = 2, leng;
3210: char fmted[ANSWER_STRING_LENG];
3211: double target, fmted_target, ratio, target_l, target_u, tmp, delta;
3212:
3213:
3214: if( (type == ANSWER_IS_FORMULA) ||
3215: (type == ANSWER_IS_EXTERNAL ) ) {
3216: strcpy(lower, input);
3217: result = 1;
3218: return (result);
3219: } else {
3220: if( tol == 0.0 ) { /* answer could be ANSWER_IS_FLOAT ANSWER_IS_INTEGER,
3221: ANSWER_IS_STRING_CI ANSWER_IS_STRING_CS
3222: ANSWER_IS_CHOICE
3223: */
3224: result = 1; /* only one answer */
3225: if( type == ANSWER_IS_FLOAT ) {
3226: target = (double)atof(input);
3227: sprintf(fmted, fmt, target);
3228: leng = strlen(fmted)+1;
3229:
3230: strcpy(lower, fmted);
3231: } else { /* could be integer, choice, string ci, string cs */
3232: strcpy(lower, input);
3233: }
3234: } else { /* we have tolerence */
3235:
3236: target = (double)atof(input);
3237: switch( tol_type ) {
3238: case TOL_ABSOLUTE:
3239: fmted_target = target; /* if answer type is integer */
3240: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
3241: sprintf(fmted, fmt, target);
3242: fmted_target = (double)atof(fmted);
3243: }
3244: tol = fabs(tol); /* tol must be positive */
3245: if( calc_type == CALC_FORMATED) {
3246: target_l = fmted_target - tol; target_u = fmted_target + tol;
3247: } else {
3248: target_l = target - tol; target_u = target + tol;
3249: }
3250: if(type == ANSWER_IS_FLOAT) {
3251: sprintf(fmted, fmt, target_l ); strcpy(lower, fmted);
3252: sprintf(fmted, fmt, target_u ); strcpy(upper, fmted);
3253: } else {
3254: sprintf(fmted, "%.15g", target_l ); strcpy(lower, fmted);
3255: sprintf(fmted, "%.15g", target_u ); strcpy(upper, fmted);
3256: }
3257: break;
3258: case TOL_PERCENTAGE:
3259: if( target != 0.0 ) {
3260: ratio = (double)(tol / 100.0);
3261: fmted_target = target; /* if answer type is integer */
3262: if( type == ANSWER_IS_FLOAT) { /* format the exact answer as specified */
3263: sprintf(fmted, fmt, target);
3264: fmted_target = (double)atof(fmted);
3265: }
3266: delta = (double)fabs((double)ratio*target);
3267: if( calc_type == CALC_FORMATED) {
3268: target_l = fmted_target - delta; target_u = fmted_target + delta;
3269: } else {
3270: target_l = target - delta; target_u = target + delta;
3271: }
3272: if( target_l > target_u ) { tmp = target_u; target_u = target_l; target_l = tmp; }
3273: if(type == ANSWER_IS_FLOAT) {
3274: sprintf(fmted, fmt, target_l ); strcpy(lower, fmted);
3275: sprintf(fmted, fmt, target_u ); strcpy(upper, fmted);
3276: } else {
3277: sprintf(fmted, "%.15g", target_l ); strcpy(lower, fmted);
3278: sprintf(fmted, "%.15g", target_u ); strcpy(upper, fmted);
3279: }
3280: } else { strcpy(lower, "0.0"); strcpy(upper, "0.0"); result = 1;}
3281: break;
3282: }
3283: }
3284: }
3285:
3286: return (result);
3287: }
3288:
3289: /* Algorithms : check ALL units first */
3290: /* sig figs second */
3291: /* numerical, string comparisons last */
3292: /* result from capa_check_ans() could be */
3293:
3294: /* New check answers routine checks the /AND and /OR group of answers */
3295: /* use array of char pointers char **a */
3296: int
3297: capa_check_answers(p,answers,cnt) Problem_t *p; char **answers; int cnt;
3298: {
3299: AnswerInfo_t *ai;
3300: int ii, done, result;
3301: int *outcomes;
3302:
3303: if(p->ans_op == ANS_AND) { /* ans /and ans */
3304: if( (cnt != p->ans_cnt) ) { return (ANS_CNT_NOT_MATCH); }
3305: if( cnt == 1 ) { return (capa_check_answer(p, answers[0])); } /* there is only one answer */
3306: outcomes = (int *)capa_malloc(sizeof(int),cnt);
3307: for(ii=0;ii<cnt;ii++) outcomes[ii]=0; /* initialize the outcomes array */
3308: outcomes[0] = capa_check_answer(p, answers[0]);
3309: for(ii=1, ai = p->ans_list; ai; ii++,ai = ai->ans_next ) {
3310: outcomes[ii] = capa_check_ans(ai,answers[ii]);
3311: }
3312: done = ii = 0;
3313: result = 0;
3314: while( !done ) { /* check if any of the outcome has failed on units */
3315: if( (outcomes[ii] == UNIT_FAIL) ||
3316: (outcomes[ii] == NO_UNIT) ||
3317: (outcomes[ii] == UNIT_NOTNEEDED) ) {
3318: result = outcomes[ii];
3319: done = 1;
3320: }
3321: ii++;
3322: if(ii==cnt) done = 1;
3323: }
3324: if( result == 0 ) { /* check if any of the outcome has failed on sig figs */
3325: done = ii = 0;
3326: while( !done ) {
3327: if( outcomes[ii] == SIG_FAIL ) {
3328: result = outcomes[ii];
3329: done = 1;
3330: }
3331: ii++;
3332: if(ii==cnt) done = 1;
3333: }
3334: }
3335: if( result == 0 ) { /* check if any of the outcome is incorrect */
3336: done = ii = 0;
3337: while( !done ) {
3338: if( outcomes[ii] == INCORRECT ) {
3339: result = outcomes[ii];
3340: done = 1;
3341: }
3342: ii++;
3343: if(ii==cnt) done = 1;
3344: }
3345: }
3346: capa_mfree((char *)outcomes);
3347: if( result == 0 ) {
3348: result = APPROX_ANS; /* all answers are correct */
3349: }
3350: } else { /* should be ANS_OR , user answer count should always be 1 */
3351: if( cnt != 1 ) { return (ANS_CNT_NOT_MATCH); }
3352: if( p->ans_cnt == 1 ) { return (capa_check_answer(p, answers[0])); }
3353: result = capa_check_answer(p, answers[0]);
3354: ii = 1; ai = p->ans_list;
3355: while( (ii<p->ans_cnt) && ( (result != EXACT_ANS) && (result != APPROX_ANS) ) ) {
3356: result = capa_check_ans(ai,answers[0]);
3357: ai = ai->ans_next; ii++;
3358: }
3359: }
3360: return (result);
3361: }
3362:
3363:
3364:
3365:
3366:
3367:
3368:
3369:
3370: /* ========================================================================= */
3371: int w_getclassdir(cpath_p, cown_p, class)
3372: char **cpath_p; char **cown_p; char *class;
3373: {
3374: FILE *fp;
3375: char filename[SMALL_LINE_BUFFER];
3376: char *cname_p;
3377: int done;
3378: char c;
3379:
3380: sprintf(filename,"class.conf");
3381: if ((fp=fopen(filename,"r"))==NULL) {
3382: sprintf(filename,"../class.conf");
3383: if ((fp=fopen(filename,"r"))==NULL) {
3384: printf("Error: can't open %s\n",filename);
3385: exit (1);
3386: }
3387: }
3388: do {
3389: c_ignorewhite(fp);
3390: c = getc(fp); ungetc(c,fp);
3391: if( c != EOF ) {
3392: cname_p = c_getword(fp);
3393: *cpath_p = c_getword(fp);
3394: *cown_p = c_getword(fp);
3395: throwaway_line(fp);
3396: if( ! strcasecmp(cname_p, class) ) {
3397: done = 1;
3398: } else {
3399: free(cname_p); free(*cpath_p); free(*cown_p);
3400: done = 0;
3401: }
3402: } else {
3403: done = 1;
3404: }
3405: } while ( ! done );
3406: fclose(fp);
3407: free(cname_p);
3408: return (1);
3409: }
3410:
3411: /* ----------------------------------------------------------------- */
3412: /* read_capa_config gets a value out of the capa.config file
3413: in the read resultant string all " are removed expect for \" occurances"
3414: in fact all case of \ then another character become just the last
3415: character
3416:
3417: inputs : key_word - a string that is searched for on the lefthand side
3418: of an equals sign
3419: outputs : value - a char pointer that the value of the key_word as defined
3420: in the config file is copied into
3421: return : -1 - unable to find or acces the capa.config file
3422: 0 - the requested keyword was not found
3423: >0 - length of the string that was returned in value
3424: */
3425: /* ----------------------------------------------------------------- */
3426: int read_capa_config(key_word,value)
3427: char *key_word;char *value;
3428: {
3429: FILE *fp;
3430: char filename[SMALL_LINE_BUFFER];
3431: char left[MAX_BUFFER_SIZE],right[MAX_BUFFER_SIZE],c;
3432: int failed=0,done=0,num=0,result=-1,found=0,returnVal=0,i,j;
3433:
3434: sprintf(filename,"capa.config");
3435: if ((fp=fopen(filename,"r"))==NULL) {
3436: return (-1);
3437: }
3438: do {
3439: num = fscanf(fp,"%[^ \n\t#] = %[^\n]",left,right);
3440: if (num == 2) { result = strcasecmp(left,key_word); }
3441: if (result==0) { done=1; }
3442: if (num==EOF) { failed=1; }
3443: if (num!=2) {
3444: found=0;
3445: while(1) {
3446: c=fgetc(fp);
3447: if (found) {
3448: if (c!='\n') {
3449: ungetc(c,fp);
3450: break;
3451: }
3452: }
3453: if (c=='\n') found=1;
3454: if (((char)c)==((char)EOF)) break;
3455: }
3456: }
3457: } while (!done && !failed);
3458:
3459: fclose(fp);
3460:
3461: if (done) {
3462: for(i=0,j=0;i<(strlen(right)+1);i++) {
3463: value[j]='\0';
3464: if (right[i] == '\\' && (i < (strlen(right))) ) {
3465: i++;value[j]=right[i];j++;
3466: } else if (right[i] != '\"' ) {
3467: value[j]=right[i];j++;
3468: }
3469: }
3470: value[j]='\0';
3471: returnVal=j;
3472: }
3473: return returnVal;
3474: }
3475:
3476: int capa_access(const char *pathname, int mode)
3477: {
3478: pid_t euid,egid;
3479: struct stat status;
3480:
3481: euid=geteuid();
3482: egid=getegid();
3483: if ( -1 == stat(pathname,&status) ) { return -1; }
3484: /*printf("mode:%x F_OK:%x mode&F_OK:%x\n",mode,F_OK,(mode&F_OK));*/
3485: /*printf("st_mode:%x S_IFMT:%x st_mode&S_IFMT:%x\n",
3486: status.st_mode,S_IFMT,(status.st_mode&S_IFMT));*/
3487: if (!(status.st_mode & S_IFMT)) { return -1; }
3488: /*printf("euid: %d\t egid: %d\tstatus.st_uid: %d\tstatus.st_gid: %d\n",
3489: euid,egid,status.st_uid,status.st_gid);*/
3490: /*printf("mode:%x R_OK:%x mode&R_OK:%x\n",mode,R_OK,(mode&R_OK));*/
3491: /*printf("mode:%x W_OK:%x mode&W_OK:%x\n",mode,R_OK,(mode&R_OK));*/
3492: /*printf("mode:%x X_OK:%x mode&X_OK:%x\n",mode,R_OK,(mode&R_OK));*/
3493: if (euid==status.st_uid) {
3494: /*printf("here1\n");*/
3495: if ((mode & R_OK) && (!(status.st_mode & S_IRUSR))) { return -1; }
3496: if ((mode & W_OK) && (!(status.st_mode & S_IWUSR))) { return -1; }
3497: if ((mode & X_OK) && (!(status.st_mode & S_IXUSR))) { return -1; }
3498: } else {
3499: if (egid==status.st_gid) {
3500: /*printf("here2\n");*/
3501: if ((mode & R_OK) && (!(status.st_mode & S_IRGRP))) { return -1; }
3502: if ((mode & W_OK) && (!(status.st_mode & S_IWGRP))) { return -1; }
3503: if ((mode & X_OK) && (!(status.st_mode & S_IXGRP))) { return -1; }
3504: } else {
3505: /*printf("here3\n");*/
3506: if ((mode & R_OK) && (!(status.st_mode & S_IROTH))) { return -1; }
3507: if ((mode & W_OK) && (!(status.st_mode & S_IWOTH))) { return -1; }
3508: if ((mode & X_OK) && (!(status.st_mode & S_IXOTH))) { return -1; }
3509: }
3510: }
3511: return 0;
3512: }
3513:
3514: /*checks if the string is all whitespace*/
3515: /*returns 0 if it isn't */
3516: /*returns 1 if it is */
3517: int is_all_ws(char* answer)
3518: {
3519: int length,result=1,i;
3520: if (answer!=NULL) {
3521: length=strlen(answer);
3522: for(i=0;i<length;i++) {
3523: if (!isspace(answer[i])) {result=0;break;}
3524: }
3525: }
3526: return result;
3527: }
3528:
3529: void trim_response_ws(char* answer)
3530: {
3531: char *temp;
3532: int i,j=0,length;
3533: length=strlen(answer);
3534: temp=capa_malloc(length+1,1);
3535: strcpy(temp,answer);
3536: for(i=0; i<length;i++) if (!(isspace(temp[i]))) break;
3537: for(j=length-1;j>=0;j--) if (!(isspace(temp[j]))) break;
3538: temp[++j]='\0';
3539: strcpy(answer,&temp[i]);
3540: }
3541:
3542: void throwaway_line(FILE* fp)
3543: {
3544: int c;
3545: do {
3546: c = getc(fp);
3547: } while ( (c != '\n') && (c != EOF) );
3548: }
3549:
3550: char* capa_get_seat(char* studentnum,char* seatfile)
3551: {
3552: FILE* fp;
3553: T_student student;
3554: char *result,*defaultseatfile="seatingchart";
3555: char line[TMP_LINE_LENGTH],*lineend;
3556: int stuline=0,seatline=0;
3557:
3558: stuline = capa_get_student(studentnum,&student);
3559: if (stuline < 1 ) goto error;
3560: if (seatfile == NULL) seatfile=defaultseatfile;
3561: if ((fp=fopen(seatfile,"r"))==NULL) goto error;
3562: while( (stuline>seatline) && (fgets(line,TMP_LINE_LENGTH-1,fp)) ) seatline++;
3563: if (seatline< stuline) goto error;
3564: if ((lineend=index(line,' '))!=NULL) lineend='\0';
3565: result=capa_malloc(strlen(line)+1,1);
3566: strcpy(result,line);
3567: return result;
3568:
3569: error:
3570: result= capa_malloc(8,1);
3571: sprintf(result,"No Seat");
3572: return result;
3573:
3574: }
3575:
3576: void protect_log_string(char* log_string)
3577: {
3578: int i,len=strlen(log_string);
3579: for(i=0;i<len;i++) {
3580: switch (log_string[i]) {
3581: case '\n': case '\t': case '\r':
3582: log_string[i]=' ';
3583: break;
3584: }
3585: }
3586: }
3587:
3588: int capa_get_login_time(char *student_number,int set,time_t *logintime)
3589: {
3590: FILE *fp;
3591: int found,temp=0;
3592: char filename[FILE_NAME_LENGTH],line[SMALL_LINE_BUFFER];
3593:
3594: *logintime=0;
3595: sprintf(filename,"records/access%d.log",set);
3596:
3597: if ((fp=fopen(filename,"r"))==NULL) return (-1);
3598: found = 0;
3599: while( (!found) && ( fgets(line,SMALL_LINE_BUFFER-1,fp) != NULL) ) {
3600: if( !strncasecmp(line,student_number,MAX_STUDENT_NUMBER) ) found = 1;
3601: }
3602: fclose(fp);
3603: if (found) sscanf(rindex(line,':'),":%d",&temp);
3604: *logintime=(time_t)temp;
3605: return found;
3606: }
3607:
3608: /*----------------------------------------------------------*/
3609: /* INPUT: set the X in logX.db */
3610: /* OUTPUT: creates the accessX.log file if it doesn't exist */
3611: /* and inserts stunum:time(NULL) if stunum isn't */
3612: /* in ther already. */
3613: /* */
3614: /* RETURN: -1 file error */
3615: /* 0 already set */
3616: /* 1 succesfully logged a login time */
3617: /*----------------------------------------------------------*/
3618: int capa_set_login_time(char *student_number,int set)
3619: {
3620: FILE *fp;
3621: int errcode=0;
3622: int found=0;
3623: char filename[FILE_NAME_LENGTH],line[SMALL_LINE_BUFFER];
3624:
3625: sprintf(filename,"records/access%d.log",set);
3626:
3627: if ((fp=fopen(filename,"r"))!=NULL) {
3628: while( (!found) && ( fgets(line,SMALL_LINE_BUFFER-1,fp) != NULL) ) {
3629: if( !strncasecmp(line,student_number,MAX_STUDENT_NUMBER) ) found = 1;
3630: }
3631: fclose(fp);
3632: }
3633:
3634: if (found) return 0;
3635:
3636: sprintf(line,"%s:%d\n", student_number,(int)time(NULL));
3637: if ((fp=fopen(filename,"a+"))==NULL) return (-1);
3638: flockstream(fp);
3639: fseek(fp,0L,SEEK_END);
3640: if ( !fwrite((char *)line, strlen(line), 1, fp) ) {
3641: errcode = -1;
3642: } else {
3643: errcode = 1;
3644: }
3645: fflush(fp);
3646: funlockstream(fp);
3647: fclose(fp);
3648: return (errcode);
3649: }
3650: /* =||>|===================== End of capaCommon.c =====================|<||= */
3651:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>