]> andersk Git - moira.git/blob - clients/mailmaint/mailmaint.c
strsave is now part of the sms library.
[moira.git] / clients / mailmaint / mailmaint.c
1 /*
2  *      $Source$
3  *      $Header$
4  */
5
6 #ifndef lint
7 static char rcsid_mailmaint_c[] = "$Header$";
8
9 #endif lint
10
11 /***********************************************************************/
12 /*  mailmaint.c - pjlevine - 20 August 1987 
13     
14 */
15 /***********************************************************************/
16 #include <stdio.h>
17 #include <pwd.h>
18 #include <menu.h>
19 #include <signal.h>
20 #include <strings.h>
21 #include <curses.h>
22 #include <sys/types.h>
23 #include <ctype.h>
24 #include "mit-copyright.h"
25
26 #define STARTCOL 0
27 #define STARTROW 3
28 #define SECONDCOL 30
29 #define DISPROW 15
30 #define LISTMAX 50
31 #define LISTSIZE 32
32 #define CTL(ch)  ((ch) & 037)
33 #define MAX(A,B) ((A) > (B) ? (A) : (B))
34
35 static char *whoami;
36 static int status;
37 static void scream();
38 char *ds();
39
40 typedef struct list_info {
41     char *acl;
42     char *desc;
43     char *expdate;
44 }         List_info;
45
46 static char *ascbuff = {"0123456789"};
47 static int 
48 print_2(), print_1();
49 static List_info *current_li = (List_info *) NULL;
50 static int get_list_info();
51 static int fetch_list_info();
52
53 char *malloc();
54 char *rindex();
55 char *getlogin();
56 extern char *strsave();
57 char *getenv();
58 char *calloc();
59
60 uid_t getuid();
61
62 typedef struct _menu {
63     int num_items;
64     char *title;
65     char **items;
66 }     MENU;
67
68 MENU *main_menu, *help_menu;
69
70 int position[2], oldpos[2];
71 int level, found_some, currow, page, num_members;
72 int moreflg, toggle, first_time;
73 char *uname;
74
75
76 /****************************************************/
77 /*ARGSUSED*/
78 main(argc, argv)
79     int argc;
80     char *argv[];
81
82 {
83
84     int use_menu = 1;
85     char buf[BUFSIZ];
86
87     init_sms_err_tbl();
88     init_krb_err_tbl();
89
90     if ((whoami = rindex(argv[0], '/')) == NULL)
91         whoami = argv[0];
92     else
93         whoami++;
94     uname = calloc(20, 1);
95     if ((current_li = (List_info *) malloc(sizeof(List_info)))
96         == (List_info *) NULL) {
97         (void) sprintf(buf, ": allocating list info");
98         goto punt;
99     }
100     else {
101         current_li->acl = (char *) NULL;
102         current_li->desc = (char *) NULL;
103         current_li->expdate = (char *) NULL;
104     }
105     if ((uname = getlogin()) == NULL) {
106         struct passwd *getpwuid();
107
108         uname = getpwuid((int) getuid())->pw_name;
109     }
110     uname = (uname && strlen(uname)) ? ds(uname) : "";
111
112     printf("Connecting to database for %s...please hold on.\n", uname);
113
114     status = sms_connect();
115     if (status) {
116         (void) sprintf(buf, "\nConnection to SMS server failed");
117         goto punt;
118     }
119
120     status = sms_auth();
121     if (status) {
122         (void) sprintf(buf, "\nAuthorization failed.\n");
123         goto punt;
124     }
125
126     if (use_menu) {
127         (void) initscr();
128         if ((LINES < 24) || (COLS < 60)) {
129             Put_message("Display window too small.\n\n");
130             (void) sprintf(buf, "Current window parameters are (%d \
131 lines, %d columns)\n", LINES, COLS);
132             Put_message(buf);
133             Put_message("Please resize your window\n");
134             Put_message("to at least 24 lines and 60 columns.\n");
135             exit(0);
136         }
137         raw();
138         noecho();
139         position[0] = oldpos[0] = 1;
140         level = 0;
141         pack_main_menu();
142         pack_help_menu();
143         display_menu(main_menu);
144         get_main_input();
145         cls();
146         endwin();
147     }
148     exit(0);
149
150 punt:
151     com_err(whoami, status, buf);
152     exit(1);
153 }
154
155 /****************************************************/
156 get_main_input()
157 {
158     int c;
159     int retflg;
160
161     while (1) {
162         oldpos[level] = position[level];
163         retflg = 0;
164         currow = DISPROW + 2;
165         page = 1;
166         toggle = num_members = moreflg = 0;
167         c = getchar();
168         if (c == 13) {
169             if (position[level] == 7)
170                 c = 'q';
171             else
172                 c = ascbuff[position[level]];
173             retflg = 1;
174         }
175         switch (c) {
176         case 'L' & 037: /* clear screen */
177             display_menu(main_menu);
178             break;
179         case 'q':
180         case 'Q':               /* quit */
181             position[level] = 7;
182             highlight(main_menu);
183             if (retflg) {
184                 cls();
185                 return;
186             }
187             break;
188         case '1':               /* show all lists */
189             position[level] = 1;
190             if (retflg) {
191                 show_all();
192             }
193             break;
194         case '2':               /* get all members of a list */
195             position[level] = 2;
196             if (retflg) {
197                 (void) list_members();
198             }
199             break;
200         case '3':               /* display list which user is a recipient */
201             position[level] = 3;
202             if (retflg) {
203                 list_by_member();
204             }
205             break;
206         case '4':               /* show description */
207             position[level] = 4;
208             if (retflg) {
209                 show_list_info();
210             }
211             break;
212         case '5':               /* add to list */
213             position[level] = 5;
214             if (retflg) {
215                 add_member();
216             }
217             break;
218         case '6':               /* delete */
219             position[level] = 6;
220             if (retflg) {
221                 delete_member();
222             }
223             break;
224         case 27:                /* up arrow */
225             c = getchar();
226             if (c == 91) {
227                 c = getchar();
228                 if (c == 65) {
229                     position[level]--;
230                     if (!position[level])
231                         position[level] = 7;
232                 }
233                 else {
234                     if (c == 66) {
235                         position[level]++;
236                         if (position[level] > 7)
237                             position[level] = 1;
238                     }
239                 }
240             }
241             break;
242         default:
243             printf("%c", 7);
244             break;
245         }
246         highlight(main_menu);
247     }
248 }
249
250 /****************************************************/
251 show_list_info()
252 {
253     char *buf;
254     char c;
255
256     show_text(DISPROW, STARTCOL, "Show information about a list.\n\r");
257     buf = calloc((unsigned)1024, 1);
258     if (Prompt("Enter List Name: ", buf, LISTSIZE) == 1) {
259         Put_message("\n\r");
260         if (fetch_list_info(buf, current_li) == 0) {
261             (void) sprintf(buf, "Description: %s\n\r", current_li->desc);
262             if (strlen(buf) > 60)
263                 (void) display_buff(buf);
264             else
265                 show_text(currow, STARTCOL, buf);
266             currow++;
267             (void) sprintf(buf, "List Administrator: %s", current_li->acl);
268             show_text(currow, STARTCOL, buf);
269             currow++;
270             (void) sprintf(buf, "Expiration date: %s", current_li->expdate);
271             show_text(currow, STARTCOL, buf);
272             currow++;
273         }
274         else {
275             show_text(currow, STARTCOL, "madm: No such list found.");
276             currow++;
277         }
278         show_text(currow, STARTCOL, "Press any Key to continue...");
279         (void) getchar();
280     }
281     clrwin(DISPROW);
282 }
283
284 /****************************************************/
285 display_buff(buf)
286     char *buf;
287 {
288     int i, cnt;
289     char *printbuf;
290     int maxcol;
291
292     maxcol = COLS;
293     if (maxcol >= 80)
294         maxcol = 80;
295
296     cnt = 0;
297     printbuf = calloc((unsigned)maxcol, 1);
298     for (i = 0; i <= strlen(buf); i++) {
299         printbuf[cnt] = buf[i];
300         cnt++;
301         if (cnt >= maxcol) {
302             (void) start_display_buff(printbuf);
303             cnt = 0;
304             free(printbuf);
305             printbuf = calloc((unsigned)maxcol, 1);
306         }
307     }
308     if (strlen(buf) % maxcol != 0) {
309         (void) start_display_buff(printbuf);
310         free(printbuf);
311     }
312     return (0);
313 }
314
315 /****************************************************/
316 start_display_buff(buff)
317     char *buff;
318 {
319     char buffer[5];
320
321     num_members++;
322     if (moreflg)
323         return (0);
324     if (currow >= LINES - 2) {
325         page++;
326         currow++;
327         mvcur(0, 0, currow, STARTCOL);
328         refresh();
329         if (Prompt("--RETURN for more, ctl-c to exit--", buffer, 1) == 0) {
330             Put_message("Flushing query...");
331             moreflg = 1;
332             return (0);
333         }
334         clrwin(DISPROW + 2);
335         currow = DISPROW + 2;
336         show_text(currow, STARTCOL, "continued");
337         currow++;
338     }
339     show_text(currow, STARTCOL, buff);
340     currow++;
341     return (0);
342 }
343
344 /****************************************************/
345 add_member()
346 {
347     static char *argv[] = {
348         "add_member_to_list",
349         0,
350         0,
351         0
352         };
353     char *buf;
354     char c;
355
356     show_text(DISPROW, STARTCOL, "Add yourself to a list\n\r");
357     buf = calloc(LISTMAX, 1);
358     if (Prompt("Enter List Name: ", buf, LISTSIZE) == 1) {
359         Put_message("\r\n");
360         argv[1] = strsave(buf);
361         argv[2] = strsave("user");
362         argv[3] = strsave(uname);
363         if (status = sms_query_internal(3, argv, scream, (char *) NULL)) {
364             Put_message("\r\n");
365             com_err(whoami, status, " found.\n");
366         }
367         else {
368             (void) sprintf(buf, "User %s added to list\r", uname);
369             show_text(DISPROW + 3, STARTCOL, buf);
370         }
371         currow = DISPROW + 4;
372         show_text(DISPROW + 4, STARTCOL, "Press any Key to continue...");
373         (void) getchar();
374     }
375     clrwin(DISPROW);
376 }
377
378 /****************************************************/
379 delete_member()
380 {
381     static char *argv[] = {
382         "delete_member_from_list",
383         0,
384         0,
385         0
386         };
387     char *buf;
388     char c;
389
390     show_text(DISPROW, STARTCOL, "Remove yourself from a list\n\r");
391     buf = calloc(LISTMAX, 1);
392     if (Prompt("Enter List Name: ", buf, LISTSIZE) == 1) {
393         Put_message("\r\n");
394         argv[1] = strsave(buf);
395         argv[2] = strsave("user");
396         argv[3] = strsave(uname);
397         if (status = sms_query_internal(3, argv, scream, (char *) NULL)) {
398             Put_message("\r\n");
399             com_err(whoami, status, " found.\n");
400         }
401         else {
402             (void) sprintf(buf, "User %s deleted from list\r", uname);
403             show_text(DISPROW + 3, STARTCOL, buf);
404         }
405         currow = DISPROW + 4;
406         show_text(DISPROW + 4, STARTCOL, "Press any Key to continue...");
407         (void) getchar();
408     }
409     clrwin(DISPROW);
410 }
411
412 /****************************************************/
413 list_by_member()
414 {
415     char *nargv[3];
416     char *buf;
417     char c;
418
419     nargv[1] = strsave("user");
420     nargv[2] = strsave(uname);
421     buf = calloc(BUFSIZ, 1);
422     (void) sprintf(buf, "%s is on the following lists:\r", uname);
423     show_text(DISPROW, STARTCOL, buf);
424     mvcur(0, 0, currow, STARTCOL);
425     refresh();
426     if (status = sms_query("get_lists_of_member", 2, nargv + 1,
427                            print_1, (char *) NULL)) {
428         Put_message("\r\n");
429         com_err(whoami, status, " in get_lists_of_member");
430     }
431     show_text(currow, STARTCOL, "Press any Key to continue...");
432     (void) getchar();
433     clrwin(DISPROW);
434     return;
435 }
436
437 /****************************************************/
438 show_all()
439 {
440     char c;
441
442     show_text(DISPROW, STARTCOL, "This function may take a while...proceed[y]?");
443     c = getchar();
444     if (c == 'n' || c == 'N') {
445         erase_line(DISPROW, STARTCOL);
446         return;
447     }
448     move(DISPROW + 1, STARTCOL);
449     addstr("Processing query...please hold");
450     refresh();
451     (void) list_all_groups();
452 }
453
454 /****************************************************/
455 /*ARGSUSED*/
456 static int
457 print_1(argc, argv, callback)
458     int argc;
459     char *argv[], *callback;
460 {
461     char buf[BUFSIZ];
462
463     /* no newline 'cause Put_message adds one */
464     (void) sprintf(buf, "%s\r", argv[0]);
465     (void) start_display(buf);
466
467     return (0);
468 }
469
470 /****************************************************/
471 /*ARGSUSED*/
472 static int
473 print_all(argc, argv, callback)
474     int argc;
475     char *argv[], *callback;
476 {
477     char buf[BUFSIZ];
478
479     if (moreflg)
480         return (0);
481     if (first_time) {
482         erase_line(DISPROW + 1, STARTCOL);
483         show_text(DISPROW + 1, STARTCOL, "All mailing lists:");
484         first_time = 0;
485     }
486     (void) sprintf(buf, "%s\r", argv[0]);
487     (void) start_display(buf);
488
489     return (0);
490 }
491
492 /****************************************************/
493 list_all_groups()
494 {
495
496     first_time = 1;
497     if (status = sms_query("get_all_visible_maillists", 0, (char **) NULL,
498                            print_all, (char *) NULL)) {
499         Put_message("\r\n");
500         com_err(whoami, status, " in list_all_groups\n");
501     }
502     end_display();
503
504     return (DM_NORMAL);         /* HA! */
505 }
506
507 /****************************************************/
508 list_members()
509 {
510     char *argv[1];
511     char *buf;
512     char buffer[80];
513
514     found_some = 0;
515     move(DISPROW, STARTCOL);
516     mvcur(0, 0, DISPROW, STARTCOL);
517     refresh();
518     buf = calloc(LISTMAX, 1);
519     if (Prompt("Enter List Name: ", buf, LISTSIZE) == 1) {
520         (void) sprintf(buffer, "The members of list '%s' are:", buf);
521         show_text(DISPROW + 1, STARTCOL, buffer);
522         argv[0] = buf;
523         if (status = sms_query("get_members_of_list", 1, argv,
524                                print_2, (char *) NULL)) {
525             Put_message("\r\n");
526             com_err(whoami, status, " found.\n");
527             currow++;
528         }
529         if (!found_some) {
530             show_text(currow, STARTCOL, "List is empty (no members).");
531             currow++;
532         }
533         end_display();
534         return(0);
535     }
536     clrwin(DISPROW);
537     return (DM_NORMAL);         /* HA! */
538 }
539
540 /****************************************************/
541 /*ARGSUSED*/
542 static int
543 print_2(argc, argv, callback)
544     int argc;
545     char *argv[], *callback;
546 {
547     char buf[BUFSIZ];
548
549     found_some = 1;
550     (void) sprintf(buf, "%s %s", argv[0], argv[1]);
551     (void) start_display(buf);
552
553     return (0);
554 }
555
556 /****************************************************/
557 start_display(buff)
558     char *buff;
559 {
560     char *buffer;
561
562     num_members++;
563     if (moreflg)
564         return(0);
565     buffer = calloc(50, 1);
566     if (currow >= LINES - 2) {
567         page++;
568         currow++;
569         mvcur(0, 0, currow, STARTCOL);
570         refresh();
571         if (Prompt("--RETURN for more, ctl-c to exit--", buffer, 1) == 0) {
572             Put_message("Flushing query...");
573             moreflg = 1;
574             return (0);
575         }
576         clrwin(DISPROW + 2);
577         currow = DISPROW + 2;
578         (void) sprintf(buffer, "Continued (Page %d)", page);
579         show_text(currow, STARTCOL, buffer);
580         currow++;
581         toggle = 0;
582     }
583     if (!toggle)
584         show_text(currow, STARTCOL, buff);
585     else {
586         show_text(currow, SECONDCOL, buff);
587         currow++;
588     }
589     toggle = !toggle;
590     return(0);
591 }
592
593 /****************************************************/
594 end_display()
595 {
596     char *buffer, c;
597
598     if (moreflg) {
599         clrwin(DISPROW);
600         return;
601     }
602
603     buffer = calloc(50, 1);
604     currow++;
605     (void) sprintf(buffer, "End of List. %d Total Members\r", num_members);
606     show_text(currow, STARTCOL, buffer);
607     currow++;
608     show_text(currow, STARTCOL, "Press any key to continue...");
609     (void) getchar();
610     clrwin(DISPROW);
611
612 }
613
614 /****************************************************/
615 display_menu(menu)
616     MENU *menu;
617 {
618     int i;
619
620     cls();
621     title(menu->title);
622     mvcur(0, 0, STARTROW, STARTCOL);
623     refresh();
624     for (i = 0; i <= menu->num_items - 1; i++) {
625         move(STARTROW + i, STARTCOL);
626         standend();
627         addstr(menu->items[i]);
628         refresh();
629     }
630     center_text(STARTROW + menu->num_items + 2,
631                 "Enter a number, <up arrow>, or <down arrow>.");
632     if (!level)
633         center_text(STARTROW + menu->num_items + 3,
634                     "Press 'q' to exit, <return> to confirm choice.");
635     else
636         center_text(STARTROW + menu->num_items + 3,
637         "Press 'q' to exit, 'r' for main menu, <return> to confirm choice.");
638
639     if (!level)
640         highlight(main_menu);
641 }
642
643 /****************************************************/
644 pack_main_menu()
645 {
646     char *buf;
647
648     main_menu = (MENU *) malloc((unsigned) sizeof(MENU));
649     main_menu->num_items = 7;
650     main_menu->items = (char **) malloc((unsigned) sizeof(char *) * main_menu->num_items);
651
652     buf = calloc(50, 1);
653     (void) sprintf(buf, "Mail List Program for %s", uname);
654     main_menu->title = strsave(buf);
655     main_menu->items[0] = strsave("1.  Show all mailing lists.");
656     main_menu->items[1] = strsave("2.  Get all members of a mailing list.");
657     main_menu->items[2] = strsave("3.  Display lists of which you are a member.");
658     main_menu->items[3] = strsave("4.  Show description of list.");
659     main_menu->items[4] = strsave("5.  Add yourself to a mailing list.");
660     main_menu->items[5] = strsave("6.  Delete yourself from a mailing list.");
661     main_menu->items[6] = strsave("q.  Quit.");
662 }
663
664 /****************************************************/
665 pack_help_menu()
666 {
667     help_menu = (MENU *) malloc((unsigned) sizeof(MENU));
668     help_menu->num_items = 5;
669     help_menu->items = (char **) malloc((unsigned) sizeof(char *) * help_menu->num_items);
670
671     help_menu->title = strsave("madm is designed as a basic mail list administration program.");
672     help_menu->items[0] = strsave("if you need to perform more advanced list manipulation like");
673     help_menu->items[1] = strsave("adding lists, or changing list characteristics, refer to the");
674     help_menu->items[2] = strsave("program listmaint.");
675     help_menu->items[3] = strsave(" ");
676     help_menu->items[4] = strsave("Press any key to continue.");
677 }
678
679 /****************************************************/
680 highlight(menu)
681     MENU *menu;
682 {
683
684
685     if (oldpos[level] != position[level]) {
686         move(STARTROW + oldpos[level] - 1, STARTCOL);
687         standend();
688         addstr(menu->items[oldpos[level] - 1]);
689         refresh();
690     }
691
692     move(STARTROW + position[level] - 1, STARTCOL);
693     standout();
694     addstr(menu->items[position[level] - 1]);
695     refresh();
696     standend();
697     refresh();
698 }
699
700 /****************************************************/
701 title(buff)
702     char *buff;
703 {
704     move(0, MAX(0, (COLS - strlen(buff)) >> 1));
705     standout();
706     addstr(buff);
707     refresh();
708     standend();
709 }
710
711 /****************************************************/
712 center_text(row, buff)
713     int row;
714     char *buff;
715 {
716     move(row, MAX(0, (COLS - strlen(buff)) >> 1));
717     addstr(buff);
718     refresh();
719 }
720
721 /****************************************************/
722 show_text(row, col, buff)
723     int row, col;
724     char *buff;
725 {
726     mvcur(0, 0, row, col);
727     refresh();
728     printf("%s", buff);
729 }
730
731 /****************************************************/
732 erase_line(row, col)
733     int row, col;
734 {
735     char *buff;
736     int i;
737
738     buff = calloc((unsigned)COLS, 1);
739     for (i = 0; i <= COLS - 2; i++)
740         buff[i] = ' ';
741     buff[i] = 0;                /* just to be sure ! */
742     move(row, col);
743     mvcur(0, 0, row, col);
744     printf("%s", buff);
745     refresh();
746 }
747
748 /****************************************************/
749 cls()
750 {
751     clear();
752     refresh();
753 }
754
755 /****************************************************/
756 clrwin(erase_row)
757     int erase_row;
758 {
759     int i;
760     char *buff;
761     int maxcol;
762
763     maxcol = COLS;
764     if (maxcol > 80)
765         maxcol = 80;            /* limit width */
766
767     buff = calloc((unsigned)maxcol + 1, 1);
768     for (i = 0; i <= maxcol - 1; i++)
769         buff[i] = ' ';
770     buff[i] = 0;                /* just to be sure ! */
771     mvcur(0, 0, erase_row, STARTCOL);
772     refresh();
773     for (i = erase_row; i <= currow - 1; i++) {
774         printf("%s\n\r", buff);
775     }
776     printf("%s", buff);
777     mvcur(erase_row, STARTCOL, STARTROW + oldpos[level] - 1, STARTCOL);
778     refresh();
779 }
780
781 /****************************************************/
782
783 static void 
784 scream()
785 {
786     com_err(whoami, status, "\nAn SMS update returned a value -- programmer \
787 botch\n");
788     sms_disconnect();
789     exit(1);
790 }
791
792 /****************************************************/
793 /*ARGSUSED*/
794 static int 
795 fetch_list_info(list, li)
796     char *list;
797     List_info *li;
798 {
799     char *argv[1];
800
801     argv[0] = list;
802     if ((status = sms_query("get_list_info", 1, argv,
803                             get_list_info, (char *) NULL)) == 0) {
804         return status;
805     }
806     else {
807         com_err(whoami, status, " found.\n");
808         return status;
809     }
810 }
811
812 /* ARGSUSED */
813 static int 
814 get_list_info(argc, argv)
815     int argc;
816     char **argv;
817 {
818
819     if (current_li->acl)
820         free(current_li->acl);
821     current_li->acl = strsave(argv[2]);
822     if (current_li->desc)
823         free(current_li->desc);
824     current_li->desc = strsave(argv[3]);
825     if (current_li->expdate)
826         free(current_li->expdate);
827     current_li->expdate = strsave(argv[4]);
828     return (0);
829 }
830
831
832
833
834 /****************************************************/
835 /* Prompt the user for input */
836 int 
837 Prompt(prompt, buf, buflen)
838     char *prompt;
839     char *buf;
840     int buflen;
841 {
842     int c;
843     char *p;
844     int x, oldx;
845
846     printf("%s", prompt);
847     refresh();
848     for (p = buf; abs(strlen(p) - strlen(buf)) <= buflen;) {
849         refresh();
850         c = getchar();
851         switch (c) {
852         case CTL('C'):
853             return 0;
854         case CTL('Z'):
855             return 0;
856         case CTL('L'):
857             cls();
858             display_menu(main_menu);
859             return (0);
860         case '\n':
861         case '\r':
862             Put_message("\r");
863             *p = '\0';
864             if (strlen(buf) < 1)/* only \n or \r in buff */
865                 return (-1);
866             else
867                 return (1);
868         case '\b':
869         case '\177':
870             if (p > buf) {
871                 p--;
872                 x--;
873                 Put_message("\b");
874                 Put_message(" ");
875                 Put_message("\b");
876             }
877             break;
878         case CTL('U'):
879         case CTL('G'):
880         case CTL('['):
881             x = oldx;
882             p = buf;
883             break;
884         default:
885             if (abs(strlen(p) - strlen(buf)) >= buflen) {
886                 printf("%c", 7);
887                 break;
888             }
889             if (isprint(c)) {
890                 (void) addch(c);
891                 *p++ = c;
892                 x++;
893             }
894             else
895                 (void) putchar(CTL('G'));
896             break;
897         }
898     }
899     return(0);
900 }
901
902 /*
903  * duplicate string 
904  */
905 char *
906 ds(str)
907     char *str;
908 {
909     register char *newstr = malloc((unsigned) strlen(str) + 1);
910
911     if (newstr == (char *) NULL)
912         return ((char *) NULL);
913     else
914         return (strcpy(newstr, str));
915 }
916
917 /*
918  * Local Variables:
919  * mode: c
920  * c-indent-level: 4
921  * c-continued-statement-offset: 4
922  * c-brace-offset: -4
923  * c-argdecl-indent: 4
924  * c-label-offset: -4
925  * End: 
926  */
This page took 0.132395 seconds and 5 git commands to generate.